# DHL Return Label (Retourenlabel) - Dokumentation ## 📦 Übersicht Die Return Label Funktionalität ermöglicht es, automatisch Retourenlabels für ausgehende DHL-Sendungen zu erstellen. --- ## ✨ Features | Feature | Status | Beschreibung | |---------|--------|--------------| | **Button in allen Views** | ✅ | Überall wo DHL Sendungen angezeigt werden | | **Sync/Async Modus** | ✅ | Basierend auf `DHL_USE_QUEUE` Config | | **Adress-Tausch** | ✅ | Kunde wird Absender, Lager wird Empfänger | | **Duplikat-Prüfung** | ✅ | Nur ein Retourenlabel pro Sendung | | **Nur für Outbound** | ✅ | Nur für ausgehende Sendungen verfügbar | | **Package Integration** | ✅ | Nutzt neues `acme-laravel-dhl` Package | --- ## 📍 Button Standorte ### **1. Bestelldetails** ``` Admin → Bestellungen → Bestellung öffnen → DHL Sendungen Block → Aktionen [👁️] [📥] [🔄] [✉️] [🔙] [❌] ↑ Return Label Button ``` ### **2. DHL Cockpit** ``` Admin → DHL → Cockpit → DataTable → Aktionen-Spalte Gleiche Buttons wie in Bestelldetails ``` ### **3. DHL Detail-Seite** ``` Admin → DHL → Sendung öffnen → Aktionsbereich oben [🔙 Retourenlabel erstellen] ``` --- ## 🎯 Button-Bedingungen Der Button wird **nur** angezeigt wenn: ✅ `type` = 'outbound' (ausgehende Sendung) ✅ Keine Retoure existiert (`returns->count()` = 0) ✅ Admin-Bereich (nicht in User-Views) ```php @if($shipment->type === 'outbound' && !$shipment->returns->count()) @endif ``` --- ## 🔄 Workflow ### **Synchroner Modus** (`DHL_USE_QUEUE=false`) ``` 1. Admin klickt "Retourenlabel erstellen" 2. Bestätigung: "Möchten Sie ein Retourenlabel erstellen?" 3. → JA 4. Button: "⏳ Wird erstellt..." 5. API-Request direkt an DHL 6. ✅ Erfolg: "Retourenlabel wurde erfolgreich erstellt!" 7. Seite lädt neu 8. Neue Retoure ist sichtbar ``` ### **Asynchroner Modus** (`DHL_USE_QUEUE=true`) ``` 1. Admin klickt "Retourenlabel erstellen" 2. Bestätigung: "Möchten Sie ein Retourenlabel erstellen?" 3. → JA 4. Button: "⏳ Wird erstellt..." 5. Job wird in Queue gestellt 6. ✅ Erfolg: "Retourenlabel wird im Hintergrund erstellt" 7. Seite lädt neu 8. Worker verarbeitet Job 9. Retoure wird erstellt ``` --- ## 🔧 Technische Details ### **Controller-Methode** ```php // app/Http/Controllers/DhlShipmentController.php public function createReturnLabel(Request $request, DhlShipment $shipment): JsonResponse { // Validierung if ($shipment->type !== 'outbound') { ... } if (existingReturn) { ... } // Sync oder Async basierend auf Config if ($useQueue) { CreateReturnLabelJob::dispatch($shipment, $options); } else { $result = $this->createReturnLabelSync($shipment); } } ``` ### **Job-Klasse** ```php // app/Jobs/CreateReturnLabelJob.php class CreateReturnLabelJob implements ShouldQueue { public function handle(): void { // DHL Client initialisieren $dhlClient = new DhlClient(...); $shippingService = new ShippingService($dhlClient); // Return Label Daten vorbereiten (Adressen getauscht) $returnData = $this->prepareReturnLabelData($dhlConfig); // Label erstellen $result = $shippingService->createLabel($returnData); } } ``` ### **Adress-Tausch** Bei Return Labels werden die Adressen **automatisch getauscht**: | Feld | Ausgehende Sendung | Retoure | |------|-------------------|---------| | **Shipper (Absender)** | Unser Lager | **Kunde** | | **Consignee (Empfänger)** | **Kunde** | Unser Lager | ```php // Shipper: Kunde sendet zurück (aus original recipient) 'shipper' => [ 'name' => 'Max Mustermann', 'street' => 'Hauptstraße', 'postalCode' => '12345', 'city' => 'Berlin', ... ], // Consignee: Unser Lager empfängt (aus DHL settings) 'consignee' => [ 'name' => 'mivita care gmbh', 'street' => 'Leinfeld', 'postalCode' => '87755', 'city' => 'Kirchhaslach', ... ], ``` --- ## 🚨 Validierung & Fehlerbehandlung ### **Validierungs-Checks** ```php // 1. Nur für ausgehende Sendungen if ($shipment->type !== 'outbound') { return 'Retourenlabels können nur für ausgehende Sendungen erstellt werden.'; } // 2. Keine doppelte Retoure $existingReturn = DhlShipment::where('related_shipment_id', $shipment->id) ->where('type', 'return') ->first(); if ($existingReturn) { return 'Für diese Sendung existiert bereits ein Retourenlabel.'; } ``` ### **Fehlerbehandlung** | Szenario | Verhalten | |----------|-----------| | API Timeout | Job wird wiederholt (3x) | | Ungültige Adresse | Fehler + Log-Eintrag | | Netzwerkfehler | Job wird wiederholt | | 3 Fehlversuche | `failed()` Methode aufgerufen | --- ## 📊 Database Structure ### **Retoure-Beziehung** ```sql -- Ausgehende Sendung id: 123 type: 'outbound' related_shipment_id: NULL -- Zugehörige Retoure id: 456 type: 'return' related_shipment_id: 123 -- Verknüpfung zur Original-Sendung ``` ### **Model-Beziehungen** ```php // In DhlShipment Model public function returns(): HasMany { return $this->hasMany(self::class, 'related_shipment_id'); } public function relatedShipment(): BelongsTo { return $this->belongsTo(self::class, 'related_shipment_id'); } ``` --- ## 🧪 Testen ### **Test 1: Retourenlabel erstellen (Sync)** ```bash # 1. .env setzen DHL_USE_QUEUE=false # 2. Label erstellen für Bestellung Admin → Bestellung #45078 → DHL Label erstellen # 3. Return Label erstellen → Bestellung öffnen → DHL Sendungen Block → Button "🔙" klicken → Bestätigen → ✅ Retoure sollte sofort erscheinen ``` ### **Test 2: Retourenlabel erstellen (Async)** ```bash # 1. .env setzen DHL_USE_QUEUE=true # 2. Queue Worker starten php artisan queue:work # 3. Label erstellen Admin → Bestellung #45078 → Button "🔙" klicken # 4. Queue prüfen → Worker-Log anschauen → Retoure sollte nach wenigen Sekunden erscheinen ``` ### **Test 3: Duplikat-Prüfung** ```bash # 1. Retoure erstellen (wie Test 1) # 2. Erneut Button "🔙" klicken # → Fehler: "Für diese Sendung existiert bereits ein Retourenlabel." ``` --- ## 📝 Logs ### **Erfolgreiche Erstellung** ``` [DHL Controller] Return label creation job dispatched - original_shipment_id: 123 - shipment_number: 00340433333... [DHL Queue] Return label created successfully - original_shipment_id: 123 - return_shipment_number: 00340433444... ``` ### **Fehler** ``` [DHL Queue] Return label creation failed - original_shipment_id: 123 - error: "DHL API error: Invalid address" - attempt: 1/3 ``` --- ## ⚙️ Konfiguration ### **Queue-Modus** ```env # .env DHL_USE_QUEUE=true # Async (empfohlen für Produktion) DHL_USE_QUEUE=false # Sync (für Testing) ``` ### **Queue-Name** ```php // Normal Priority $job->onQueue('dhl-returns'); // High Priority $options['priority'] = 'high'; $job->onQueue('high-priority'); ``` --- ## 🔗 Routes ```php // routes/domains/crm.php Route::post('/shipment/{shipment}/return-label', 'DhlShipmentController@createReturnLabel') ->name('admin.dhl.create-return'); ``` --- ## 📋 Betroffene Dateien | Datei | Änderung | |-------|----------| | `app/Http/Controllers/DhlShipmentController.php` | `createReturnLabel()` + `createReturnLabelSync()` | | `app/Jobs/CreateReturnLabelJob.php` | Aktualisiert für neues Package | | `resources/views/admin/sales/_detail_dhl_shipments.blade.php` | Button + JavaScript Handler | | `resources/views/admin/dhl/show.blade.php` | Button aktiviert | | `resources/views/admin/dhl/cockpit.blade.php` | Button funktioniert bereits | --- ## ✅ Checkliste - [x] Button in allen DHL Views - [x] JavaScript Handler implementiert - [x] Controller-Methode mit Sync/Async - [x] Job für Queue-Verarbeitung - [x] Adress-Tausch korrekt - [x] Validierung & Fehlerbehandlung - [x] Duplikat-Prüfung - [x] Logging implementiert - [x] Dokumentation erstellt --- ## 🎉 Fertig! Die Return Label Funktionalität ist vollständig implementiert und einsatzbereit!