mivita/dev/2026-01-22/dhl-return-label-info.md
2026-02-20 17:55:06 +01:00

8 KiB

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)

@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

// 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

// 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
// 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

// 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

-- 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

// 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)

# 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)

# 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

# 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
DHL_USE_QUEUE=true   # Async (empfohlen für Produktion)
DHL_USE_QUEUE=false  # Sync (für Testing)

Queue-Name

// Normal Priority
$job->onQueue('dhl-returns');

// High Priority
$options['priority'] = 'high';
$job->onQueue('high-priority');

🔗 Routes

// 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

  • Button in allen DHL Views
  • JavaScript Handler implementiert
  • Controller-Methode mit Sync/Async
  • Job für Queue-Verarbeitung
  • Adress-Tausch korrekt
  • Validierung & Fehlerbehandlung
  • Duplikat-Prüfung
  • Logging implementiert
  • Dokumentation erstellt

🎉 Fertig!

Die Return Label Funktionalität ist vollständig implementiert und einsatzbereit!