31.5, 'V53PAK' => 31.5, 'V62KP' => 1.0, ]; public function calculate(ShoppingOrder $order): float { $this->loadOrderItems($order); $baseWeightGrams = max((int) ($order->weight ?? 0), 0); $compensationWeightGrams = $this->calculateCompensationWeightGrams($order); $totalWeightGrams = $baseWeightGrams + $compensationWeightGrams; if ($totalWeightGrams <= 0) { return self::DEFAULT_WEIGHT_KG; } return $this->roundWeightKg($totalWeightGrams / 1000); } public function getMaxWeightKgForProduct(?string $productCode): float { $productCode = strtoupper(trim((string) $productCode)); return self::PRODUCT_MAX_WEIGHTS_KG[$productCode] ?? self::DEFAULT_MAX_WEIGHT_KG; } public function assertWithinProductLimit(float $weightKg, ?string $productCode): void { $maxWeightKg = $this->getMaxWeightKgForProduct($productCode); if ($weightKg > $maxWeightKg) { throw new InvalidArgumentException(sprintf( 'Gewicht %.3f kg ueberschreitet das DHL-Maximalgewicht fuer %s (%.1f kg).', $weightKg, $productCode ?: 'das gewaehlte Produkt', $maxWeightKg )); } } private function calculateCompensationWeightGrams(ShoppingOrder $order): int { $items = $order->shopping_order_items ?? collect(); $weightGrams = 0; foreach ($items as $item) { if ((int) ($item->comp ?? 0) <= 0) { continue; } $productWeight = (int) ($item->product?->weight ?? 0); if ($productWeight <= 0) { continue; } $quantity = max((int) ($item->qty ?? 1), 1); $weightGrams += $productWeight * $quantity; } return $weightGrams; } private function roundWeightKg(float $weightKg): float { return round(max($weightKg, 0.1), 3); } private function loadOrderItems(ShoppingOrder $order): void { if ($order->exists && ! $order->relationLoaded('shopping_order_items')) { $order->loadMissing('shopping_order_items.product'); } } }