From d3de47607d4a99aeacc0e78fcb366ee4f3da9832 Mon Sep 17 00:00:00 2001 From: matteolavaggi Date: Thu, 9 Jul 2026 13:57:48 +0200 Subject: [PATCH] fix: convert Packlink shipping costs to cart currency Convert API/service prices from the shipping method currency to the cart currency before returning from PackageCostCalculator, and expose all enabled shop currencies in SystemInfoService for multi-currency configuration. Co-authored-by: Cursor --- .../SystemInfoService.php | 20 +++-- .../PackageCostCalculator.php | 64 ++++++++++++++- .../Utility/ShippingCostCurrencyConverter.php | 79 +++++++++++++++++++ 3 files changed, 154 insertions(+), 9 deletions(-) create mode 100644 src/classes/Utility/ShippingCostCurrencyConverter.php diff --git a/src/classes/BusinessLogicServices/SystemInfoService.php b/src/classes/BusinessLogicServices/SystemInfoService.php index 90efcae..60f5926 100644 --- a/src/classes/BusinessLogicServices/SystemInfoService.php +++ b/src/classes/BusinessLogicServices/SystemInfoService.php @@ -68,13 +68,19 @@ private function getCurrencies($systemId = null) return array(); } - $currency = new \Currency(\Configuration::get( - 'PS_CURRENCY_DEFAULT', - null, - null, - $systemId - )); + $currencies = \Currency::getCurrenciesByIdShop((int) $systemId); + $isoCodes = array(); - return array($currency->iso_code); + foreach ($currencies as $currency) { + if (empty($currency['active']) || !empty($currency['deleted'])) { + continue; + } + + if (!empty($currency['iso_code'])) { + $isoCodes[] = $currency['iso_code']; + } + } + + return array_values(array_unique($isoCodes)); } } diff --git a/src/classes/ShippingServices/PackageCostCalculator.php b/src/classes/ShippingServices/PackageCostCalculator.php index 3a818bd..ef89d63 100644 --- a/src/classes/ShippingServices/PackageCostCalculator.php +++ b/src/classes/ShippingServices/PackageCostCalculator.php @@ -13,6 +13,7 @@ use Packlink\BusinessLogic\ShippingMethod\ShippingMethodService; use Packlink\PrestaShop\Classes\Bootstrap; use Packlink\PrestaShop\Classes\Utility\CachingUtility; +use Packlink\PrestaShop\Classes\Utility\ShippingCostCurrencyConverter; /** * Class PackageCostCalculator. @@ -62,13 +63,18 @@ public static function getPackageCost(Cart $cart, array $products, $carrierId) if (self::displayBackupCarrier($cart, $calculatedCosts, $carrierReferenceId)) { $allCosts = self::getCostsForAllShippingMethods($cart, $shippingProducts); if (!empty($allCosts)) { + $allCosts = self::convertCostsToCartCurrency($allCosts, $cart); + return self::applyShopCostCalculationSettings(min(array_values($allCosts)), $cart); } } if ($calculatedCosts !== false) { return isset($calculatedCosts[$methodId]) - ? self::applyShopCostCalculationSettings($calculatedCosts[$methodId], $cart) : false; + ? self::applyShopCostCalculationSettings( + self::convertCostToCartCurrency($calculatedCosts[$methodId], $cart, $methodId), + $cart + ) : false; } $warehouse = CachingUtility::getDefaultWarehouse(); @@ -98,7 +104,10 @@ public static function getPackageCost(Cart $cart, array $products, $carrierId) CachingUtility::setCosts($calculatedCosts); return isset($calculatedCosts[$methodId]) - ? self::applyShopCostCalculationSettings($calculatedCosts[$methodId], $cart) : false; + ? self::applyShopCostCalculationSettings( + self::convertCostToCartCurrency($calculatedCosts[$methodId], $cart, $methodId), + $cart + ) : false; } /** @@ -234,6 +243,57 @@ private static function getCartTotal(Cart $cart) return CachingUtility::getCartTotal(); } + /** + * Converts shipping costs from service currency to cart currency. + * + * @param array $costs Shipping costs keyed by shipping method ID. + * @param \Cart $cart + * + * @return array + * + * @throws \Logeecom\Infrastructure\ORM\Exceptions\QueryFilterInvalidParamException + * @throws \Logeecom\Infrastructure\ORM\Exceptions\RepositoryNotRegisteredException + */ + private static function convertCostsToCartCurrency(array $costs, Cart $cart) + { + $convertedCosts = array(); + + foreach ($costs as $methodId => $cost) { + $convertedCosts[$methodId] = self::convertCostToCartCurrency($cost, $cart, $methodId); + } + + return $convertedCosts; + } + + /** + * Converts a single shipping cost from service currency to cart currency. + * + * @param float $cost + * @param \Cart $cart + * @param int|string $methodId + * + * @return float + * + * @throws \Logeecom\Infrastructure\ORM\Exceptions\QueryFilterInvalidParamException + * @throws \Logeecom\Infrastructure\ORM\Exceptions\RepositoryNotRegisteredException + */ + private static function convertCostToCartCurrency($cost, Cart $cart, $methodId) + { + /** @var \Packlink\BusinessLogic\ShippingMethod\ShippingMethodService $shippingMethodService */ + $shippingMethodService = ServiceRegister::getService(ShippingMethodService::CLASS_NAME); + $shippingMethod = $shippingMethodService->getShippingMethod($methodId); + + if ($shippingMethod === null) { + return $cost; + } + + return ShippingCostCurrencyConverter::convertToCartCurrency( + $cost, + $shippingMethod->getCurrency(), + (int) $cart->id_currency + ); + } + /** * Checks shipping cost settings and handling costs and applies settings to the given cost. * diff --git a/src/classes/Utility/ShippingCostCurrencyConverter.php b/src/classes/Utility/ShippingCostCurrencyConverter.php new file mode 100644 index 0000000..8691061 --- /dev/null +++ b/src/classes/Utility/ShippingCostCurrencyConverter.php @@ -0,0 +1,79 @@ +iso_code)) { + return $amount; + } + + $fromCurrencyId = (int) \Currency::getIdByIsoCode($fromCurrencyIso); + if ($fromCurrencyId <= 0) { + return $amount; + } + + $fromCurrency = new \Currency($fromCurrencyId); + + return self::convertPrice($amount, $fromCurrency, $cartCurrency); + } + + /** + * Converts price between two currencies using shop conversion rates. + * + * @param float $amount + * @param \Currency $currencyFrom + * @param \Currency $currencyTo + * + * @return float + */ + private static function convertPrice($amount, \Currency $currencyFrom, \Currency $currencyTo) + { + if ((int) $currencyFrom->id === (int) $currencyTo->id) { + return $amount; + } + + $defaultCurrencyId = (int) \Configuration::get('PS_CURRENCY_DEFAULT'); + + if ((int) $currencyFrom->id === $defaultCurrencyId) { + $amount *= (float) $currencyTo->conversion_rate; + } else { + $conversionRate = (float) $currencyFrom->conversion_rate; + if ($conversionRate <= 0) { + $conversionRate = 1; + } + + $amount = $amount / $conversionRate; + $amount *= (float) $currencyTo->conversion_rate; + } + + return (float) \Tools::ps_round($amount, _PS_PRICE_DISPLAY_PRECISION_); + } +}