# Entwicklungskonzept DHL Modul

Stand: 13.05.2026

## Ziel

Diese Datei ist die aktuelle Arbeitsgrundlage fuer die Weiterentwicklung des DHL Moduls. Die bisherigen Markdown-Dateien in diesem Ordner dokumentieren abgeschlossene oder ueberholte Zwischenstaende, insbesondere den frueheren SDK-Ansatz, Paketinstallation, SSL/cURL-Fixes und einzelne abgeschlossene Entwicklungsschritte.

Aktuelle Anforderungen kommen aus `docs/dhl/Anpassung DHL Modul.md`:

- Internationaler Versand ausserhalb Deutschlands, insbesondere Oesterreich und Spanien.
- Freies Feld fuer Sendungsreferenz oder interne Hinweise wie "Nachlieferung".
- Adressvalidierung vor Labelerstellung, damit fehlerhafte Labels und kostenpflichtige Stornos vermieden werden.
- Storno im DHL Cockpit pruefen und stabilisieren.
- Gewicht von Kompensationsprodukten in das DHL-Paketgewicht einrechnen.
- Tracking-Mails auf Rhythmus, Ausloeser und Mehrfachversand pruefen.
- Tracking-Codes in Admin, User-Portal und User-N-Portal sichtbar machen.
- Tracking-Mail-Versand nur bei Statusaenderung.
- DHL-Umstellung von `V62WP` Warenpost auf `V62KP` DHL Kleinpaket bis spaetestens 31.05.2026.

## Aktueller technischer Stand

Das produktive Modul basiert auf dem Paket `packages/acme-laravel-dhl` und verwendet die DHL REST API ueber `Acme\Dhl\Support\DhlClient`. Die zentrale Tabelle ist `dhl_package_shipments`.

Wichtige produktive Einstiegspunkte:

- `app/Http/Controllers/DhlShipmentController.php`
- `app/Services/DhlShipmentService.php`
- `app/Services/DhlModalService.php`
- `app/Services/DhlDataHelper.php`
- `app/Services/DhlTrackingService.php`
- `packages/acme-laravel-dhl/src/Services/ShippingService.php`
- `packages/acme-laravel-dhl/src/Services/ReturnsService.php`
- `packages/acme-laravel-dhl/src/Models/DhlShipment.php`
- `config/dhl.php`

Historische Dokumente erwaehnen teilweise alte Strukturen wie `App\Models\DhlShipment`, `dhl_shipments` oder einen konsolidierten `DhlApiService`. Diese Angaben sind nicht mehr massgeblich, ausser sie werden explizit in aktuellem Code noch referenziert. Aktuell gibt es genau dort noch Altlasten, die bereinigt werden muessen.

## Offensichtliche Befunde

### 1. Produktkuerzel `V62WP` ist veraltet

`V62WP` ist weiterhin in Konfiguration, Admin-Settings, Validierung, Produktauswahl und Sprachdateien vorhanden. DHL verlangt die Umstellung auf `V62KP`.

Betroffene Stellen:

- `config/dhl.php`
- `app/Http/Controllers/SettingController.php`
- `app/Services/DhlModalService.php`
- `packages/acme-laravel-dhl/src/Services/ShippingService.php`
- `resources/lang/*/dhl.php`

Risiko: Kleinpaket/Warenpost-Labels koennen nach der DHL-Frist abgelehnt werden.

### 2. Async Tracking verwendet veraltetes Model

`app/Jobs/TrackShipmentJob.php` importiert `App\Models\DhlShipment`, dieses Model existiert im aktuellen System nicht mehr. Die produktive DHL-Integration verwendet `Acme\Dhl\Models\DhlShipment`.

Risiko: Asynchrones Tracking bricht zur Laufzeit, sobald Queue-Tracking genutzt wird.

### 3. Statuswerte fuer Storno sind inkonsistent

Im Paket wird bei erfolgreichem Storno `canceled` gesetzt. Andere Stellen, Uebersetzungen und historische Dokumente verwenden `cancelled`.

Risiko: Filter, Badges, Terminal-Status, Uebersetzungen und Storno-Buttons verhalten sich uneinheitlich.

### 4. Storno ist technisch vorhanden, aber nicht robust genug

Storno laeuft ueber `DELETE /parcel/de/shipping/v2/orders/{shipmentNumber}`. Der Code prueft `canCancel()`, speichert aber Fehler nur begrenzt fachlich verwertbar. Produktspezifische Einschraenkungen wie Warenpost/Kleinpaket sind nicht sauber modelliert.

Risiko: Anwender sehen generische Fehler und koennen nicht erkennen, ob ein Storno produktbedingt, statusbedingt, API-bedingt oder wegen Sandbox/Production-Mismatch scheitert.

### 5. Internationaler Versand ist nur teilweise vorbereitet

`V53PAK` ist als internationales Produkt vorhanden, und einige Laender werden in 3-stellige ISO-Codes konvertiert. Dennoch gibt es keinen zentralen Produktentscheid je Zielland, keine harte Validierung nicht unterstuetzter Laender und einen gefaehrlichen Fallback auf `DEU`.

Risiko: Sendungen nach Oesterreich, Spanien oder weitere Laender koennen falsche Produktcodes, falsche Abrechnungsnummern oder falsche Laendercodes erhalten.

### 6. Adressvalidierung ist nur formal

Aktuell prueft das Modul Pflichtfelder, Hausnummern und einfache PLZ-Regeln. Eine echte Pruefung, ob Strasse, PLZ und Ort postalisch existieren, findet nicht statt.

Empfohlene Loesung: DHL/Post & DHL `DATAFACTORY AUTOCOMPLETE 2.0` fuer DE/AT/CH pruefen und integrieren. Alternativen fuer breiteren Laenderumfang: Loqate, Google Address Validation oder HERE. Wichtig ist eine harte Sperre bei nicht versandfaehigen Adressen vor Labelerstellung.

### 7. Referenzfeld ist API-seitig vorhanden, aber nicht im Cockpit nutzbar

`ShippingService` kann `reference` nach `refNo` mappen. `DhlDataHelper` setzt aktuell automatisch `Order-{id}`.

Risiko: Admins koennen Hinweise wie "Nachlieferung" nicht strukturiert am Label/API-Auftrag hinterlegen.

### 8. Gewicht von Kompensationsprodukten fehlt

Kompensationsprodukte werden im Warenkorb mit Gewicht `0` abgelegt, damit die Kompensationslogik nicht beeinflusst wird. Das DHL-Gewicht kommt aus `ShoppingOrder->weight` und enthaelt dieses Produktgewicht dadurch nicht.

Risiko: DHL-Label wird mit zu geringem Paketgewicht erstellt.

### 9. Tracking-Mail-Logik ist grundsaetzlich brauchbar, muss aber abgesichert werden

Der Scheduler ruft stuendlich `dhl:update-tracking --days=30 --send-emails` auf. Statusabhaengige Intervalle verhindern zu viele API-Calls. Automatische Mails werden nur gesendet, wenn eine Sendung neu auf `in_transit` wechselt und noch keine Mail markiert wurde.

Risiko: Statusspruenge direkt auf `out_for_delivery` oder besondere DHL-Statuscodes koennen ohne Mail bleiben. Mehrere Sendungen einer Bestellung werden teils zusammengefasst, aber die fachliche Regel muss final bestaetigt werden.

## Entwicklungskonzept

### Phase 1: Pflichtkorrekturen vor DHL-Frist

1. `V62WP` vollstaendig auf `V62KP` migrieren.
2. Neue Konfigurationskeys fuer `DHL_ACCOUNT_NUMBER_V62KP`, Admin-Setting `dhl_account_v62kp`, Dimensionen und Uebersetzungen einfuehren.
3. `ShippingService` Validierung um `V62KP` erweitern und `V62WP` entfernen oder nur noch als Legacy-Mapping fuer Altdaten anzeigen.
4. Bestehende Sendungen mit `V62WP` historisch lesbar lassen, aber neue Labelerstellung blockieren.
5. Tests fuer Produktcode-Auswahl, Validierung und Payload-Erstellung schreiben.

### Phase 2: Stabilisierung von Tracking und Storno

1. `TrackShipmentJob` auf aktuelles Model und aktuellen `DhlTrackingService` umstellen.
2. Statuswerte vereinheitlichen. Empfehlung: intern `canceled` verwenden, Uebersetzung auf Deutsch "Storniert".
3. `TERMINAL_STATUSES`, Badges, Filter und Sprachdateien entsprechend angleichen.
4. Storno-Fehler strukturiert speichern: HTTP-Status, DHL-Fehlercode, DHL-Detailtext, Zeitpunkt.
5. Admin-Feedback verbessern: nicht stornierbar wegen Status, Produkt, API-Antwort oder nicht auffindbarer DHL-Sendung.
6. Tests fuer erfolgreiche Stornierung, bereits stornierte Sendung, nicht stornierbare Sendung und API-Fehler.

### Phase 3: Internationalisierung Versand

1. Zentralen Service fuer Produkt-/Billing-Entscheidung einfuehren, z. B. `DhlProductResolver`.
2. Zielland, Produktcode, Abrechnungsnummer und erlaubte Services dort validieren.
3. Regeln initial:
   - `DE`: `V01PAK` oder `V62KP`
   - `AT`, `ES` und weitere aktivierte Laender: `V53PAK`
4. Fallback auf `DEU` entfernen. Unbekannte Laender muessen mit klarer Fehlermeldung abbrechen.
5. Cockpit-Formular: Produkt anhand Zielland vorschlagen, aber Admin-Korrektur erlauben.

### Phase 4: Adressvalidierung vor Labelerstellung

1. Neuen serverseitigen Validierungsendpunkt fuer DHL-Adressen schaffen.
2. Basisvalidierung behalten: Pflichtfelder, Land, PLZ-Format, Hausnummer, Packstation/Postnummer.
3. DHL DATAFACTORY AUTOCOMPLETE 2.0 fuer DE/AT/CH evaluieren.
4. Falls DHL fuer alle benoetigten Laender nicht ausreicht, externen Provider evaluieren.
5. UI-Status einfuehren:
   - gueltig: Labelerstellung erlaubt
   - Warnung: Admin kann bewusst fortfahren
   - Fehler: Labelerstellung gesperrt
6. Validierungsergebnis optional am Shipment/Order protokollieren.

### Phase 5: Referenzfeld und Admin-UX

1. Neues Formularfeld `reference` oder `shipment_reference` im DHL Cockpit.
2. Wert an `DhlDataHelper::prepareOrderData()` uebergeben.
3. `ShippingService` nutzt vorhandenes Mapping nach `refNo`.
4. Referenz im Shipment speichern, damit spaeter nachvollziehbar ist, warum eine Sendung erstellt wurde.
5. Laengenlimit der DHL API beachten, aktuell maximal 35 Zeichen.

### Phase 6: DHL-Gewicht korrekt berechnen

1. Separaten Gewichtsdienst fuer DHL einfuehren, z. B. `DhlShipmentWeightCalculator`.
2. Basis: `ShoppingOrder->weight`.
3. Fuer `shopping_order_items` mit `comp > 0` das Produktgewicht aus `Product->weight` nachladen und addieren.
4. Nur DHL-Gewicht anpassen, nicht die bestehende Warenkorb-/Versandkostenlogik.
5. Rundung und DHL-Grenzwerte je Produkt testen.

### Phase 7: Tracking-Codes und Mails fachlich finalisieren

1. Bestehende Admin-Anzeige pruefen und bei Bedarf vereinheitlichen.
2. Tracking-Code-Anzeige in User-Portal und User-N-Portal ergaenzen.
3. Mail-Regel final definieren:
   - automatisch nur einmal pro Sendung
   - nur bei relevanter Statusaenderung
   - mehrere Sendungen einer Bestellung sinnvoll zusammenfassen
4. Statusspruenge wie `created` direkt nach `out_for_delivery` abdecken.
5. Command `dhl:update-tracking` Tests fuer Mailausloeser und Nicht-Ausloeser ergaenzen.

## Empfohlene Reihenfolge

1. `V62WP` -> `V62KP`, Statuswerte und `TrackShipmentJob` korrigieren.
2. Storno stabilisieren und bessere Fehlermeldungen im Cockpit anzeigen.
3. Internationalen Produktresolver einbauen.
4. Referenzfeld und Gewichtskorrektur umsetzen.
5. Adressvalidierung integrieren.
6. Tracking-Anzeigen und Mailregeln final testen.

## Teststrategie

- Feature-Tests fuer Controller-Endpunkte: Label erstellen, Storno, Tracking-Mail, Tracking-Update.
- Unit-Tests fuer Produktresolver, Gewichtskalkulation und Adressvalidierung.
- HTTP-Fakes fuer DHL API Responses inklusive Fehlerfaelle.
- Regression-Test fuer `V62KP` Payload.
- Command-Test fuer `dhl:update-tracking --send-emails`.

## Legacy-Dokumentation

Die bisherigen Markdown-Dateien wurden nach `dev/dhl-modul/legacy` verschoben. Sie bleiben als Historie erhalten, sind aber nicht mehr die aktuelle Arbeitsgrundlage.
