-- 0014_delivery_credit_audit.sql -- -- Betrags-Gutschrift pro Lieferung (Geld-Nachlass, unabhängig von Stückzahl; -- ≤150 €, in 10-€-Schritten, Pflichtgrund). -- -- Append-only Audit-Log — analog scan_audit: jede Änderung (set/remove) ist -- eine eigene Zeile, nichts wird geupdated/gelöscht. Der "aktuelle" Stand -- einer Lieferung ist das jüngste Ereignis (DISTINCT ON delivery_id … -- ORDER BY recorded_at DESC): action='set' → Betrag+Grund, action='remove' -- → keine Gutschrift. -- -- Idempotenz: client_event_id ist UNIQUE. Ein Netz-Retry desselben Events -- kollidiert auf dem Index (INSERT … ON CONFLICT DO NOTHING) — der Server -- liefert den aktuellen Stand zurück, ohne eine Dublette anzuhängen. CREATE TABLE delivery_credit_audit ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), -- Idempotenz-Schlüssel vom Client. client_event_id UUID NOT NULL UNIQUE, delivery_id UUID NOT NULL REFERENCES deliveries(id) ON DELETE CASCADE, action TEXT NOT NULL CHECK (action IN ('set', 'remove')), -- Resultierender Betrag NACH diesem Ereignis (in Cent). 0 bei 'remove'. -- Harte Obergrenze 150 € als CHECK; die 10-€-Schritt-Regel prüft der -- Use Case (fachlich, leichter änderbar als ein DB-CHECK). amount_cents BIGINT NOT NULL DEFAULT 0 CHECK (amount_cents >= 0 AND amount_cents <= 15000), -- Pflicht bei 'set' (im Use Case erzwungen), bei 'remove' optional. reason TEXT, -- Akteur: Personalnummer aus dem JWT (Pflicht), Fahrzeug optional. author_personalnummer BIGINT NOT NULL, author_car_id UUID, recorded_at TIMESTAMPTZ NOT NULL DEFAULT now() ); CREATE INDEX delivery_credit_audit_delivery ON delivery_credit_audit (delivery_id, recorded_at DESC);