# 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())
    <button class="btn btn-outline-info dhl-create-return-btn">
        <i class="fas fa-undo"></i>
    </button>
@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!
