Split 5 oversized files (501-583 LOC each) into focused units all under 500 LOC: - license_policy.go → +_types.go (engine logic / type definitions) - models.go → +_intake.go, +_assessment.go (enums+domains / intake structs / output+DB types) - pdf_export.go → +_markdown.go (PDF export / markdown export) - escalation_store.go → +_dsb.go (main escalation ops / DSB pool ops) - obligations_registry.go → +_grouping.go (registry core / grouping methods) All files remain in package ucca. Zero behavior changes. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
124 lines
3.5 KiB
Go
124 lines
3.5 KiB
Go
package ucca
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/google/uuid"
|
|
)
|
|
|
|
// ============================================================================
|
|
// DSB Pool Operations
|
|
// ============================================================================
|
|
|
|
// AddDSBPoolMember adds a member to the DSB review pool.
|
|
func (s *EscalationStore) AddDSBPoolMember(ctx context.Context, m *DSBPoolMember) error {
|
|
query := `
|
|
INSERT INTO ucca_dsb_pool (
|
|
id, tenant_id, user_id, user_name, user_email, role,
|
|
is_active, max_concurrent_reviews, created_at, updated_at
|
|
) VALUES (
|
|
$1, $2, $3, $4, $5, $6, $7, $8, NOW(), NOW()
|
|
)
|
|
ON CONFLICT (tenant_id, user_id) DO UPDATE
|
|
SET user_name = $4, user_email = $5, role = $6,
|
|
is_active = $7, max_concurrent_reviews = $8, updated_at = NOW()
|
|
`
|
|
|
|
if m.ID == uuid.Nil {
|
|
m.ID = uuid.New()
|
|
}
|
|
|
|
_, err := s.pool.Exec(ctx, query,
|
|
m.ID, m.TenantID, m.UserID, m.UserName, m.UserEmail, m.Role,
|
|
m.IsActive, m.MaxConcurrentReviews,
|
|
)
|
|
|
|
return err
|
|
}
|
|
|
|
// GetDSBPoolMembers retrieves active DSB pool members for a tenant.
|
|
func (s *EscalationStore) GetDSBPoolMembers(ctx context.Context, tenantID uuid.UUID, role string) ([]DSBPoolMember, error) {
|
|
query := `
|
|
SELECT id, tenant_id, user_id, user_name, user_email, role,
|
|
is_active, max_concurrent_reviews, current_reviews, created_at, updated_at
|
|
FROM ucca_dsb_pool
|
|
WHERE tenant_id = $1 AND is_active = true
|
|
`
|
|
args := []interface{}{tenantID}
|
|
|
|
if role != "" {
|
|
query += " AND role = $2"
|
|
args = append(args, role)
|
|
}
|
|
|
|
query += " ORDER BY current_reviews ASC, user_name ASC"
|
|
|
|
rows, err := s.pool.Query(ctx, query, args...)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
|
|
var members []DSBPoolMember
|
|
for rows.Next() {
|
|
var m DSBPoolMember
|
|
err := rows.Scan(
|
|
&m.ID, &m.TenantID, &m.UserID, &m.UserName, &m.UserEmail, &m.Role,
|
|
&m.IsActive, &m.MaxConcurrentReviews, &m.CurrentReviews, &m.CreatedAt, &m.UpdatedAt,
|
|
)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
members = append(members, m)
|
|
}
|
|
|
|
return members, nil
|
|
}
|
|
|
|
// GetNextAvailableReviewer finds the next available reviewer for a role.
|
|
func (s *EscalationStore) GetNextAvailableReviewer(ctx context.Context, tenantID uuid.UUID, role string) (*DSBPoolMember, error) {
|
|
query := `
|
|
SELECT id, tenant_id, user_id, user_name, user_email, role,
|
|
is_active, max_concurrent_reviews, current_reviews, created_at, updated_at
|
|
FROM ucca_dsb_pool
|
|
WHERE tenant_id = $1 AND is_active = true AND role = $2
|
|
AND current_reviews < max_concurrent_reviews
|
|
ORDER BY current_reviews ASC
|
|
LIMIT 1
|
|
`
|
|
|
|
var m DSBPoolMember
|
|
err := s.pool.QueryRow(ctx, query, tenantID, role).Scan(
|
|
&m.ID, &m.TenantID, &m.UserID, &m.UserName, &m.UserEmail, &m.Role,
|
|
&m.IsActive, &m.MaxConcurrentReviews, &m.CurrentReviews, &m.CreatedAt, &m.UpdatedAt,
|
|
)
|
|
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &m, nil
|
|
}
|
|
|
|
// IncrementReviewerCount increments the current review count for a DSB member.
|
|
func (s *EscalationStore) IncrementReviewerCount(ctx context.Context, userID uuid.UUID) error {
|
|
query := `
|
|
UPDATE ucca_dsb_pool
|
|
SET current_reviews = current_reviews + 1, updated_at = NOW()
|
|
WHERE user_id = $1
|
|
`
|
|
_, err := s.pool.Exec(ctx, query, userID)
|
|
return err
|
|
}
|
|
|
|
// DecrementReviewerCount decrements the current review count for a DSB member.
|
|
func (s *EscalationStore) DecrementReviewerCount(ctx context.Context, userID uuid.UUID) error {
|
|
query := `
|
|
UPDATE ucca_dsb_pool
|
|
SET current_reviews = GREATEST(0, current_reviews - 1), updated_at = NOW()
|
|
WHERE user_id = $1
|
|
`
|
|
_, err := s.pool.Exec(ctx, query, userID)
|
|
return err
|
|
}
|