Files
nexarch/workflow/internal/caseobj/notes.go
patrickandClaude Sonnet 5 da6cfd8535
CI / Web-Barrierefreiheitspruefung (axe, Tastatur, Reflow, Textabstaende) (push) Canceled after 0s
CI / Core-Modul (Build/Vet/Test) (push) Canceled after 0s
CI / DMS Security-Test-Gate (AC5, Merge-Gate) (push) Canceled after 0s
CI / DMS-Modul Supply-Chain-Scan (govulncheck) (push) Canceled after 0s
CI / Web (dms-browser) (push) Canceled after 0s
CI / Web (pdf-viewer) (push) Canceled after 0s
CI / Web (shl) (push) Canceled after 0s
Supply-Chain-Scan (Go) / govulncheck (push) Canceled after 0s
CI / DMS-Modul (Lint/Build/Test/Coverage/Artefakt) (push) Canceled after 0s
VOR-02: vermerke notizen an akte vorgang
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-23 09:31:02 +02:00

79 lines
2.2 KiB
Go

// VOR-02: Freitext-Vermerke an einer Akte. Nach dem Speichern
// unveraenderlich (Datenbank-Trigger in 0006_case_notes.up.sql, nicht nur
// Anwendungslogik -- gleiches Muster wie workflow_instance_history aus
// ENG-04), damit die Akte als Nachweis taugt.
package caseobj
import (
"context"
"errors"
"fmt"
"time"
)
// Note ist ein einzelner, unveraenderlicher Aktenvermerk.
type Note struct {
ID string
CaseID string
Author string
Body string
CreatedAt time.Time
}
// AddNote fuegt der Akte einen neuen Vermerk hinzu (Akzeptanzkriterium 1:
// nur Ergaenzen, es gibt bewusst keine Update-Methode). Autor und Text
// sind Pflichtfelder (Akzeptanzkriterium 2, Pruefung 2).
func (s *Service) AddNote(ctx context.Context, caseID, author, body string) (Note, error) {
if author == "" {
return Note{}, fmt.Errorf("caseobj: autor ist pflicht")
}
if body == "" {
return Note{}, fmt.Errorf("caseobj: vermerktext ist pflicht")
}
var n Note
err := s.pool.QueryRow(ctx, `
INSERT INTO case_notes (case_id, author, body)
VALUES ($1, $2, $3)
RETURNING id, case_id, author, body, created_at
`, caseID, author, body).Scan(&n.ID, &n.CaseID, &n.Author, &n.Body, &n.CreatedAt)
if err != nil {
if isForeignKeyViolation(err) {
return Note{}, ErrNotFound
}
return Note{}, fmt.Errorf("caseobj: vermerk anlegen: %w", err)
}
return n, nil
}
// Notes liefert die Vermerke einer Akte in chronologischer Reihenfolge
// (Akzeptanzkriterium 3, Pruefung 3).
func (s *Service) Notes(ctx context.Context, caseID string) ([]Note, error) {
rows, err := s.pool.Query(ctx, `
SELECT id, case_id, author, body, created_at
FROM case_notes WHERE case_id = $1
ORDER BY created_at ASC, id ASC
`, caseID)
if err != nil {
return nil, fmt.Errorf("caseobj: vermerke lesen: %w", err)
}
defer rows.Close()
var out []Note
for rows.Next() {
var n Note
if err := rows.Scan(&n.ID, &n.CaseID, &n.Author, &n.Body, &n.CreatedAt); err != nil {
return nil, fmt.Errorf("caseobj: vermerk lesen: %w", err)
}
out = append(out, n)
}
return out, rows.Err()
}
func isForeignKeyViolation(err error) bool {
var pgErr interface{ SQLState() string }
if errors.As(err, &pgErr) {
return pgErr.SQLState() == "23503"
}
return false
}