27-05-2026 Update DHL Modul v2.0

This commit is contained in:
Kevin 2026-05-27 13:40:38 +00:00
parent 53bdba33cd
commit 036595be94
41 changed files with 3346 additions and 310 deletions

View file

@ -7,9 +7,13 @@ use App\Jobs\CancelShipmentJob;
// Old DHL model replaced with new package model
use App\Jobs\CreateReturnLabelJob;
use App\Mail\MailDhlTracking;
use App\Models\Country;
use App\Models\ShoppingOrder;
use App\Services\DhlAddressValidator;
use App\Services\DhlModalService;
use App\Services\DhlProductResolver;
use App\Services\DhlShipmentService;
use App\Services\DhlShipmentWeightCalculator;
use App\Services\DhlTrackingService;
use Exception;
use Illuminate\Http\JsonResponse;
@ -122,7 +126,12 @@ class DhlShipmentController extends Controller
$query->where('type', $request->get('type'));
}
if ($request->filled('status')) {
$query->where('status', $request->get('status'));
$status = DhlShipment::normalizeStatus($request->get('status'));
if ($status === 'canceled') {
$query->whereIn('status', ['canceled', 'cancelled']);
} else {
$query->where('status', $status);
}
}
if ($request->filled('date_from')) {
$query->whereDate('created_at', '>=', $request->get('date_from'));
@ -181,10 +190,11 @@ class DhlShipmentController extends Controller
'created' => ['class' => 'success', 'text' => 'Erstellt'],
'shipped' => ['class' => 'primary', 'text' => 'Versendet'],
'delivered' => ['class' => 'info', 'text' => 'Zugestellt'],
'cancelled' => ['class' => 'secondary', 'text' => 'Storniert'],
'canceled' => ['class' => 'secondary', 'text' => 'Storniert'],
'failed' => ['class' => 'danger', 'text' => 'Fehler'],
];
$statusInfo = $statusMap[$shipment->status] ?? ['class' => 'light', 'text' => e($shipment->status)];
$status = DhlShipment::normalizeStatus($shipment->status);
$statusInfo = $statusMap[$status] ?? ['class' => 'light', 'text' => e($shipment->status)];
return '<span class="badge badge-'.$statusInfo['class'].'">'.$statusInfo['text'].'</span>';
})
@ -277,6 +287,7 @@ class DhlShipmentController extends Controller
'order_id' => 'required|exists:shopping_orders,id',
'weight' => 'required|numeric|min:0.1|max:31.5',
'product_code' => 'sometimes|string',
'reference' => 'nullable|string|max:35',
'priority' => 'sometimes|string|in:normal,high',
'auto_track' => 'sometimes|boolean',
// Shipping address validation
@ -294,6 +305,10 @@ class DhlShipmentController extends Controller
]);
$order = ShoppingOrder::findOrFail($request->order_id);
$shipmentWeight = max(
(float) $request->weight,
(new DhlShipmentWeightCalculator)->calculate($order)
);
// Check if shipment already exists
/* $existingShipment = DhlShipment::where('shopping_order_id', $order->id)
@ -314,6 +329,7 @@ class DhlShipmentController extends Controller
// Prepare options for shipment creation
$options = [
'product_code' => $request->get('product_code', 'V01PAK'),
'reference' => $request->get('reference'),
'priority' => $request->get('priority', 'normal'),
'auto_track' => $request->get('auto_track', true),
'shipping_address' => $shippingAddress,
@ -323,15 +339,20 @@ class DhlShipmentController extends Controller
// Use DhlShipmentService (handles queue/sync automatically based on config)
$dhlShipmentService = new DhlShipmentService;
$result = $dhlShipmentService->createShipment($order, (float) $request->weight, $options);
$result = $dhlShipmentService->createShipment($order, $shipmentWeight, $options);
Log::info('[DHL Controller] Shipment creation processed', [
'order_id' => $order->id,
'weight' => $request->weight,
'weight' => $shipmentWeight,
'requested_weight' => $request->weight,
'queued' => $result['queued'] ?? false,
'success' => $result['success'] ?? false,
]);
if (! ($result['success'] ?? false)) {
return response()->json($result, ($result['type'] ?? null) === 'dhl_address_validation' ? 422 : 500);
}
return response()->json($result);
} catch (Exception $e) {
Log::error('[DHL Controller] Failed to dispatch shipment creation', [
@ -346,6 +367,81 @@ class DhlShipmentController extends Controller
}
}
public function validateAddress(Request $request, DhlAddressValidator $validator): JsonResponse
{
$country = $request->filled('shipping_country_id')
? Country::find($request->get('shipping_country_id'))
: null;
$resolver = new DhlProductResolver;
$result = $validator->validate(array_merge($request->all(), [
'shipping_country_code' => $country?->code,
]));
$errors = $result['errors'];
$warnings = $result['warnings'];
$product = [
'code' => $request->get('product_code'),
'scope' => null,
'scope_label' => 'Nicht geprüft',
'country_code' => $country?->code,
'country_label' => $country?->getLocated(),
];
if ($country) {
try {
$resolvedProductCode = $resolver->resolveProductCode(
$country->code,
$request->get('product_code'),
config('dhl.default_product', 'V01PAK')
);
$product = [
'code' => $resolvedProductCode,
'scope' => $resolver->getProductScope($resolvedProductCode),
'scope_label' => $resolver->getProductScopeLabel($resolvedProductCode),
'country_code' => $country->code,
'country_label' => $country->getLocated(),
];
} catch (\InvalidArgumentException $e) {
$errors[] = $e->getMessage();
}
}
$status = 'valid';
if ($errors !== []) {
$status = 'error';
} elseif ($warnings !== []) {
$status = 'warning';
}
return response()->json([
'success' => $errors === [],
'status' => $status,
'can_create_label' => $errors === [],
'errors' => array_values(array_unique($errors)),
'warnings' => array_values(array_unique($warnings)),
'message' => $this->addressValidationMessage($status),
'preflight' => [
'product' => $product,
'address' => [
'status' => $result['status'],
'normalized' => $result['normalized'],
'validation_available' => $result['validation_available'],
'validation_level' => $result['validation_level'],
'validation_message' => $result['validation_message'],
],
],
], $errors === [] ? 200 : 422);
}
private function addressValidationMessage(string $status): string
{
return match ($status) {
'valid' => 'Adresse ist formal versandfähig.',
'warning' => 'Adresse ist formal versandfähig, sollte aber vor der Labelerstellung geprüft werden.',
default => 'Adresse ist nicht versandfähig. Bitte korrigieren Sie die markierten Felder.',
};
}
/**
* Display the specified shipment
*/
@ -719,7 +815,7 @@ class DhlShipmentController extends Controller
// Mark all included shipments as sent
foreach ($allShipments as $s) {
$s->markTrackingEmailSent('manual');
$s->markTrackingEmailSent('manual', $recipientEmail, $allShipments);
}
Log::info('[DHL Controller] Tracking email sent', [

View file

@ -241,6 +241,8 @@ class ModalController extends Controller
'V01PAK' => 'DHL Paket (National)',
'V53WPAK' => 'DHL Paket International',
],
'productSuggestions' => (new \App\Services\DhlProductResolver)->getProductSuggestionsByCountry(),
'selectedProductCode' => 'V01PAK',
'errors' => ['Fehler beim Laden der Daten: '.$e->getMessage()],
'warnings' => [],
];

View file

@ -3,6 +3,8 @@
namespace App\Http\Controllers;
use App\Models\Setting;
use App\Services\DhlProductResolver;
use Illuminate\Support\Facades\Session;
use Request;
class SettingController extends Controller
@ -36,9 +38,9 @@ class SettingController extends Controller
// DHL-spezifische Behandlung
if ($data['action'] === 'save_dhl') {
$this->updateDhlConfigCache();
\Session()->flash('alert-save-dhl', 'DHL Konfiguration erfolgreich gespeichert!');
Session::flash('alert-save-dhl', 'DHL Konfiguration erfolgreich gespeichert!');
} else {
\Session()->flash('alert-save', '1');
Session::flash('alert-save', '1');
}
}
@ -72,10 +74,12 @@ class SettingController extends Controller
'test_mode' => config('dhl.legacy.test_mode', true),
// Product Settings
'default_product' => $this->getConfigValue('dhl_product', config('dhl.default_product'), $useEnvPriority),
'default_product' => $this->normalizeDhlProductCode($this->getConfigValue('dhl_product', config('dhl.default_product'), $useEnvPriority)),
'international_countries' => $this->getDhlInternationalCountries($useEnvPriority),
'label_format' => $this->getConfigValue('dhl_label_format', config('dhl.label_format'), $useEnvPriority),
'print_format' => $this->getConfigValue('dhl_print_format', config('dhl.print_format'), $useEnvPriority),
'retoure_print_format' => $this->getConfigValue('dhl_retoure_print_format', config('dhl.retoure_print_format'), $useEnvPriority),
'print_only_if_codeable' => (bool) $this->getConfigValue('dhl_print_only_if_codeable', config('dhl.print_only_if_codeable'), $useEnvPriority),
'use_queue' => $this->getConfigValue('dhl_use_queue', config('dhl.use_queue'), $useEnvPriority),
// Sender Address
@ -94,7 +98,7 @@ class SettingController extends Controller
// Account Numbers
'account_numbers' => [
'V01PAK' => $this->getConfigValue('dhl_account_v01pak', config('dhl.account_numbers.V01PAK'), $useEnvPriority),
'V62WP' => $this->getConfigValue('dhl_account_v62wp', config('dhl.account_numbers.V62WP'), $useEnvPriority),
'V62KP' => $this->getConfigValue('dhl_account_v62kp', $this->getConfigValue('dhl_account_v62wp', config('dhl.account_numbers.V62KP'), $useEnvPriority), $useEnvPriority),
'V53PAK' => $this->getConfigValue('dhl_account_v53pak', config('dhl.account_numbers.V53PAK'), $useEnvPriority),
'V07PAK' => $this->getConfigValue('dhl_account_v07pak', config('dhl.account_numbers.V07PAK'), $useEnvPriority),
'default' => config('dhl.account_numbers.default'),
@ -103,7 +107,7 @@ class SettingController extends Controller
// Dimensions
'dimensions' => [
'V01PAK' => config('dhl.dimensions.V01PAK'),
'V62WP' => config('dhl.dimensions.V62WP'),
'V62KP' => config('dhl.dimensions.V62KP'),
'V53PAK' => config('dhl.dimensions.V53PAK'),
'V07PAK' => config('dhl.dimensions.V07PAK'),
'default' => config('dhl.dimensions.default'),
@ -136,6 +140,26 @@ class SettingController extends Controller
}
}
private function normalizeDhlProductCode(?string $productCode): string
{
return $productCode === 'V62WP' ? 'V62KP' : ($productCode ?: 'V01PAK');
}
/**
* @return string[]
*/
private function getDhlInternationalCountries(bool $useEnvPriority): array
{
$configCountries = config('dhl.international_countries', DhlProductResolver::DEFAULT_INTERNATIONAL_COUNTRIES);
$countries = $configCountries;
if (! $useEnvPriority) {
$countries = Setting::getContentBySlug('dhl_international_countries') ?: $configCountries;
}
return DhlProductResolver::normalizeCountryCodeList(is_array($countries) ? $countries : []);
}
/**
* Update DHL configuration cache after saving settings
*/