5.0 KiB
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):
uploadDriverSignature(deliveryId, driverSignature)uploadCustomerSignature(deliveryId, customerSignature)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 1–3 bzw. 4–6) 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 1–3: keine Fahrer-Signatur, kein Abschluss.
- Fehler in 4–6: 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 bleibtlaufend. 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 1–6 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.