23-01-2026
This commit is contained in:
parent
a939cd51ef
commit
a8b395e20d
248 changed files with 29342 additions and 4805 deletions
|
|
@ -2,12 +2,11 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Jobs\CancelShipmentJob;
|
||||
use App\Jobs\CreateReturnLabelJob;
|
||||
use App\Jobs\TrackShipmentJob;
|
||||
// Old DHL model replaced with new package model
|
||||
use Acme\Dhl\Models\DhlShipment;
|
||||
use App\Jobs\CancelShipmentJob;
|
||||
// Old DHL model replaced with new package model
|
||||
use App\Jobs\CreateReturnLabelJob;
|
||||
use App\Mail\MailDhlTracking;
|
||||
use App\Models\ShoppingOrder;
|
||||
use App\Services\DhlModalService;
|
||||
use App\Services\DhlShipmentService;
|
||||
|
|
@ -16,21 +15,18 @@ use Exception;
|
|||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\View\View;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
// Import new DHL package and SettingController
|
||||
use Yajra\DataTables\Facades\DataTables;
|
||||
use ZipArchive;
|
||||
|
||||
// Import new DHL package and SettingController
|
||||
use Acme\Dhl\DhlManager;
|
||||
|
||||
/**
|
||||
* DHL Shipment Controller
|
||||
*
|
||||
*
|
||||
* Handles all DHL shipment operations including creation, cancellation,
|
||||
* tracking, and return labels. Provides both web interface and AJAX endpoints.
|
||||
*/
|
||||
|
|
@ -54,7 +50,7 @@ class DhlShipmentController extends Controller
|
|||
{
|
||||
try {
|
||||
// Get DHL configuration with admin settings
|
||||
$settingController = new \App\Http\Controllers\SettingController();
|
||||
$settingController = new \App\Http\Controllers\SettingController;
|
||||
$dhlConfig = $settingController->getDhlConfig();
|
||||
|
||||
// Create DhlClient with merged configuration
|
||||
|
|
@ -74,34 +70,31 @@ class DhlShipmentController extends Controller
|
|||
'message' => 'DHL API Verbindung erfolgreich getestet!',
|
||||
'details' => [
|
||||
'base_url' => $dhlConfig['base_url'],
|
||||
'using_admin_config' => !empty($dhlConfig['api_key'])
|
||||
]
|
||||
'using_admin_config' => ! empty($dhlConfig['api_key']),
|
||||
],
|
||||
];
|
||||
} else {
|
||||
$result = [
|
||||
'success' => false,
|
||||
'message' => 'DHL API Verbindung fehlgeschlagen. Prüfen Sie Ihre Zugangsdaten.'
|
||||
'message' => 'DHL API Verbindung fehlgeschlagen. Prüfen Sie Ihre Zugangsdaten.',
|
||||
];
|
||||
}
|
||||
|
||||
return response()->json($result);
|
||||
} catch (Exception $e) {
|
||||
Log::error('[DHL Controller] Test login failed', [
|
||||
'error' => $e->getMessage()
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'DHL API Test fehlgeschlagen: ' . $e->getMessage()
|
||||
'message' => 'DHL API Test fehlgeschlagen: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the DHL Cockpit (main overview)
|
||||
*
|
||||
* @param Request $request
|
||||
* @return View
|
||||
*/
|
||||
public function index(Request $request): View
|
||||
{
|
||||
|
|
@ -118,9 +111,6 @@ class DhlShipmentController extends Controller
|
|||
|
||||
/**
|
||||
* Provides data for the DHL Cockpit DataTable.
|
||||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function datatable(Request $request): JsonResponse
|
||||
{
|
||||
|
|
@ -161,19 +151,22 @@ class DhlShipmentController extends Controller
|
|||
return '<label class="custom-control custom-checkbox mb-0"><input type="checkbox" class="custom-control-input shipment-checkbox" value="' . $shipment->id . '"><span class="custom-control-label"></span></label>';
|
||||
})
|
||||
->editColumn('id', function ($shipment) {
|
||||
return '<a href="' . route('admin.dhl.show', $shipment) . '" class="text-primary font-weight-semibold">#' . $shipment->id . '</a>';
|
||||
$class = $shipment->type === 'return' ? 'text-warning font-weight-bold' : 'text-primary font-weight-semibold';
|
||||
$icon = $shipment->type === 'return' ? '<i class="fas fa-undo mr-1"></i>' : '';
|
||||
return '<a href="' . route('admin.dhl.show', $shipment) . '" class="' . $class . '">' . $icon . '#' . $shipment->id . '</a>';
|
||||
})
|
||||
->addColumn('type', function ($shipment) {
|
||||
if ($shipment->type == 'outbound') {
|
||||
return '<span class="badge badge-primary"><i class="fas fa-arrow-right"></i> Ausgehend</span>';
|
||||
} else {
|
||||
return '<span class="badge badge-info"><i class="fas fa-undo"></i> Retoure</span>';
|
||||
return '<span class="badge badge-warning" style="font-size: 0.9rem; font-weight: 600;"><i class="fas fa-undo"></i> RETOURE</span>';
|
||||
}
|
||||
})
|
||||
->addColumn('order', function ($shipment) {
|
||||
if ($shipment->order_id) {
|
||||
return '<a href="' . route('admin_sales_customers_detail', $shipment->order_id) . '" class="text-primary">#' . $shipment->order_id . '</a>';
|
||||
}
|
||||
|
||||
return '<span class="text-muted">N/A</span>';
|
||||
})
|
||||
->addColumn('customer', function ($shipment) {
|
||||
|
|
@ -184,14 +177,15 @@ class DhlShipmentController extends Controller
|
|||
})
|
||||
->addColumn('status', function ($shipment) {
|
||||
$statusMap = [
|
||||
'pending' => ['class' => 'warning', 'text' => 'Wartend'],
|
||||
'created' => ['class' => 'success', 'text' => 'Erstellt'],
|
||||
'shipped' => ['class' => 'primary', 'text' => 'Versendet'],
|
||||
'pending' => ['class' => 'warning', 'text' => 'Wartend'],
|
||||
'created' => ['class' => 'success', 'text' => 'Erstellt'],
|
||||
'shipped' => ['class' => 'primary', 'text' => 'Versendet'],
|
||||
'delivered' => ['class' => 'info', 'text' => 'Zugestellt'],
|
||||
'cancelled' => ['class' => 'secondary', 'text' => 'Storniert'],
|
||||
'failed' => ['class' => 'danger', 'text' => 'Fehler'],
|
||||
'failed' => ['class' => 'danger', 'text' => 'Fehler'],
|
||||
];
|
||||
$statusInfo = $statusMap[$shipment->status] ?? ['class' => 'light', 'text' => e($shipment->status)];
|
||||
|
||||
return '<span class="badge badge-' . $statusInfo['class'] . '">' . $statusInfo['text'] . '</span>';
|
||||
})
|
||||
->addColumn('tracking_status', function ($shipment) {
|
||||
|
|
@ -199,6 +193,7 @@ class DhlShipmentController extends Controller
|
|||
return '<small class="text-muted">' . e($shipment->tracking_status) . '</small>' .
|
||||
($shipment->last_tracked_at ? '<br><small class="text-muted">' . $shipment->last_tracked_at->format('d.m.Y H:i') . '</small>' : '');
|
||||
}
|
||||
|
||||
return '<span class="text-muted">-</span>';
|
||||
})
|
||||
->editColumn('weight_kg', function ($shipment) {
|
||||
|
|
@ -213,25 +208,36 @@ class DhlShipmentController extends Controller
|
|||
if ($shipment->label_path) {
|
||||
$buttons .= '<a href="' . route('admin.dhl.download-label', $shipment) . '" class="btn btn-sm btn-outline-success" data-toggle="tooltip" title="Label herunterladen"><i class="fas fa-download"></i></a>';
|
||||
}
|
||||
/* Todo: Add tracking button
|
||||
if ($shipment->canCancel()) {
|
||||
$buttons .= '<button type="button" class="btn btn-sm btn-outline-warning cancel-shipment-btn" data-shipment-id="' . $shipment->id . '" data-toggle="tooltip" title="Sendung stornieren"><i class="fas fa-ban"></i></button>';
|
||||
// Email button
|
||||
if ($shipment->dhl_shipment_no && $shipment->canSendTrackingEmail()) {
|
||||
$emailTitle = $shipment->wasTrackingEmailSent()
|
||||
? 'Tracking-E-Mail erneut senden (gesendet: ' . $shipment->tracking_email_sent_at->format('d.m.Y H:i') . ')'
|
||||
: 'Tracking-E-Mail senden';
|
||||
$emailClass = $shipment->wasTrackingEmailSent() ? 'btn-success' : 'btn-outline-info';
|
||||
$buttons .= '<button type="button" class="btn btn-sm ' . $emailClass . ' send-tracking-email-btn" data-shipment-id="' . $shipment->id . '" data-toggle="tooltip" title="' . $emailTitle . '"><i class="fas fa-envelope"></i></button>';
|
||||
}
|
||||
if ($shipment->type == 'outbound' && !$shipment->returns()->count()) {
|
||||
// Cancel button
|
||||
if ($shipment->canCancel()) {
|
||||
$buttons .= '<button type="button" class="btn btn-sm btn-outline-danger cancel-shipment-btn" data-shipment-id="' . $shipment->id . '" data-toggle="tooltip" title="Sendung stornieren"><i class="fas fa-ban"></i></button>';
|
||||
}
|
||||
// Return label button
|
||||
if ($shipment->type == 'outbound' && ! $shipment->returns()->count()) {
|
||||
$buttons .= '<button type="button" class="btn btn-sm btn-outline-info create-return-btn" data-shipment-id="' . $shipment->id . '" data-toggle="tooltip" title="Retourenlabel erstellen"><i class="fas fa-undo"></i></button>';
|
||||
}
|
||||
*/
|
||||
$buttons .= '</div>';
|
||||
|
||||
return $buttons;
|
||||
})
|
||||
->addColumn('DT_RowClass', function ($shipment) {
|
||||
return $shipment->type === 'return' ? 'return-shipment' : '';
|
||||
})
|
||||
->rawColumns(['checkbox', 'id', 'type', 'order', 'customer', 'dhl_shipment_no', 'status', 'tracking_status', 'actions'])
|
||||
->make(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the form for creating a new shipment
|
||||
*
|
||||
* @param ShoppingOrder $order
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function create(ShoppingOrder $order): View|\Illuminate\Http\RedirectResponse
|
||||
|
|
@ -251,21 +257,18 @@ class DhlShipmentController extends Controller
|
|||
|
||||
/**
|
||||
* Store a new shipment (async via queue)
|
||||
*
|
||||
* @param Request $request
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(Request $request): JsonResponse
|
||||
{
|
||||
try {
|
||||
// Use DhlModalService for validation
|
||||
$dhlModalService = new DhlModalService();
|
||||
$dhlModalService = new DhlModalService;
|
||||
$validationResult = $dhlModalService->validateShipmentData($request->all());
|
||||
|
||||
if (!$validationResult['valid']) {
|
||||
if (! $validationResult['valid']) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Validierungsfehler: ' . implode(', ', $validationResult['errors'])
|
||||
'message' => 'Validierungsfehler: ' . implode(', ', $validationResult['errors']),
|
||||
], 422);
|
||||
}
|
||||
|
||||
|
|
@ -286,6 +289,8 @@ class DhlShipmentController extends Controller
|
|||
'shipping_city' => 'required|string|max:50',
|
||||
'shipping_country_id' => 'required|exists:countries,id',
|
||||
'shipping_phone' => 'nullable|string|max:20',
|
||||
'shipping_email' => 'required|email|max:100',
|
||||
'shipping_postnumber' => 'nullable|string|max:20',
|
||||
]);
|
||||
|
||||
$order = ShoppingOrder::findOrFail($request->order_id);
|
||||
|
|
@ -313,11 +318,11 @@ class DhlShipmentController extends Controller
|
|||
'auto_track' => $request->get('auto_track', true),
|
||||
'shipping_address' => $shippingAddress,
|
||||
'services' => $request->get('services', []),
|
||||
'dimensions' => $request->only(['length', 'width', 'height'])
|
||||
'dimensions' => $request->only(['length', 'width', 'height']),
|
||||
];
|
||||
|
||||
// Use DhlShipmentService (handles queue/sync automatically based on config)
|
||||
$dhlShipmentService = new DhlShipmentService();
|
||||
$dhlShipmentService = new DhlShipmentService;
|
||||
$result = $dhlShipmentService->createShipment($order, (float) $request->weight, $options);
|
||||
|
||||
Log::info('[DHL Controller] Shipment creation processed', [
|
||||
|
|
@ -336,16 +341,13 @@ class DhlShipmentController extends Controller
|
|||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Erstellen der Sendung: ' . $e->getMessage()
|
||||
'message' => 'Fehler beim Erstellen der Sendung: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the specified shipment
|
||||
*
|
||||
* @param DhlShipment $shipment
|
||||
* @return View
|
||||
*/
|
||||
public function show(DhlShipment $shipment): View
|
||||
{
|
||||
|
|
@ -356,57 +358,49 @@ class DhlShipmentController extends Controller
|
|||
|
||||
/**
|
||||
* Cancel the specified shipment
|
||||
*
|
||||
* @param Request $request
|
||||
* @param DhlShipment $shipment
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function cancel(Request $request, DhlShipment $shipment): JsonResponse
|
||||
{
|
||||
try {
|
||||
// Validate cancellation is possible
|
||||
if (!$shipment->canCancel()) {
|
||||
if (! $shipment->canCancel()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Diese Sendung kann nicht mehr storniert werden.'
|
||||
'message' => 'Diese Sendung kann nicht mehr storniert werden.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
// Dispatch cancellation job
|
||||
// Use DhlShipmentService (handles queue/sync automatically based on config)
|
||||
$options = [
|
||||
'priority' => $request->get('priority', 'normal')
|
||||
'priority' => $request->get('priority', 'normal'),
|
||||
];
|
||||
|
||||
CancelShipmentJob::dispatch($shipment, $options);
|
||||
$dhlShipmentService = new DhlShipmentService;
|
||||
$result = $dhlShipmentService->cancelShipment($shipment, $options);
|
||||
|
||||
Log::info('[DHL Controller] Shipment cancellation job dispatched', [
|
||||
Log::info('[DHL Controller] Shipment cancellation processed', [
|
||||
'shipment_id' => $shipment->id,
|
||||
'shipment_number' => $shipment->shipment_number,
|
||||
'dhl_shipment_no' => $shipment->dhl_shipment_no,
|
||||
'queued' => $result['queued'] ?? false,
|
||||
'success' => $result['success'] ?? false,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Sendung wird storniert...'
|
||||
]);
|
||||
return response()->json($result);
|
||||
} catch (Exception $e) {
|
||||
Log::error('[DHL Controller] Failed to dispatch shipment cancellation', [
|
||||
Log::error('[DHL Controller] Failed to process shipment cancellation', [
|
||||
'error' => $e->getMessage(),
|
||||
'shipment_id' => $shipment->id,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Stornieren der Sendung: ' . $e->getMessage()
|
||||
'message' => 'Fehler beim Stornieren der Sendung: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create return label for the specified shipment
|
||||
*
|
||||
* @param Request $request
|
||||
* @param DhlShipment $shipment
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function createReturnLabel(Request $request, DhlShipment $shipment): JsonResponse
|
||||
{
|
||||
|
|
@ -415,7 +409,7 @@ class DhlShipmentController extends Controller
|
|||
if ($shipment->type !== 'outbound') {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Retourenlabels können nur für ausgehende Sendungen erstellt werden.'
|
||||
'message' => 'Retourenlabels können nur für ausgehende Sendungen erstellt werden.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
|
|
@ -427,58 +421,156 @@ class DhlShipmentController extends Controller
|
|||
if ($existingReturn) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Für diese Sendung existiert bereits ein Retourenlabel.'
|
||||
'message' => 'Für diese Sendung existiert bereits ein Retourenlabel.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
// Dispatch return label creation job
|
||||
$options = [
|
||||
'auto_track' => $request->get('auto_track', false),
|
||||
'priority' => $request->get('priority', 'normal')
|
||||
];
|
||||
// Check DHL_USE_QUEUE configuration
|
||||
$settingController = new SettingController();
|
||||
$dhlConfig = $settingController->getDhlConfig();
|
||||
$useQueue = $dhlConfig['use_queue'] ?? false;
|
||||
|
||||
CreateReturnLabelJob::dispatch($shipment, $options);
|
||||
if ($useQueue) {
|
||||
// Dispatch return label creation job
|
||||
$options = [
|
||||
'auto_track' => $request->get('auto_track', false),
|
||||
'priority' => $request->get('priority', 'normal'),
|
||||
];
|
||||
|
||||
Log::info('[DHL Controller] Return label creation job dispatched', [
|
||||
'original_shipment_id' => $shipment->id,
|
||||
'shipment_number' => $shipment->shipment_number,
|
||||
]);
|
||||
CreateReturnLabelJob::dispatch($shipment, $options);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Retourenlabel wird erstellt...'
|
||||
]);
|
||||
Log::info('[DHL Controller] Return label creation job dispatched', [
|
||||
'original_shipment_id' => $shipment->id,
|
||||
'shipment_number' => $shipment->dhl_shipment_no,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => 'Retourenlabel wird im Hintergrund erstellt. Dies kann einige Sekunden dauern.',
|
||||
]);
|
||||
} else {
|
||||
// Create synchronously
|
||||
$result = $this->createReturnLabelSync($shipment);
|
||||
|
||||
return response()->json($result);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Log::error('[DHL Controller] Failed to dispatch return label creation', [
|
||||
Log::error('[DHL Controller] Failed to create return label', [
|
||||
'error' => $e->getMessage(),
|
||||
'shipment_id' => $shipment->id,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Erstellen des Retourenlabels: ' . $e->getMessage()
|
||||
'message' => 'Fehler beim Erstellen des Retourenlabels: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create return label synchronously
|
||||
*/
|
||||
private function createReturnLabelSync(DhlShipment $shipment): array
|
||||
{
|
||||
try {
|
||||
Log::info('[DHL Controller] Creating return label synchronously', [
|
||||
'original_shipment_id' => $shipment->id,
|
||||
]);
|
||||
|
||||
// Get DHL configuration
|
||||
$settingController = new SettingController();
|
||||
$dhlConfig = $settingController->getDhlConfig();
|
||||
|
||||
// Initialize DHL client
|
||||
$dhlClient = new \Acme\Dhl\Support\DhlClient(
|
||||
$dhlConfig['base_url'],
|
||||
$dhlConfig['api_key'],
|
||||
$dhlConfig['username'],
|
||||
$dhlConfig['password']
|
||||
);
|
||||
|
||||
// Use ReturnsService instead of ShippingService
|
||||
$returnsService = new \Acme\Dhl\Services\ReturnsService($dhlClient);
|
||||
|
||||
// Prepare return label data
|
||||
$order = $shipment->shoppingOrder;
|
||||
$recipient = $shipment->recipient ?? [];
|
||||
|
||||
$returnData = [
|
||||
'order_id' => $order->id,
|
||||
'original_shipment_id' => $shipment->id,
|
||||
'weight_kg' => $shipment->weight_kg,
|
||||
'label_format' => $shipment->label_format ?? 'PDF',
|
||||
|
||||
// Shipper: Customer sends back to us (swap addresses)
|
||||
'shipper' => [
|
||||
'name' => trim(($recipient['firstname'] ?? '') . ' ' . ($recipient['lastname'] ?? '')),
|
||||
'name2' => $recipient['company'] ?? '',
|
||||
'street' => $recipient['street'] ?? '',
|
||||
'houseNumber' => $recipient['houseNumber'] ?? '',
|
||||
'postalCode' => $recipient['postalCode'] ?? '',
|
||||
'city' => $recipient['city'] ?? '',
|
||||
'country' => $recipient['country'] ?? 'DEU',
|
||||
'email' => $recipient['email'] ?? '',
|
||||
'phone' => $recipient['phone'] ?? '',
|
||||
],
|
||||
|
||||
// Consignee: Our warehouse
|
||||
'consignee' => [
|
||||
'name' => $dhlConfig['sender']['company'] ?? 'mivita care gmbh',
|
||||
'name2' => $dhlConfig['sender']['name'] ?? '',
|
||||
'street' => $dhlConfig['sender']['street'] ?? 'Leinfeld',
|
||||
'houseNumber' => $dhlConfig['sender']['house_number'] ?? '2',
|
||||
'postalCode' => $dhlConfig['sender']['postalCode'] ?? '87755',
|
||||
'city' => $dhlConfig['sender']['city'] ?? 'Kirchhaslach',
|
||||
'country' => $dhlConfig['sender']['country'] ?? 'DEU',
|
||||
'email' => $dhlConfig['sender']['email'] ?? 'versand@mivita.care',
|
||||
'phone' => $dhlConfig['sender']['phone'] ?? '+49 123 456789',
|
||||
],
|
||||
];
|
||||
|
||||
// Create the return label using ReturnsService
|
||||
$result = $returnsService->createReturn($returnData);
|
||||
|
||||
Log::info('[DHL Controller] Return label created successfully (sync)', [
|
||||
'original_shipment_id' => $shipment->id,
|
||||
'return_shipment_number' => $result['returnNumber'] ?? 'N/A',
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => true,
|
||||
'message' => 'Retourenlabel wurde erfolgreich erstellt!',
|
||||
'shipment_number' => $result['returnNumber'] ?? null,
|
||||
'return_shipment' => $result['returnShipment'] ?? null,
|
||||
];
|
||||
} catch (Exception $e) {
|
||||
Log::error('[DHL Controller] Return label creation failed (sync)', [
|
||||
'original_shipment_id' => $shipment->id,
|
||||
'error' => $e->getMessage(),
|
||||
]);
|
||||
|
||||
return [
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Erstellen des Retourenlabels: ' . $e->getMessage(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update tracking status for the specified shipment
|
||||
*
|
||||
* @param DhlShipment $shipment
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function updateTracking(DhlShipment $shipment): JsonResponse
|
||||
{
|
||||
try {
|
||||
if (!$shipment->dhl_shipment_no) {
|
||||
if (! $shipment->dhl_shipment_no) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Keine DHL-Sendungsnummer verfügbar.'
|
||||
'message' => 'Keine DHL-Sendungsnummer verfügbar.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
// Use DhlTrackingService (handles queue/sync automatically based on config)
|
||||
$dhlTrackingService = new DhlTrackingService();
|
||||
$dhlTrackingService = new DhlTrackingService;
|
||||
$result = $dhlTrackingService->updateTracking($shipment, ['auto_retrack' => false]);
|
||||
|
||||
Log::info('[DHL Controller] Tracking update processed', [
|
||||
|
|
@ -497,21 +589,108 @@ class DhlShipmentController extends Controller
|
|||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Aktualisieren der Tracking-Informationen: ' . $e->getMessage()
|
||||
'message' => 'Fehler beim Aktualisieren der Tracking-Informationen: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send tracking email to customer (supports multiple shipments per order)
|
||||
*/
|
||||
public function sendTrackingEmail(DhlShipment $shipment): JsonResponse
|
||||
{
|
||||
try {
|
||||
// Check if shipment has tracking number
|
||||
if (! $shipment->dhl_shipment_no) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Keine DHL-Sendungsnummer verfügbar.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
// Check if shipment can send email
|
||||
if (! $shipment->canSendTrackingEmail()) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'E-Mail kann nicht gesendet werden. Bestellung oder E-Mail-Adresse fehlt.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
$order = $shipment->shoppingOrder;
|
||||
|
||||
// Determine recipient email: prefer shipment email, fallback to shopping user email
|
||||
$recipientEmail = null;
|
||||
if (! empty($shipment->email)) {
|
||||
$recipientEmail = $shipment->email;
|
||||
} elseif ($order->shopping_user && ! empty($order->shopping_user->email)) {
|
||||
$recipientEmail = $order->shopping_user->email;
|
||||
}
|
||||
|
||||
if (! $recipientEmail) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Keine Empfänger-E-Mail-Adresse verfügbar.',
|
||||
], 422);
|
||||
}
|
||||
|
||||
// Collect all shipments for this order that have tracking numbers
|
||||
$allShipments = DhlShipment::where('order_id', $order->id)
|
||||
->whereNotNull('dhl_shipment_no')
|
||||
->whereIn('status', ['created', 'in_transit', 'out_for_delivery'])
|
||||
->orderBy('created_at', 'asc')
|
||||
->get();
|
||||
|
||||
// If no shipments found, use only the current one
|
||||
if ($allShipments->isEmpty()) {
|
||||
$allShipments = collect([$shipment]);
|
||||
}
|
||||
|
||||
// Send email with all shipments
|
||||
Mail::to($recipientEmail)->send(new MailDhlTracking($allShipments, $order));
|
||||
|
||||
// Mark all included shipments as sent
|
||||
foreach ($allShipments as $s) {
|
||||
$s->markTrackingEmailSent('manual');
|
||||
}
|
||||
|
||||
Log::info('[DHL Controller] Tracking email sent', [
|
||||
'shipment_ids' => $allShipments->pluck('id')->toArray(),
|
||||
'shipments_count' => $allShipments->count(),
|
||||
'dhl_shipment_nos' => $allShipments->pluck('dhl_shipment_no')->toArray(),
|
||||
'email' => $recipientEmail,
|
||||
'type' => 'manual',
|
||||
]);
|
||||
|
||||
$message = $allShipments->count() > 1
|
||||
? "Tracking-E-Mail mit {$allShipments->count()} Sendungen wurde erfolgreich an {$recipientEmail} gesendet."
|
||||
: "Tracking-E-Mail wurde erfolgreich an {$recipientEmail} gesendet.";
|
||||
|
||||
return response()->json([
|
||||
'success' => true,
|
||||
'message' => $message,
|
||||
'sent_at' => now()->format('d.m.Y H:i'),
|
||||
'shipments_count' => $allShipments->count(),
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
Log::error('[DHL Controller] Failed to send tracking email', [
|
||||
'error' => $e->getMessage(),
|
||||
'shipment_id' => $shipment->id,
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Senden der Tracking-E-Mail: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Download shipping label
|
||||
*
|
||||
* @param DhlShipment $shipment
|
||||
* @return Response
|
||||
*/
|
||||
public function downloadLabel(DhlShipment $shipment): Response
|
||||
{
|
||||
try {
|
||||
if (!$shipment->label_path || !Storage::exists($shipment->label_path)) {
|
||||
if (! $shipment->label_path || ! Storage::exists($shipment->label_path)) {
|
||||
abort(404, 'Versandlabel nicht gefunden.');
|
||||
}
|
||||
|
||||
|
|
@ -538,9 +717,6 @@ class DhlShipmentController extends Controller
|
|||
* Generate descriptive filename for DHL label
|
||||
* Format: DHL-Kundenname-Sendungsnummer-Datum.pdf
|
||||
* Example: DHL-Geraldine-Seebacher-0034043333301020015589177-15092025.pdf
|
||||
*
|
||||
* @param DhlShipment $shipment
|
||||
* @return string
|
||||
*/
|
||||
private function generateLabelFilename(DhlShipment $shipment): string
|
||||
{
|
||||
|
|
@ -586,8 +762,7 @@ class DhlShipmentController extends Controller
|
|||
|
||||
/**
|
||||
* Batch operations (multiple shipments)
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return JsonResponse|BinaryFileResponse
|
||||
*/
|
||||
public function batchAction(Request $request)
|
||||
|
|
@ -621,7 +796,7 @@ class DhlShipmentController extends Controller
|
|||
|
||||
case 'update_tracking':
|
||||
if ($shipment->dhl_shipment_no) {
|
||||
$dhlTrackingService = new DhlTrackingService();
|
||||
$dhlTrackingService = new DhlTrackingService;
|
||||
$trackingResult = $dhlTrackingService->updateTracking($shipment, ['auto_retrack' => false]);
|
||||
|
||||
if ($trackingResult['success']) {
|
||||
|
|
@ -639,7 +814,7 @@ class DhlShipmentController extends Controller
|
|||
$labels[] = [
|
||||
'shipment' => $shipment,
|
||||
'filename' => $this->generateLabelFilename($shipment),
|
||||
'path' => $shipment->label_path
|
||||
'path' => $shipment->label_path,
|
||||
];
|
||||
$processed++;
|
||||
} else {
|
||||
|
|
@ -653,7 +828,7 @@ class DhlShipmentController extends Controller
|
|||
}
|
||||
|
||||
// Handle batch label download
|
||||
if ($action === 'download_labels' && !empty($labels)) {
|
||||
if ($action === 'download_labels' && ! empty($labels)) {
|
||||
return $this->createLabelsZip($labels);
|
||||
}
|
||||
|
||||
|
|
@ -677,16 +852,13 @@ class DhlShipmentController extends Controller
|
|||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Fehler bei der Stapelverarbeitung: ' . $e->getMessage()
|
||||
'message' => 'Fehler bei der Stapelverarbeitung: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Public tracking page (for customers)
|
||||
*
|
||||
* @param Request $request
|
||||
* @return View|JsonResponse
|
||||
*/
|
||||
public function track(Request $request): View|JsonResponse
|
||||
{
|
||||
|
|
@ -698,15 +870,15 @@ class DhlShipmentController extends Controller
|
|||
try {
|
||||
$shipment = DhlShipment::where('dhl_shipment_no', $request->tracking_number)->first();
|
||||
|
||||
if (!$shipment) {
|
||||
if (! $shipment) {
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Sendung nicht gefunden.'
|
||||
'message' => 'Sendung nicht gefunden.',
|
||||
], 404);
|
||||
}
|
||||
|
||||
// Use DhlTrackingService for tracking update
|
||||
$dhlTrackingService = new DhlTrackingService();
|
||||
$dhlTrackingService = new DhlTrackingService;
|
||||
$trackingResult = $dhlTrackingService->updateTracking($shipment, ['auto_retrack' => false]);
|
||||
|
||||
return response()->json([
|
||||
|
|
@ -717,7 +889,7 @@ class DhlShipmentController extends Controller
|
|||
'status' => $shipment->status,
|
||||
'tracking_status' => $shipment->tracking_status,
|
||||
'last_tracked_at' => $shipment->last_tracked_at?->format('d.m.Y H:i'),
|
||||
]
|
||||
],
|
||||
]);
|
||||
} catch (Exception $e) {
|
||||
Log::error('[DHL Controller] Public tracking failed', [
|
||||
|
|
@ -727,7 +899,7 @@ class DhlShipmentController extends Controller
|
|||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Abrufen der Tracking-Informationen.'
|
||||
'message' => 'Fehler beim Abrufen der Tracking-Informationen.',
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
|
@ -737,23 +909,23 @@ class DhlShipmentController extends Controller
|
|||
|
||||
/**
|
||||
* Create ZIP file with multiple labels
|
||||
*
|
||||
* @param array $labels Array of label data
|
||||
*
|
||||
* @param array $labels Array of label data
|
||||
* @return Response|BinaryFileResponse
|
||||
*/
|
||||
private function createLabelsZip(array $labels)
|
||||
{
|
||||
try {
|
||||
$zip = new ZipArchive();
|
||||
$zip = new ZipArchive;
|
||||
$zipFilename = 'dhl_labels_' . date('Y-m-d_H-i-s') . '.zip';
|
||||
$zipPath = storage_path('app/temp/' . $zipFilename);
|
||||
|
||||
// Ensure temp directory exists
|
||||
if (!file_exists(storage_path('app/temp'))) {
|
||||
if (! file_exists(storage_path('app/temp'))) {
|
||||
mkdir(storage_path('app/temp'), 0755, true);
|
||||
}
|
||||
|
||||
if ($zip->open($zipPath, ZipArchive::CREATE) !== TRUE) {
|
||||
if ($zip->open($zipPath, ZipArchive::CREATE) !== true) {
|
||||
throw new Exception('ZIP-Datei konnte nicht erstellt werden.');
|
||||
}
|
||||
|
||||
|
|
@ -779,19 +951,19 @@ class DhlShipmentController extends Controller
|
|||
Log::info('[DHL Controller] Labels ZIP created', [
|
||||
'zip_file' => $zipFilename,
|
||||
'files_count' => $addedFiles,
|
||||
'total_labels' => count($labels)
|
||||
'total_labels' => count($labels),
|
||||
]);
|
||||
|
||||
return response()->download($zipPath, $zipFilename)->deleteFileAfterSend(true);
|
||||
} catch (Exception $e) {
|
||||
Log::error('[DHL Controller] Failed to create labels ZIP', [
|
||||
'error' => $e->getMessage(),
|
||||
'labels_count' => count($labels)
|
||||
'labels_count' => count($labels),
|
||||
]);
|
||||
|
||||
return response()->json([
|
||||
'success' => false,
|
||||
'message' => 'Fehler beim Erstellen der ZIP-Datei: ' . $e->getMessage()
|
||||
'message' => 'Fehler beim Erstellen der ZIP-Datei: ' . $e->getMessage(),
|
||||
], 500);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue