Files
Agent-System/internal/docgov/engine_persist.go
T
WeiCHEN 39e115b4d3 refactor(docgov): split engine.go into use-case files
Move claim/document/persist/proposal/read/review_flow into ≤800-line
siblings without behavior change; short tests green.
2026-09-23 09:54:19 +08:00

59 lines
1.7 KiB
Go

package docgov
import (
"context"
"encoding/json"
"fmt"
"chat-agent-system/internal/app/uow"
)
// nullIfZero maps unset duty holders (0) to SQL NULL so nullable FK columns
// (author_id/reviewer_id/approver_id → users.id) accept optional duties.
func nullIfZero(id int64) any {
if id <= 0 {
return nil
}
return id
}
func (e *GovernanceEngine) syncDocAndAuditToDB(ctx context.Context, doc *DocumentRecord, audit *AuditLog) error {
if e.pool == nil {
return nil
}
exec := func(sql string, args ...any) error {
if scope, ok := uow.ScopeFrom(ctx); ok {
tx, err := uow.AsPG(scope)
if err != nil {
return err
}
_, err = tx.Exec(ctx, sql, args...)
return err
}
_, err := e.pool.Exec(ctx, sql, args...)
return err
}
if err := exec(`
UPDATE document_records
SET current_state = $1, is_locked = $2,
last_rejected_reason = $3, last_rejected_by_role = $4, last_rejected_by_name = $5, last_rejected_at = $6,
approved_at = $7, updated_at = $8
WHERE doc_id = $9
`, string(doc.CurrentState), doc.IsLocked,
doc.LastRejectedReason, doc.LastRejectedByRole, doc.LastRejectedByName, doc.LastRejectedAt,
doc.ApprovedAt, doc.UpdatedAt, doc.DocID); err != nil {
return fmt.Errorf("docgov: sync document: %w", err)
}
if audit != nil {
detJSON, _ := json.Marshal(audit.Details)
if err := exec(`
INSERT INTO document_audit_logs (doc_id, action, actor_id, actor_name, actor_role, from_state, to_state, details, created_at)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
`, audit.DocID, audit.Action, audit.ActorID, audit.ActorName, string(audit.ActorRole),
string(audit.FromState), string(audit.ToState), detJSON, audit.CreatedAt); err != nil {
return fmt.Errorf("docgov: sync audit: %w", err)
}
}
return nil
}