- Sync nimmt die Lieferadresse als Ganzes: mit eigener LieferAdressId
alle Felder aus ihr, sonst alle aus der Belegadresse. Das bisherige
COALESCE je Feld hat leere Felder mit Werten des Bestellers gefüllt
(z. B. dessen Ortsteil an eine fremde Anschrift gehängt).
- ERP-Freitext `Adressen.Land` (praktisch Ortsteil/Etage/Hinweis) wird
zum Adresszusatz `Address.addition`; `country` kommt jetzt aus dem
Länderstamm (`LandID` → `Laender.Land`). Deutschland-Kürzel und reine
Landnamen sind kein Zusatz.
- Migration 0034: `customers.address_addition`, `deliveries.snap_addition`;
Bestandstext aus `country` wandert in den Zusatz.
- Lieferbericht und Beleg-Ansicht: Land nur außerhalb Deutschlands,
Zusatz als eigene Zeile „Zusatz: …".
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>
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>
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>
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>