Personnaliser Ibexa Commerce - Calculateur de frais de port

Comment calculer dynamiquement des frais de port?
Ibexa Commerce Transport API

21 août 2024

Comment calculer dynamiquement des frais de port ?

La documentation officielle qui explique comment créer des méthodes de livraison dans Ibexa Commerce omet une explication cruciale : comment calculer les frais pour la méthode en question.

Je vais donc combler ce manque et expliquer comment créer un calculateur de frais pour une méthode de livraison. Je vais prendre comme exemple un cas simple où on a des produits avec frais de port offert :

  • si tous les produits de la commande ont les frais de port offerts, les frais de port de la commande sera de 0 ;
  • sinon les frais de port seront le montant configuré dans la méthode de livraison.

Comme beaucoup d'autres choses dans Ibexa ou Symfony de manière générale, ce calculateur sera un service tagué.

Voici la classe src/Commerce/Attribute/String/StringStorageDefinition.php :

   

<?php 
declare(strict_types=1); 
namespace App\Commerce\Shipping; 
use Ibexa\Contracts\Cart\Value\CartInterface;
use Ibexa\Contracts\ProductCatalog\CurrencyServiceInterface;
use Ibexa\Contracts\ProductCatalog\Values\AttributeInterface;
use Ibexa\Contracts\Shipping\ShippingMethod\CostCalculatorInterface;
use Ibexa\Contracts\Shipping\Value\ShippingMethod\ShippingMethodInterface;
use Ibexa\ProductCatalog\Money\DecimalMoneyFactory;
use Money\Currency;
use Money\Money; 
class CostCalculator implements CostCalculatorInterface
{
   public function __construct(
       private readonly DecimalMoneyFactory $decimalMoneyFactory,
       private readonly CurrencyServiceInterface $currencyService
   ) {
   } 
   public function calculate(ShippingMethodInterface $method, CartInterface $cart): Money
   {
       $isFree = true; 
       // On itère sur chaque article du panier et on vérifie si les frais de port sont offerts
       foreach ($cart->getEntries() as $entry) {
           /** @var array<AttributeInterface> $attributes */
           $attributes = iterator_to_array($entry->getProduct()->getAttributes());
           if (!$attributes['free_shipping']->getValue()) {
               $isFree = false;
               break;
           }
       } 
       // On récupère la configuration de la méthode
       $price = $method->getOptions()->get('price');
       $currencyId = $method->getOptions()->get('currency'); 
       $currency = $this->currencyService->getCurrency($currencyId); 
       // Tous les produits ont les frais de port offerts, on retourne un montant de 0
       if ($isFree) {
           return new Money('0', new Currency($currency->getCode()));
       } 
       return $this->decimalMoneyFactory->getMoneyParser()->parse(
           $price,
           new Currency($currency->getCode())
       );
   }
} 
   

Il ne reste plus qu'à taguer notre service dans le fichier de configuration config/services.yaml :

   

App\Commerce\Shipping\CostCalculator:
       tags:
           - name: ibexa.shipping.shipping.cost_calculator
             method: custom_method # custom_method à remplacer par l'identifiant de la méthode de livraison