This commit is contained in:
Dennis Nemec
2026-04-28 13:03:09 +02:00
parent de8668c11a
commit 2470299a10
53 changed files with 2409 additions and 1433 deletions

85
docs/finish_delivery.md Normal file
View File

@ -0,0 +1,85 @@
# Lieferungs-Abschluss: Ablauf & bekannte Themen
Dieses Dokument beschreibt den Request-Ablauf, der ausgelöst wird, wenn der
Fahrer nach der Unterschrift "Lieferung abschließen" auslöst, sowie bekannte
Schwachstellen, die mittelfristig adressiert werden sollten.
Stand: 2026-04-26.
## Aufrufkette
UI: `SignatureView.onSigned``_onSign(customer, driver)`
(`lib/feature/delivery/detail/presentation/delivery_detail_page.dart`)
BLoC: dispatched `FinishDeliveryEvent``TourBloc._finishDelivery`
(`lib/feature/delivery/bloc/tour_bloc.dart`)
Repository (`lib/feature/delivery/repository/tour_repository.dart`):
1. `uploadDriverSignature(deliveryId, driverSignature)`
2. `uploadCustomerSignature(deliveryId, customerSignature)`
3. `finishDelivery(deliveryId)`
Daraus ergeben sich 7 sequenzielle HTTP-Requests (jeweils `await`):
| Reihenfolge | HTTP | Endpoint | Zweck |
| ----------- | ------ | --------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| 1 | GET | `/v1/uploadFile` | `uploadId` für Fahrer-Signatur holen |
| 2 | POST | `/v1/uploadFile/{uploadId}` | Multipart-Upload `delivery_{id}_signature_driver.jpg` |
| 3 | PATCH | `/v1/uploadFile/{uploadId}` | Upload commit, liefert `ObjectID` |
| 4 | GET | `/v1/uploadFile` | `uploadId` für Kunden-Signatur holen |
| 5 | POST | `/v1/uploadFile/{uploadId}` | Multipart-Upload `delivery_{id}_signature_customer.jpg` |
| 6 | PATCH | `/v1/uploadFile/{uploadId}` | Upload commit |
| 7 | POST | `_web_finishDelivery` | Atomarer Abschluss: setzt `_SV_DELIVERY_STATE = "geliefert"` und `_SV_DELIVERY_DELIVERED_AT = <Zeitstempel>`, räumt entfernte Artikel auf. Body `{ "delivery_id": <id>, "delivered_at": "<yyyy-MM-ddTHH:mm:ss>" }` |
Die GET/POST/PATCH-Sequenz pro Signatur (Schritte 13 bzw. 46) ist vom
ERP-/Dokumentenverwaltungssystem so vorgegeben und wird hier **nicht**
angepasst.
Der frühere zusätzliche Aufruf von `_web_updateDelivery` mit `state = finished`
(historisch Schritt 7) ist entfallen: `_web_finishDelivery` setzt State und
Lieferzeitpunkt jetzt atomar in einem einzigen `UPDATE` auf `Belegkopf`.
## Offene Punkte
### 1. ~~Doppelter Abschluss-Call~~ — erledigt (2026-04-26)
Status: behoben. `_web_updateDelivery` wird im Abschluss-Flow nicht mehr
aufgerufen. `_web_finishDelivery` schreibt `_SV_DELIVERY_STATE` und
`_SV_DELIVERY_DELIVERED_AT` atomar in einem einzigen `UPDATE` auf
`Belegkopf` und führt anschließend `_removeArticles` aus.
### 3. Hartcodierte Sequenz ohne Retry, generisches Error-Reporting
Die 7 Requests laufen strikt nacheinander mit `await`. Bei einem Fehler an
einer beliebigen Stelle landet der Flow in `TourBloc._handleError` und
emittiert eine generische Meldung "Fehler beim Abschließen der Lieferung",
ohne den genauen Schritt zu nennen.
Risiken:
- Partial-Failure-Zustände sind möglich:
- Fehler in 13: keine Fahrer-Signatur, kein Abschluss.
- Fehler in 46: Fahrer-Signatur ist hochgeladen, Kunden-Signatur nicht,
Lieferung weiterhin offen.
- Fehler in 7 (`_web_finishDelivery`): beide Signaturen liegen am ERP,
State und Lieferzeitpunkt aber nicht gesetzt — Lieferung bleibt
`laufend`. Da der Endpoint atomar ist, gibt es keinen Zwischen-Zustand
"State gesetzt, Zeitstempel fehlt" oder umgekehrt.
- Schlechtes Netz / Funkloch beim Fahrer ist Realität → Wahrscheinlichkeit
ist nicht klein.
- Fahrer kann den Schritt blind wiederholen, ohne zu wissen, ob Signaturen
schon liegen → potenziell doppelte Bilddateien im DMS.
- Diagnose im Support ist mühsam, weil die Fehlermeldung nichts zur Stelle
sagt.
To-do (mittelfristig):
- Pro Repository-Schritt eine eigene, sprechende Fehlermeldung
("Fahrersignatur konnte nicht gespeichert werden", "Kundensignatur …",
"Lieferung konnte nicht als abgeschlossen markiert werden").
- Idempotenz prüfen: lassen sich die Schritte 16 ohne Doppel-Effekt
wiederholen? Falls ja, Retry-Strategie mit exponential backoff für
Netzfehler. Falls nein, mit Backend abstimmen.
- Server-Sicht "Wurde Schritt X für Lieferung Y schon erledigt?" einbauen,
damit ein Wiederaufnehmen nach App-Crash/Neustart möglich ist.
- Optional: Outbox-Pattern — Signaturen + Finish-Marker werden lokal
persistiert und im Hintergrund hochgeladen, statt blockierend im UI.