Feat v0.3.4 team roles signoff (#18)
Some checks failed
CI/CD / detect-changes (push) Successful in 3s
CI/CD / test-frontend (push) Successful in 5s
CI/CD / test-go-pg (push) Failing after 2m45s
CI/CD / test-sqlite (push) Successful in 2m49s
CI/CD / build-and-deploy (push) Has been skipped

Co-authored-by: Jeffrey Smith <jasafpro@gmail.com>
Co-committed-by: Jeffrey Smith <jasafpro@gmail.com>
This commit was merged in pull request #18.
This commit is contained in:
2026-03-28 01:15:33 +00:00
committed by xcaliber
parent dba718b914
commit 0773c86c27
24 changed files with 1039 additions and 20 deletions

View File

@@ -660,6 +660,48 @@ func (s *WorkflowStore) ListAssignmentsByUser(ctx context.Context, userID string
return s.queryAssignments(ctx, q, args...)
}
// ── Signoffs (v0.3.4) ─────────────────────────
func (s *WorkflowStore) CreateSignoff(ctx context.Context, so *models.WorkflowSignoff) error {
return DB.QueryRowContext(ctx, `
INSERT INTO workflow_signoffs (instance_id, stage, user_id, decision, comment)
VALUES ($1, $2, $3, $4, $5)
RETURNING id, created_at`,
so.InstanceID, so.Stage, so.UserID, so.Decision, so.Comment,
).Scan(&so.ID, &so.CreatedAt)
}
func (s *WorkflowStore) ListSignoffs(ctx context.Context, instanceID, stage string) ([]models.WorkflowSignoff, error) {
rows, err := DB.QueryContext(ctx, `
SELECT id, instance_id, stage, user_id, decision, comment, created_at
FROM workflow_signoffs
WHERE instance_id = $1 AND stage = $2
ORDER BY created_at`, instanceID, stage)
if err != nil {
return nil, err
}
defer rows.Close()
var result []models.WorkflowSignoff
for rows.Next() {
var so models.WorkflowSignoff
if err := rows.Scan(&so.ID, &so.InstanceID, &so.Stage, &so.UserID,
&so.Decision, &so.Comment, &so.CreatedAt); err != nil {
return nil, err
}
result = append(result, so)
}
return result, rows.Err()
}
func (s *WorkflowStore) CountSignoffs(ctx context.Context, instanceID, stage, decision string) (int, error) {
var count int
err := DB.QueryRowContext(ctx, `
SELECT COUNT(*) FROM workflow_signoffs
WHERE instance_id = $1 AND stage = $2 AND decision = $3`,
instanceID, stage, decision).Scan(&count)
return count, err
}
func (s *WorkflowStore) queryAssignments(ctx context.Context, q string, args ...interface{}) ([]models.WorkflowAssignment, error) {
rows, err := DB.QueryContext(ctx, q, args...)
if err != nil {

View File

@@ -686,6 +686,50 @@ func (s *WorkflowStore) ListAssignmentsByUser(ctx context.Context, userID string
return s.queryAssignments(ctx, q, args...)
}
// ── Signoffs (v0.3.4) ─────────────────────────
func (s *WorkflowStore) CreateSignoff(ctx context.Context, so *models.WorkflowSignoff) error {
so.ID = store.NewID()
so.CreatedAt = time.Now().UTC()
_, err := DB.ExecContext(ctx, `
INSERT INTO workflow_signoffs (id, instance_id, stage, user_id, decision, comment, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?)`,
so.ID, so.InstanceID, so.Stage, so.UserID, so.Decision, so.Comment,
so.CreatedAt.Format(timeFmt))
return err
}
func (s *WorkflowStore) ListSignoffs(ctx context.Context, instanceID, stage string) ([]models.WorkflowSignoff, error) {
rows, err := DB.QueryContext(ctx, `
SELECT id, instance_id, stage, user_id, decision, comment, created_at
FROM workflow_signoffs
WHERE instance_id = ? AND stage = ?
ORDER BY created_at`, instanceID, stage)
if err != nil {
return nil, err
}
defer rows.Close()
var result []models.WorkflowSignoff
for rows.Next() {
var so models.WorkflowSignoff
if err := rows.Scan(&so.ID, &so.InstanceID, &so.Stage, &so.UserID,
&so.Decision, &so.Comment, st(&so.CreatedAt)); err != nil {
return nil, err
}
result = append(result, so)
}
return result, rows.Err()
}
func (s *WorkflowStore) CountSignoffs(ctx context.Context, instanceID, stage, decision string) (int, error) {
var count int
err := DB.QueryRowContext(ctx, `
SELECT COUNT(*) FROM workflow_signoffs
WHERE instance_id = ? AND stage = ? AND decision = ?`,
instanceID, stage, decision).Scan(&count)
return count, err
}
func (s *WorkflowStore) queryAssignments(ctx context.Context, q string, args ...interface{}) ([]models.WorkflowAssignment, error) {
rows, err := DB.QueryContext(ctx, q, args...)
if err != nil {

View File

@@ -52,4 +52,9 @@ type WorkflowStore interface {
ListAssignmentsByTeam(ctx context.Context, teamID string, status string) ([]models.WorkflowAssignment, error)
ListAssignmentsByInstance(ctx context.Context, instanceID string) ([]models.WorkflowAssignment, error)
ListAssignmentsByUser(ctx context.Context, userID string, status string) ([]models.WorkflowAssignment, error)
// Signoffs (v0.3.4)
CreateSignoff(ctx context.Context, s *models.WorkflowSignoff) error
ListSignoffs(ctx context.Context, instanceID, stage string) ([]models.WorkflowSignoff, error)
CountSignoffs(ctx context.Context, instanceID, stage, decision string) (int, error)
}