update 20.10.2025

This commit is contained in:
Kevin Adametz 2025-10-20 17:42:08 +02:00
parent 8c11130b5d
commit a939cd51ef
616 changed files with 84821 additions and 4121 deletions

View file

@ -11,16 +11,19 @@ use Acme\Dhl\Models\DhlShipment;
use App\Models\ShoppingOrder;
use App\Services\DhlModalService;
use App\Services\DhlShipmentService;
use App\Services\DhlTrackingService;
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\Storage;
use Illuminate\View\View;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Session;
use Yajra\DataTables\Facades\DataTables;
use ZipArchive;
// Import new DHL package and SettingController
use Acme\Dhl\DhlManager;
@ -141,11 +144,15 @@ class DhlShipmentController extends Controller
if ($request->filled('search')) {
$search = $request->get('search');
$query->where(function ($q) use ($search) {
$q->where('dhl_shipment_no', 'LIKE', "%{$search}%")
->orWhere('id', 'LIKE', "%{$search}%")
->orWhereHas('shoppingOrder', function ($orderQuery) use ($search) {
$orderQuery->where('id', $search);
});
// Search in shipment fields
$q->where('order_id', 'LIKE', "%{$search}%")
->orWhere('dhl_shipment_no', 'LIKE', "%{$search}%")
->orWhere('routing_code', 'LIKE', "%{$search}%")
->orWhere('related_shipment_id', 'LIKE', "%{$search}%")
->orWhere('billing_number', 'LIKE', "%{$search}%")
->orWhere('firstname', 'LIKE', "%{$search}%")
->orWhere('lastname', 'LIKE', "%{$search}%")
->orWhere('company', 'LIKE', "%{$search}%");
});
}
@ -170,11 +177,7 @@ class DhlShipmentController extends Controller
return '<span class="text-muted">N/A</span>';
})
->addColumn('customer', function ($shipment) {
if ($shipment->shoppingOrder && $shipment->shoppingOrder->shopping_user) {
return e($shipment->shoppingOrder->shopping_user->billing_firstname) . ' ' . e($shipment->shoppingOrder->shopping_user->billing_lastname) .
'<br><small class="text-muted">' . e($shipment->shoppingOrder->shopping_user->billing_email) . '</small>';
}
return '<span class="text-muted">Unbekannt</span>';
return $shipment->firstname . ' ' . $shipment->lastname;
})
->editColumn('dhl_shipment_no', function ($shipment) {
return $shipment->dhl_shipment_no ? '<code class="text-success">' . e($shipment->dhl_shipment_no) . '</code>' : '<span class="text-muted">-</span>';
@ -210,12 +213,14 @@ 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>';
}
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;
})
@ -465,27 +470,27 @@ class DhlShipmentController extends Controller
public function updateTracking(DhlShipment $shipment): JsonResponse
{
try {
if (!$shipment->tracking_number) {
if (!$shipment->dhl_shipment_no) {
return response()->json([
'success' => false,
'message' => 'Keine Tracking-Nummer verfügbar.'
'message' => 'Keine DHL-Sendungsnummer verfügbar.'
], 422);
}
// Dispatch tracking update job
TrackShipmentJob::dispatch($shipment, ['auto_retrack' => false]);
// Use DhlTrackingService (handles queue/sync automatically based on config)
$dhlTrackingService = new DhlTrackingService();
$result = $dhlTrackingService->updateTracking($shipment, ['auto_retrack' => false]);
Log::info('[DHL Controller] Tracking update job dispatched', [
Log::info('[DHL Controller] Tracking update processed', [
'shipment_id' => $shipment->id,
'tracking_number' => $shipment->tracking_number,
'dhl_shipment_no' => $shipment->dhl_shipment_no,
'queued' => $result['queued'] ?? false,
'success' => $result['success'] ?? false,
]);
return response()->json([
'success' => true,
'message' => 'Tracking-Informationen werden aktualisiert...'
]);
return response()->json($result);
} catch (Exception $e) {
Log::error('[DHL Controller] Failed to dispatch tracking update', [
Log::error('[DHL Controller] Failed to process tracking update', [
'error' => $e->getMessage(),
'shipment_id' => $shipment->id,
]);
@ -511,11 +516,9 @@ class DhlShipmentController extends Controller
}
$labelContent = Storage::get($shipment->label_path);
$filename = sprintf(
'dhl-label-%s-%s.pdf',
$shipment->type,
$shipment->shipment_number ?: $shipment->id
);
// Generate descriptive filename
$filename = $this->generateLabelFilename($shipment);
return response($labelContent, 200)
->header('Content-Type', 'application/pdf')
@ -531,13 +534,63 @@ 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
{
// Load order with customer data
$customerName = $shipment->firstname . '_' . $shipment->lastname;
if ($shipment->company) {
$customerName = $shipment->company;
}
// Clean customer name for filename (remove special characters)
$customerName = preg_replace('/[^a-zA-Z0-9\-]/', '', $customerName);
$customerName = preg_replace('/-+/', '-', $customerName); // Remove multiple dashes
$customerName = trim($customerName, '-'); // Remove leading/trailing dashes
// Get shipment number
$shipmentNumber = $shipment->dhl_shipment_no ?: $shipment->id;
// Get creation date
$date = $shipment->created_at->format('d_m_Y');
// Build filename
$filename = sprintf(
'DHL-%s-%s-%s.pdf',
$customerName,
$shipmentNumber,
$date
);
// Ensure filename is not too long (max 255 characters)
if (strlen($filename) > 255) {
$maxCustomerLength = 255 - strlen('DHL--' . $shipmentNumber . '-' . $date . '.pdf');
$customerName = substr($customerName, 0, max(10, $maxCustomerLength));
$filename = sprintf(
'DHL-%s-%s-%s.pdf',
$customerName,
$shipmentNumber,
$date
);
}
return $filename;
}
/**
* Batch operations (multiple shipments)
*
* @param Request $request
* @return JsonResponse
* @return JsonResponse|BinaryFileResponse
*/
public function batchAction(Request $request): JsonResponse
public function batchAction(Request $request)
{
try {
$request->validate([
@ -550,6 +603,7 @@ class DhlShipmentController extends Controller
$action = $request->action;
$processed = 0;
$errors = [];
$labels = []; // For batch label download
foreach ($shipmentIds as $shipmentId) {
try {
@ -566,17 +620,31 @@ class DhlShipmentController extends Controller
break;
case 'update_tracking':
if ($shipment->tracking_number) {
TrackShipmentJob::dispatch($shipment, ['auto_retrack' => false]);
$processed++;
if ($shipment->dhl_shipment_no) {
$dhlTrackingService = new DhlTrackingService();
$trackingResult = $dhlTrackingService->updateTracking($shipment, ['auto_retrack' => false]);
if ($trackingResult['success']) {
$processed++;
} else {
$errors[] = "Sendung #{$shipment->id}: " . $trackingResult['message'];
}
} else {
$errors[] = "Sendung {$shipment->shipment_number} hat keine Tracking-Nummer.";
$errors[] = "Sendung #{$shipment->id} hat keine DHL-Sendungsnummer.";
}
break;
case 'download_labels':
// This would require ZIP creation - implement if needed
$errors[] = "Stapel-Download noch nicht implementiert.";
if ($shipment->label_path && Storage::exists($shipment->label_path)) {
$labels[] = [
'shipment' => $shipment,
'filename' => $this->generateLabelFilename($shipment),
'path' => $shipment->label_path
];
$processed++;
} else {
$errors[] = "Sendung #{$shipment->id} hat kein verfügbares Label.";
}
break;
}
} catch (Exception $e) {
@ -584,6 +652,11 @@ class DhlShipmentController extends Controller
}
}
// Handle batch label download
if ($action === 'download_labels' && !empty($labels)) {
return $this->createLabelsZip($labels);
}
Log::info('[DHL Controller] Batch action executed', [
'action' => $action,
'processed' => $processed,
@ -623,7 +696,7 @@ class DhlShipmentController extends Controller
]);
try {
$shipment = DhlShipment::where('tracking_number', $request->tracking_number)->first();
$shipment = DhlShipment::where('dhl_shipment_no', $request->tracking_number)->first();
if (!$shipment) {
return response()->json([
@ -632,13 +705,15 @@ class DhlShipmentController extends Controller
], 404);
}
// Dispatch tracking update
TrackShipmentJob::dispatch($shipment, ['auto_retrack' => false]);
// Use DhlTrackingService for tracking update
$dhlTrackingService = new DhlTrackingService();
$trackingResult = $dhlTrackingService->updateTracking($shipment, ['auto_retrack' => false]);
return response()->json([
'success' => true,
'success' => $trackingResult['success'],
'message' => $trackingResult['message'],
'data' => [
'tracking_number' => $shipment->tracking_number,
'dhl_shipment_no' => $shipment->dhl_shipment_no,
'status' => $shipment->status,
'tracking_status' => $shipment->tracking_status,
'last_tracked_at' => $shipment->last_tracked_at?->format('d.m.Y H:i'),
@ -659,4 +734,65 @@ class DhlShipmentController extends Controller
return view('public.tracking');
}
/**
* Create ZIP file with multiple labels
*
* @param array $labels Array of label data
* @return Response|BinaryFileResponse
*/
private function createLabelsZip(array $labels)
{
try {
$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'))) {
mkdir(storage_path('app/temp'), 0755, true);
}
if ($zip->open($zipPath, ZipArchive::CREATE) !== TRUE) {
throw new Exception('ZIP-Datei konnte nicht erstellt werden.');
}
$addedFiles = 0;
foreach ($labels as $labelData) {
$shipment = $labelData['shipment'];
$filename = $labelData['filename'];
$filePath = $labelData['path'];
if (Storage::exists($filePath)) {
$content = Storage::get($filePath);
$zip->addFromString($filename, $content);
$addedFiles++;
}
}
$zip->close();
if ($addedFiles === 0) {
throw new Exception('Keine Labels konnten zur ZIP-Datei hinzugefügt werden.');
}
Log::info('[DHL Controller] Labels ZIP created', [
'zip_file' => $zipFilename,
'files_count' => $addedFiles,
'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)
]);
return response()->json([
'success' => false,
'message' => 'Fehler beim Erstellen der ZIP-Datei: ' . $e->getMessage()
], 500);
}
}
}