I have tried various ways so far with CartService and Collector/Processor as well. There is similar class DeliveryProcessor.php and I overwrited the file but I didn’t succeed in changing the shipment. Can someone shine some light.
For test purpose this is how i calculate shipping costs.
$manualShippingCosts = new CalculatedPrice(0.0, 0.0, new CalculatedTaxCollection(), new TaxRuleCollection());
I am really not sure whether we should use collector/processor to change shipping as we change price or use cartService.
Complete class
class DeliveryProcessorOverWrite implements CartDataCollectorInterface, CartProcessorInterface
{
public const MANUAL_SHIPPING_COSTS = 'manualShippingCosts';
public const SKIP_DELIVERY_PRICE_RECALCULATION = 'skipDeliveryPriceRecalculation';
public const SKIP_DELIVERY_TAX_RECALCULATION = 'skipDeliveryTaxRecalculation';
/**
* @var DeliveryBuilder
*/
protected $builder;
/**
* @var DeliveryCalculator
*/
protected $deliveryCalculator;
/**
* @var EntityRepositoryInterface
*/
protected $shippingMethodRepository;
public function __construct(
DeliveryBuilder $builder,
DeliveryCalculator $deliveryCalculator,
EntityRepositoryInterface $shippingMethodRepository
) {
$this->builder = $builder;
$this->deliveryCalculator = $deliveryCalculator;
$this->shippingMethodRepository = $shippingMethodRepository;
}
public static function buildKey(string $shippingMethodId): string
{
return 'shipping-method-' . $shippingMethodId;
}
public function collect(CartDataCollection $data, Cart $original, SalesChannelContext $context, CartBehavior $behavior): void
{
Profiler::trace('cart::delivery::collect', function () use ($data, $original, $context): void {
$default = $context->getShippingMethod()->getId();
if (!$data->has(self::buildKey($default))) {
$ids = [$default];
}
foreach ($original->getDeliveries() as $delivery) {
$id = $delivery->getShippingMethod()->getId();
if (!$data->has(self::buildKey($id))) {
$ids[] = $id;
}
}
if (empty($ids)) {
return;
}
$criteria = new Criteria($ids);
$criteria->addAssociation('prices');
$criteria->addAssociation('deliveryTime');
$criteria->addAssociation('tax');
$criteria->setTitle('cart::shipping-methods');
$shippingMethods = $this->shippingMethodRepository->search($criteria, $context->getContext());
foreach ($ids as $id) {
$key = self::buildKey($id);
if (!$shippingMethods->has($id)) {
continue;
}
$data->set($key, $shippingMethods->get($id));
}
}, 'cart');
}
public function process(CartDataCollection $data, Cart $original, Cart $toCalculate, SalesChannelContext $context, CartBehavior $behavior): void
{
Profiler::trace('cart::delivery::process', function () use ($data, $original, $toCalculate, $context, $behavior): void {
$deliveries = $this->builder->build($toCalculate, $data, $context, $behavior);
$delivery = $deliveries->first();
if ($behavior->hasPermission(self::SKIP_DELIVERY_PRICE_RECALCULATION)) {
$originalDeliveries = $original->getDeliveries();
$originalDelivery = $originalDeliveries->first();
if ($delivery !== null && $originalDelivery !== null) {
$originalDelivery->setShippingMethod($delivery->getShippingMethod());
//Keep old prices
$manualShippingCosts = new CalculatedPrice(0.0, 0.0, new CalculatedTaxCollection(), new TaxRuleCollection());
$delivery->setShippingCosts($manualShippingCosts);
//Recalculate tax
$this->deliveryCalculator->calculate($data, $toCalculate, $deliveries, $context);
$originalDelivery->setShippingCosts($manualShippingCosts);
}
// New shipping method (if changed) but with old prices
$toCalculate->setDeliveries($originalDeliveries);
return;
}
$manualShippingCosts = new CalculatedPrice(0.0, 0.0, new CalculatedTaxCollection(), new TaxRuleCollection());
if ($delivery !== null && $manualShippingCosts instanceof CalculatedPrice) {
$delivery->setShippingCosts($manualShippingCosts);
}
$this->deliveryCalculator->calculate($data, $toCalculate, $deliveries, $context);
$toCalculate->setDeliveries($deliveries);
}, 'cart');
}
}