Vertrag-Löschen: Kette bleibt intakt, Liste refresht
Zwei zusammenspielende Bugs: 1) Backend: deleteContract-Reihenfolge scheiterte am UNIQUE- Constraint auf Contract.previousContractId. Beim Middle-Delete (A → B → C, B löschen) hielt B im UPDATE-Moment noch selbst previousContractId=A – der Versuch, C ebenfalls auf A umzubiegen, warf MariaDB Duplicate-Entry, das UPDATE brach ab. Fix: Transaction, umgedrehte Reihenfolge – erst B löschen (DB-Cascade ON DELETE SET NULL räumt C.previousContractId ab, gibt A-Slot frei), dann C sauber auf A umbiegen. 2) Frontend: deleteMutation invalidierte weder Contract-Listen noch Kunden-Vertragsbaum und hatte keinen onError-Handler. Nach dem Delete wurde nach /contracts navigiert, dort zeigte der stale Cache noch den gelöschten Vertrag – Eindruck: „ganze Historie weg". Bei Bug 1 fehlgeschlagen brach das schweigend ab. Fix: queryClient.invalidateQueries für ['contracts'], ['contract-tree', customerId], ['customer', customerId] nach Erfolg. onError-Toast bei Fehler. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -97,6 +97,24 @@ isolierte Instanz (keine Multi-Tenancy im Code), Provisioning + Abrechnung
|
||||
|
||||
## ✅ Erledigt
|
||||
|
||||
- [x] **🐞 Vertrag-Löschen: Kette unterbrach, Liste aktualisierte nicht**
|
||||
- Zwei zusammenspielende Bugs: (1) im Service scheiterte das Umbiegen
|
||||
des Folgevertrags an der `@unique`-Regel auf `Contract.previousContractId`
|
||||
– wenn A → B → C stand und B gelöscht wurde, hielt B im UPDATE-Moment
|
||||
noch selbst `previousContractId=A`, C sollte auch auf A → Duplicate-
|
||||
Entry, das Update brach ab. (2) Der Frontend-`deleteMutation` in
|
||||
`ContractDetail` invalidierte die Contract-Listen-Query nicht,
|
||||
navigierte nur nach `/contracts` und zeigte den alten Cache.
|
||||
Zusammen sah es aus, als wäre die ganze Historie weg – tatsächlich
|
||||
stand der Vorgänger noch im Backend.
|
||||
- Fix Service: in einer Transaktion erst B löschen (DB-Cascade räumt
|
||||
C.previousContractId auf NULL und gibt den A-Slot frei), dann C
|
||||
sauber auf A umbiegen. Kein Zwischenzustand mehr sichtbar.
|
||||
- Fix Frontend: `queryClient.invalidateQueries(['contracts'])`
|
||||
plus `['contract-tree', customerId]` und `['customer', customerId]`
|
||||
nach dem Delete. `onError`-Toast ergänzt, damit fehlgeschlagene
|
||||
Löschungen nicht mehr still verschwinden.
|
||||
|
||||
- [x] **📝 DSGVO-Audit: Portaldaten-Opt-out als eigenes CRITICAL-Event**
|
||||
- Auf Wunsch des Pentesters (R117-Nachtrag): das Umschalten des
|
||||
`portalCredentialsNotRequired`-Flags emittiert jetzt zusätzlich zum
|
||||
|
||||
Reference in New Issue
Block a user