Files
archivdms/internal/storage/migrations/022_retention_rules.sql
T
patrick 9a24ea29e1 FDN-01: repository & projektgerüst
Git-Repository für bestehenden archivdms-Code initialisiert, Branch-/Commit-Konvention (feature/<ticket>-<slug>-Branches, Ticket-Prefix in Commit-Nachricht) etabliert.
2026-08-11 21:27:53 +02:00

54 lines
3.1 KiB
SQL

-- PROJ: retention-rules-engine
-- Doku-only (siehe README.md in diesem Verzeichnis) — die tatsächliche
-- Ausführung passiert idempotent über internal/storage/retention_rules.go
-- initRetentionRulesSchema(), aufgerufen aus (*Store).initSchema().
--
-- GoBD-Aufbewahrungsregeln (retention rules / "Disposition Schedules",
-- Namens-/Modellreferenz Alfresco, NICHT dessen Architektur):
-- * Eine Regel definiert pro Dokumenttyp (oder tenant-weit als Default mit
-- doc_type_id IS NULL) WIE LANGE ein Dokument aufbewahrt werden muss und
-- ab WELCHEM Stichtag (trigger_type) die Frist zählt.
-- * Der Batch-Job ApplyRetentionRules (CLI: `archivdms retention apply`)
-- berechnet retain_until und SETZT es auf documents — er löscht NIEMALS
-- und verkürzt eine bereits gesetzte Sperre NIE (GoBD: WORM nur
-- verlängerbar). Die eigentliche Vernichtung läuft weiter über den
-- Papierkorb + Vier-Augen-Workflow (007_trash.sql).
-- * trigger_type:
-- document_date -> documents.document_date, sonst created_at
-- upload_date -> documents.created_at
-- fixed_date -> trigger_reference als YYYY-MM-DD (einmaliger Stichtag)
-- event -> NICHT auto-berechnet (z.B. Geschäftsjahresende /
-- Vertragsende); Dokumente werden übersprungen, künftiger
-- Erweiterungspunkt.
-- * retain_until = Stichtag + retention_years Jahre + retention_days Tage.
-- Für non-event-Regeln muss mindestens eines von years/days > 0 sein
-- (im Go-Store validiert, nicht per CHECK).
-- * Präzedenz: doc-typ-spezifische Regel schlägt die tenant-weite Default-
-- Regel (doc_type_id IS NULL). UNIQUE(tenant_id, doc_type_id) erzwingt
-- höchstens eine Regel pro (Mandant, Dokumenttyp), daher keine
-- "strictest wins"-Logik nötig.
-- * requires_approval_for_destroy / dsgvo_conflict sind informative Flags für
-- das spätere Disposition-Frontend; die Vier-Augen-Pflicht selbst wird
-- bereits vom Trash-Flow erzwungen.
CREATE TABLE IF NOT EXISTS retention_rules (
id BIGSERIAL PRIMARY KEY,
tenant_id BIGINT NOT NULL,
doc_type_id BIGINT REFERENCES document_types(id) ON DELETE CASCADE,
name TEXT NOT NULL,
trigger_type TEXT NOT NULL
CHECK (trigger_type IN ('document_date','upload_date','fixed_date','event')),
trigger_reference TEXT NOT NULL DEFAULT '',
retention_years INT,
retention_days INT,
legal_basis TEXT NOT NULL DEFAULT '',
requires_approval_for_destroy BOOLEAN NOT NULL DEFAULT true,
dsgvo_conflict BOOLEAN NOT NULL DEFAULT false,
active BOOLEAN NOT NULL DEFAULT true,
created_by BIGINT,
created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT now(),
UNIQUE(tenant_id, doc_type_id)
);
CREATE INDEX IF NOT EXISTS idx_retention_rules_tenant ON retention_rules(tenant_id) WHERE active;