feat: add store CRUD methods for submission/extraction/finding/evidence
Create/Get for submission (including the one legitimate status transition — submission is not append-only, unlike the other three), Create/GetLatest for extraction and evidence_package, Create for finding plus ListCurrentFindings which applies the anti-join documented in the migration (a finding referenced by another row's `supersedes` is not "current"). Tested against real Postgres, including that the append-only trigger still rejects UPDATE on evidence_package via this new code path, and that ListCurrentFindings actually hides a finding once a correction supersedes it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
66
internal/store/submission.go
Normal file
66
internal/store/submission.go
Normal file
@@ -0,0 +1,66 @@
|
||||
package store
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Submission ist ein eingereichter Beitrag.
|
||||
type Submission struct {
|
||||
ID string
|
||||
Platform string
|
||||
PostType string
|
||||
Caption string
|
||||
Status string
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// CreateSubmission legt einen neuen Beitrag an (Status "draft").
|
||||
func (s *Store) CreateSubmission(ctx context.Context, platform, postType, caption string) (Submission, error) {
|
||||
var sub Submission
|
||||
err := s.Pool.QueryRow(ctx, `
|
||||
INSERT INTO submission (platform, post_type, caption)
|
||||
VALUES ($1, $2, $3)
|
||||
RETURNING id, platform, post_type, caption, status, created_at, updated_at
|
||||
`, platform, postType, caption).Scan(
|
||||
&sub.ID, &sub.Platform, &sub.PostType, &sub.Caption, &sub.Status, &sub.CreatedAt, &sub.UpdatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return Submission{}, fmt.Errorf("store: create submission: %w", err)
|
||||
}
|
||||
return sub, nil
|
||||
}
|
||||
|
||||
// GetSubmission liest einen Beitrag anhand seiner ID.
|
||||
func (s *Store) GetSubmission(ctx context.Context, id string) (Submission, error) {
|
||||
var sub Submission
|
||||
err := s.Pool.QueryRow(ctx, `
|
||||
SELECT id, platform, post_type, caption, status, created_at, updated_at
|
||||
FROM submission WHERE id = $1
|
||||
`, id).Scan(
|
||||
&sub.ID, &sub.Platform, &sub.PostType, &sub.Caption, &sub.Status, &sub.CreatedAt, &sub.UpdatedAt,
|
||||
)
|
||||
if err != nil {
|
||||
return Submission{}, fmt.Errorf("store: get submission: %w", err)
|
||||
}
|
||||
return sub, nil
|
||||
}
|
||||
|
||||
// SetSubmissionStatus setzt den Status eines Beitrags (submission ist,
|
||||
// anders als extraction/finding/evidence_package, NICHT append-only —
|
||||
// der Lebenszyklus draft → checked → published → archived ist eine
|
||||
// normale Zustandsänderung, kein Beweis-Eintrag).
|
||||
func (s *Store) SetSubmissionStatus(ctx context.Context, id, status string) error {
|
||||
tag, err := s.Pool.Exec(ctx, `
|
||||
UPDATE submission SET status = $2, updated_at = now() WHERE id = $1
|
||||
`, id, status)
|
||||
if err != nil {
|
||||
return fmt.Errorf("store: set submission status: %w", err)
|
||||
}
|
||||
if tag.RowsAffected() == 0 {
|
||||
return fmt.Errorf("store: set submission status: submission %s nicht gefunden", id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user