$boxes Box Now only — one entry per * physical parcel, each a compartment size ('S'|'M'|'L'). A single * shipment can be split across several lockers of the same * destinationLocationId's collection point, e.g. two Large boxes for * an order that doesn't fit one compartment. Empty for every other * carrier, which ships as a single package described by $weight * instead. * @param array $services staff-picked extra * services; a carrier only receives ones it declares via * SupportsExtraServices. * @param ?float $insuranceAmount when ExtraService::Insurance is picked. * @param ?string $deliveryUntil "HH:MM", when ExtraService::TimedDelivery is picked. */ public function __construct( public readonly ?float $weight = null, public readonly int $packageCount = 1, public readonly ?string $destinationLocationId = null, public readonly ?string $paymentMode = null, public readonly ?float $amountToCollect = null, public readonly array $boxes = [], public readonly array $services = [], public readonly ?float $insuranceAmount = null, public readonly ?string $deliveryUntil = null, public readonly ?string $trackingReference = null, ) {} public function has(ExtraService $service): bool { return in_array($service, $this->services, true); } /** * @return array */ public function serviceValues(): array { return array_map(fn (ExtraService $service) => $service->value, $this->services); } }