package store import ( "context" "errors" "fmt" "time" "github.com/jackc/pgx/v5" ) // Submission ist ein eingereichter Beitrag. AccountID ist der Mandant, // dem der Beitrag gehört (Mandantentrennung) — jede Abfrage, die einen // Beitrag ausliefert, muss AccountID gegen den angemeldeten Account // prüfen (siehe internal/web-Middleware), store selbst erzwingt das // nicht auf Zeilenebene. type Submission struct { ID string AccountID string Platform string PostType string Caption string Status string CreatedAt time.Time UpdatedAt time.Time } // CreateSubmission legt einen neuen Beitrag für einen Mandanten an // (Status "draft"). func (s *Store) CreateSubmission(ctx context.Context, accountID, platform, postType, caption string) (Submission, error) { var sub Submission err := s.Pool.QueryRow(ctx, ` INSERT INTO submission (account_id, platform, post_type, caption) VALUES ($1, $2, $3, $4) RETURNING id, account_id, platform, post_type, caption, status, created_at, updated_at `, accountID, platform, postType, caption).Scan( &sub.ID, &sub.AccountID, &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 — ohne // Mandanten-Prüfung, das ist Sache des Aufrufers (siehe Submission.AccountID). func (s *Store) GetSubmission(ctx context.Context, id string) (Submission, error) { var sub Submission err := s.Pool.QueryRow(ctx, ` SELECT id, account_id, platform, post_type, caption, status, created_at, updated_at FROM submission WHERE id = $1 `, id).Scan( &sub.ID, &sub.AccountID, &sub.Platform, &sub.PostType, &sub.Caption, &sub.Status, &sub.CreatedAt, &sub.UpdatedAt, ) if errors.Is(err, pgx.ErrNoRows) { return Submission{}, ErrNotFound } 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 }