Ohne offenen Betrag gab es im Abschnitt "Zahlung" keine Aussage zur
Abwicklung, nur die Zahlungsmethode vom Beleg (z. B. "Bar"). Jetzt steht
dort "Zahlungsabwicklung: Nicht erforderlich, ..." mit Begruendung:
bereits bei Bestellung bezahlt, durch Anzahlung und Gutschrift oder nur
durch Gutschrift ausgeglichen, bzw. kein Warenwert. Unit-Tests dazu.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- CompleteDeliveryAcknowledgements.internalNote (optional, getrimmt,
max. 2000 Zeichen) wird atomar mit dem Abschluss gespeichert
(delivery_completions.internal_note)
- Bewusst keine delivery_notes-Zeile: loest weder die Kunden-Bestaetigung
der Notizen aus noch erscheint sie im Notizen-Step der App
- Lieferbericht: eigener Abschnitt "Interne Notiz" mit Zeitpunkt und Fahrer
- Bericht: Betrag in "Betrag erhalten" ans Zeilenende (Helvetica setzt nach
dem Euro-Zeichen zu eng)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Job::new_async interpretiert den Cron-Ausdruck in UTC - '0 0 17 * * *'
feuerte dadurch erst um 19:00 deutscher Zeit (CEST), der 17-Uhr-Import
fuer 'morgen' blieb aus. Alle drei Scheduler (ERP-Import, Report-Retry,
Signatur-Cleanup) nutzen jetzt Job::new_async_tz mit der konfigurierten
Fach-Zeitzone, sodass die Uhrzeit in der Config als Ortszeit gilt.
Hinweis: tokio-cron-scheduler ermittelt den UTC-Offset einmalig beim
Anlegen des Jobs (Serverstart); ein DST-Wechsel greift erst nach Neustart.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Lieferbericht zeigte UTC (08.09. 22:54 statt 09.09. 00:54): renderer.dt()
formatierte DateTime<Utc> ohne Umrechnung. Weitere Stellen hingen an
chrono::Local (OS-Zone des Hosts) bzw. hardcodiertem 'Europe/Berlin'.
Neu: server.timezone (IANA, Default Europe/Berlin, chrono-tz) und
durchgaengig UTC-Instant -> konfigurierte Zone:
- Lieferbericht: alle Zeitstempel (Abgeschlossen, Notizen, Scans, erzeugt am)
- Belegansicht (fmt_datetime)
- ERP-Rueckschreibung delivered_at (Wanduhrzeit)
- 'heute'-Ableitung: /me/tours, /dev/resync, /admin/import-erp,
Import-Cron + Startup-Catch-up
- Completion-Repo: AT TIME ZONE als Bind-Param statt Literal
Speicherung bleibt UTC (TIMESTAMPTZ / DateTime<Utc>) - nur Anzeige und
Kalendertag-Ableitung nutzen die Zone.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Das Makro ordnet den Lieferbericht dem Vorgang des Kunden zu und braucht
dafuer jetzt zusaetzlich die im ERP hinterlegte Kundennummer:
{ objectId, belegnummer, kundennummer }
- AssignReportRequest + Gateway-Port um kundennummer (String) erweitert
- AttachmentRepository.delivery_customer_number(): liest
customers.erp_customer_id (= ERP Kunden.Kundennummer) ueber
deliveries.customer_id
- ProcessDeliveryReportUseCase liest die Nummer aus der DB (nicht aus dem
Render-Ergebnis), damit sie auch im Retry-Pfad ohne erneutes Rendern vorliegt
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Fahrer können jetzt die Tour eines beliebigen Datums abrufen (z. B. morgen
vorab). Ohne date-Param bleibt serverseitig 'heute' (Local::now bzw.
Dev-today_override); Praezedenz: requested_date > today_override > Uhr.
Endpoint umbenannt /me/tours/today -> /me/tours (semantisch sauberer).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
'Heute' wurde per Utc::now().date_naive() bestimmt. Bei CEST (UTC+2)
wechselte der Tag dadurch erst um 02:00 Ortszeit — der Fahrer sah nach
Mitternacht noch die Touren von gestern. Umgestellt auf Local::now() in
list_my_tours_today sowie den Import-/Resync-Defaults und dem
Scheduler-Catch-up.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Konsistent zur App-Umbenennung (Step "Services" → "Checkliste"): die
Report-Sektion für delivery_services heißt im PDF jetzt "Checkliste".
Nur Anzeige/Wording (+ Kommentare), Datenmodell unverändert.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Beim Mengen-Rückschreiben werden jetzt auch die von der ERPframe-Engine
mitgeführten abgeleiteten Felder gesetzt, damit der Beleg konsistent bleibt
(Lagerbestand bucht das Lager weiterhin manuell — keine Lagerbewegung):
- Belegzeile: StatUmsatz, StatKosten (linear aus Alt-Stand skaliert),
Lagerverteilung (XML neu), row_update_time. VPEMenge NICHT (berechnete
Spalte → Fehler 271).
- Belegkopf: zusätzlich StatKosten, kalk (Kalkulations-XML), Druckkennzeichen,
row_update_time.
- Entfernt: mark_delivered (_SV_DELIVERY_DELIVERED_AT/_SV_DELIVERY_STATE) —
wird nicht mehr benötigt.
Alle geschriebenen Spalten gegen sys.computed_columns verifiziert.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rücknahme der Entkernung: set_line_menge + die Schleife in run() sind
wieder aktiv, d. h. die tatsächlich ausgelieferte Menge wird pro Belegzeile
gesetzt. Das umgeht bewusst die ERPframe-Engine (keine Lagerbuchung) — das
Lager verbucht den Bestand jetzt MANUELL nach Rückgabe des Geräts.
Gutschrift-Toggle + Vier-Augen-Review bleiben unverändert bestehen.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Rendert dieselben Daten wie der JSON-Detail-Endpunkt als schoen kategorisierte
HTML-Seite (askama, compile-time-Template). Der Handler destilliert das
DeliveryDetails-Aggregat in ein flaches View-Modell (Artikel-/Lagernamen
aufgeloest, Euro/Datum formatiert, deutsche Status-/Rollen-Labels); die
Template-Datei bleibt frei von Domain-Logik. Kategorien: Uebersicht, Kunde,
Lieferadresse, Positionen (Tabelle, veraenderte Zeilen hervorgehoben),
Geld-Gutschrift, Dienstleistungen, Notizen, Kontakte. Nutzt den bestehenden
get_delivery_details-Use-Case; admin-key-geschuetzt.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neuer Admin-Endpunkt, der zu einer ERP-Belegnummer das komplette Detail-Paket
einer Lieferung liefert (Kopf, Positionen mit Scan-Ständen, Kunde +
Ansprechpartner, referenzierte Artikel/Lager, Notizen, Geld-Gutschrift,
Dienstleistungswerte, Kontakte). Jede Lieferung, unabhaengig vom Status;
404 bei unbekannter Belegnummer.
Umsetzung: TourRepository::find_tour_id_by_belegnummer loest die Belegnummer
auf ihre tour_id auf; der Use Case laedt das bestehende Tour-Aggregat und
destilliert daraus in-memory die eine Lieferung samt referenzierter Stammdaten
(neues DTO DeliveryDetails). Kein neuer grosser Query.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Die "mindestens eine Grenze"-Sperre (400) entfernt. Ruft man
/admin/completed-deliveries ohne day/from/to, kommt jetzt der komplette
Bestand aller ausgelieferten (abgeschlossenen) Belege zurück, datumsunabhängig.
Der Repo-Query unterstützt from=NULL/to=NULL bereits.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neuer Admin-Endpunkt, der zu EINER ERP-Belegnummer das positions_modified-Flag
liefert (Stück-Gutschrift auf einer Belegzeile ODER aktive Geld-Gutschrift) —
gleiche Definition wie in completed-deliveries, aber pro Beleg und ohne
Abschluss-Voraussetzung. 404 bei unbekannter Belegnummer; bei mehreren
Lieferungen gleicher Belegnummer true, sobald eine verändert ist (bool_or).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
/admin/completed-deliveries akzeptiert jetzt zusätzlich zu `day` (Kurzform
from=to) optionale `from`/`to` (DD-MM-YYYY, inklusive, je offen). Damit lassen
sich Halb-Grenzen abfragen: `?from=` bzw. `?to=` liefern je eine Belegnummern-
Menge, deren SQL-AND-Schnitt einen Zeitraum ergibt (Range-Filter über zwei
unabhängige ERPframe-Filter). Response gibt statt `day` nun `from`/`to` zurück.
Mindestens eine Grenze ist Pflicht (kein Full-Table-Dump).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Neuer Admin-Endpunkt, der ALLE an einem Tag (Berliner Kalendertag von
completed_at) abgeschlossenen Lieferungen liefert — unabhängig vom
Mail-Versand-Status. Pro Lieferung: Belegnummer und ein Flag
`positions_modified`, das true ist, wenn eine Belegzeile in der Menge
reduziert/entfernt wurde (delivery_items.credited_quantity > 0) oder eine
aktive Geld-Gutschrift vorliegt (jüngstes delivery_credit_audit-Event 'set').
Pflichtparameter `day` (DD-MM-YYYY). Geschützt per admin_api_key.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Setzt EINE Lieferung zurück, ohne die Tour zu löschen (Alternative zum
destruktiven /dev/resync): Abschluss (delivery_completions), Scan-/
Gutschrift-Audit + offener Report-Job weg, Positionen zurück (scanned/
credited = 0, Status in_progress), Lieferung wieder active (state_reason/
assigned_car/review_* geleert). Notizen/Dienstleistungen/Anhänge bleiben.
Vervollständigt den bisher nur als Port-Stub vorhandenen
reset_delivery_by_belegnummer (Build war dadurch kaputt) + Use Case +
DEV-Route (nur bei dev.sync_enabled gemountet, unauthentifiziert).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Neues Flag [erp] gutschrift_writeback_enabled (Default true): steuert, ob
die Geld-Gutschrift (GUTSCHRIFT10-Belegzeile) beim Abschluss ins ERP
zurückgeschrieben wird. Gutschriften sind bestandsneutral (keine
Bestandsführung) → unkritisch, daher standardmäßig an, aber abschaltbar.
Die Belegzeilen-Menge wird weiterhin generell NICHT zurückgeschrieben
(Bestands-Inkonsistenz); geänderte Belege gehen in die Vier-Augen-Prüfung.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Geänderte Lieferscheine (Artikel entfernt/teil-gutgeschrieben ODER
Geld-Gutschrift) sollen von der Fakturierung gegengeprüft werden, statt
die Menge im ERP zu reduzieren (was den Lagerbestand inkonsistent machte,
weil der Raw-Writeback die ERPframe-Engine umgeht).
- ERP-Writeback: kein Setzen der Belegzeilen-Menge mehr → ERP-Beleg bleibt
im Original (kein Bestandskonflikt). Geld-Gutschrift wird weiter
geschrieben (unkritisch, nur Vier-Augen). delivered-at/State/Zahlbed
bleiben.
- Migration 0031: review_resolved_at/by/note auf deliveries. Der Status
wird ABGELEITET (Abweichung via credited_quantity / aktueller Gutschrift
vs. resolved_at), daher: Originalzustand wiederhergestellt ⇒ Flag weg;
nach Bestätigung erneut geändert ⇒ wieder offen.
- ReviewRepository (Port + Pg-Impl) + Use Cases ListPendingReviews/
ResolveReview.
- Endpoints: GET /admin/reviews (offene Prüfungen inkl. Änderungsdetails
aus scan_audit/credit_audit) + POST /admin/reviews/{delivery_id}/resolve
(Admin-Key).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Unterschrifts-Dateien folgen jetzt dem Schema
delivery_{Belegnummer}_signature_{customer|driver}.png
(z. B. delivery_V-30690287_signature_customer.png) statt zuvor
{delivery_id}_{role}.png.
- SignatureStorage::save nimmt Belegnummer statt delivery_id; Adapter
baut den Dateinamen + saubere Sanitisierung des Belegnummer-Anteils
(Schutz gegen Pfad-Ausbruch, übliche Werte wie V-30690287 bleiben).
- CompleteDeliveryUseCase löst die Belegnummer vor dem Speichern auf.
- Neue Lookup-Methode DeliveryCompletionRepository::belegnummer_for.
- Totes delete_for_delivery (Reconstruktion via delivery_id, keine
Aufrufer mehr seit Cron-Cleanup) entfernt.
Abwärtskompatibel: bestehende Signaturen werden über die in
delivery_completions gespeicherte Referenz geladen, alte Dateinamen
bleiben lesbar. Nur neue Abschlüsse verwenden das neue Schema.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Jeder ERPframe-Import (Scheduler, Startup, manuell) wird in der neuen Tabelle
erp_sync_runs protokolliert (target_date, trigger, success, Zaehler, Fehler).
Beim Serverstart synct das Backend das Zieldatum (heute + offset, i.d.R. morgen)
nach, falls dafuer noch kein erfolgreicher Lauf dokumentiert ist — deckt
Erststart UND laengere Unterbrechungen ab, bei denen der Cron-Zeitpunkt verpasst
wurde. Gated ueber [import] enabled.
- Migration 0030_erp_sync_runs
- Port SyncRunRepository (+ SyncRunRecord, SyncTrigger)
- Adapter PgSyncRunRepository
- ImportErpToursUseCase dokumentiert jeden Lauf; neues execute_with(date, trigger)
- main.rs: Repo verdrahtet, Scheduler-Trigger, Startup-Catch-up (tokio::spawn)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Das Backend kann jetzt — analog zum Mail-Client — als Windows-Dienst laufen.
- main() refaktoriert: App-Logik in run_app(shutdown, service_mode); eigene
tokio-Runtime statt #[tokio::main]. Windows startet zuerst den SCM-Dispatcher,
fällt bei interaktivem Start auf Konsolenmodus zurück (--console erzwingt ihn).
- src/service.rs (windows-only): SCM-Integration via windows-service-Crate,
Stop/Shutdown-Handler, Running/Stopped-Status. Setzt das Arbeitsverzeichnis
aufs EXE-Verzeichnis (Dienst startet sonst in System32), damit config.toml/
data/logs daneben liegen. Fallback-Log bei Boot-Fehler.
- Graceful Shutdown: GSD-Lizenz-Freigabe in den Serve-Wrapper gezogen (greift
in beiden Modi); Stop-Trigger ist das übergebene shutdown-Future.
- Logging: Konsolenmodus → stderr (wie bisher); Dienst-Modus → rollende
Tagesdatei (tracing-appender) unter [logging] dir (Default logs/).
- install-service.ps1 / uninstall-service.ps1 (Dienst "Holzleitner Backend").
- README: Windows-Dienst-Abschnitt; .gitignore: /logs + Fatal-Log.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>