diff --git a/controllers/front/recurringOrderDetail.php b/controllers/front/recurringOrderDetail.php index b0b5d0b48..6fe4b7b86 100644 --- a/controllers/front/recurringOrderDetail.php +++ b/controllers/front/recurringOrderDetail.php @@ -27,7 +27,7 @@ use Mollie\Controller\AbstractMollieController; use Mollie\Subscription\Handler\FreeOrderCreationHandler; use Mollie\Subscription\Handler\SubscriptionCancellationHandler; -use Mollie\Subscription\Logger\RecurringOrderPresenter; +use Mollie\Subscription\Presenter\RecurringOrderPresenter; use Mollie\Subscription\Repository\RecurringOrderRepositoryInterface; class MollieRecurringOrderDetailModuleFrontController extends AbstractMollieController diff --git a/controllers/front/subscriptions.php b/controllers/front/subscriptions.php index 5bc2db973..b0a9d81b2 100644 --- a/controllers/front/subscriptions.php +++ b/controllers/front/subscriptions.php @@ -1,7 +1,7 @@ getCommands(); foreach ($commands as $query) { - if (false == Db::getInstance()->execute($query)) { + if (!Db::getInstance()->execute($query)) { return false; } } - return true; + return $this->alterTableCommands(); } /** @@ -142,4 +142,29 @@ private function getCommands() return $sql; } + + private function alterTableCommands(): bool + { + $query = ' + SELECT COUNT(*) > 0 AS count + FROM information_schema.columns + WHERE TABLE_SCHEMA = "' . _DB_NAME_ . '" AND table_name = "' . _DB_PREFIX_ . 'mollie_payments" AND column_name = "mandate_id"; + '; + + /* only run if it doesn't exist */ + if (Db::getInstance()->getValue($query)) { + return true; + } + + $query = ' + ALTER TABLE ' . _DB_PREFIX_ . 'mollie_payments + ADD COLUMN mandate_id VARCHAR(64); + '; + + if (!Db::getInstance()->execute($query)) { + return false; + } + + return true; + } } diff --git a/src/Install/DatabaseTableUninstaller.php b/src/Install/DatabaseTableUninstaller.php index 7f6d24ed5..2dde9bee9 100644 --- a/src/Install/DatabaseTableUninstaller.php +++ b/src/Install/DatabaseTableUninstaller.php @@ -34,7 +34,6 @@ private function getCommands(): array $sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'mol_country`;'; $sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'mol_payment_method`;'; $sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'mol_payment_method_issuer`;'; - $sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'mol_order_payment_fee`;'; $sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'mol_carrier_information`;'; $sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'mol_pending_order_cart`;'; $sql[] = 'DROP TABLE IF EXISTS `' . _DB_PREFIX_ . 'mol_excluded_country`;'; diff --git a/src/Service/MailService.php b/src/Service/MailService.php index ebe359d5e..3b0d812d7 100644 --- a/src/Service/MailService.php +++ b/src/Service/MailService.php @@ -34,7 +34,6 @@ use Order; use OrderState; use PDF; -use PrestaShop\Decimal\Number; use Product; use State; use Tools; @@ -186,13 +185,21 @@ private function getSubscriptionCancellationWarningMailData( Customer $customer ): array { $product = new Product($recurringOrderProduct->id_product, false, $customer->id_lang); - $totalPrice = NumberUtility::times((float) $recurringOrderProduct->unit_price, (float) $recurringOrderProduct->quantity); - $unitPrice = new Number((string) $recurringOrderProduct->unit_price); + + $totalPrice = NumberUtility::toPrecision( + (float) $recurringOrder->total_tax_incl, + NumberUtility::DECIMAL_PRECISION + ); + + $unitPrice = NumberUtility::toPrecision( + (float) $recurringOrderProduct->unit_price, + NumberUtility::DECIMAL_PRECISION + ); return [ 'subscription_reference' => $recurringOrder->mollie_subscription_id, 'product_name' => $product->name, - 'unit_price' => $this->toolsAdapter->displayPrice($unitPrice->toPrecision(2), new Currency($recurringOrder->id_currency)), + 'unit_price' => $this->toolsAdapter->displayPrice($unitPrice, new Currency($recurringOrder->id_currency)), 'quantity' => $recurringOrderProduct->quantity, 'total_price' => $this->toolsAdapter->displayPrice($totalPrice, new Currency($recurringOrder->id_currency)), 'firstName' => $customer->firstname, diff --git a/subscription/Entity/MolRecurringOrder.php b/subscription/Entity/MolRecurringOrder.php index 691339212..07adcee47 100644 --- a/subscription/Entity/MolRecurringOrder.php +++ b/subscription/Entity/MolRecurringOrder.php @@ -29,6 +29,9 @@ class MolRecurringOrder extends ObjectModel /** @var string */ public $status; + /** @var float */ + public $total_tax_incl; + /** @var string */ public $payment_method; @@ -71,6 +74,7 @@ class MolRecurringOrder extends ObjectModel 'mollie_customer_id' => ['type' => self::TYPE_STRING, 'validate' => 'isString'], 'description' => ['type' => self::TYPE_STRING, 'validate' => 'isString'], 'status' => ['type' => self::TYPE_STRING, 'validate' => 'isString'], + 'total_tax_incl' => ['type' => self::TYPE_FLOAT, 'validate' => 'isFloat'], 'payment_method' => ['type' => self::TYPE_STRING, 'validate' => 'isString'], 'next_payment' => ['type' => self::TYPE_DATE], 'reminder_at' => ['type' => self::TYPE_DATE], diff --git a/subscription/Factory/CreateSubscriptionDataFactory.php b/subscription/Factory/CreateSubscriptionDataFactory.php index 109774f7b..6563b892c 100644 --- a/subscription/Factory/CreateSubscriptionDataFactory.php +++ b/subscription/Factory/CreateSubscriptionDataFactory.php @@ -74,10 +74,14 @@ public function build(Order $order, array $subscriptionProduct): SubscriptionDat $currency = $this->currencyAdapter->getById((int) $order->id_currency); $description = $this->subscriptionDescription->getSubscriptionDescription($order); + $orderTotal = (float) $subscriptionProduct['total_price_tax_incl'] + + (float) $order->total_wrapping_tax_incl + + (float) $order->total_shipping_tax_incl; + /** * NOTE: we will only send product price as total for subscriptions */ - $orderAmount = new Amount((float) $subscriptionProduct['total_price_tax_incl'], $currency->iso_code); + $orderAmount = new Amount($orderTotal, $currency->iso_code); $subscriptionData = new SubscriptionDataDTO( $molCustomer->customer_id, $orderAmount, diff --git a/subscription/Grid/SubscriptionGridDefinitionFactory.php b/subscription/Grid/SubscriptionGridDefinitionFactory.php index ea1f1b8dd..876d18058 100644 --- a/subscription/Grid/SubscriptionGridDefinitionFactory.php +++ b/subscription/Grid/SubscriptionGridDefinitionFactory.php @@ -104,10 +104,10 @@ protected function getColumns() 'sortable' => true, ]) ) - ->add((new DataColumn('unit_price')) - ->setName($this->module->l('Unit price', self::FILE_NAME)) + ->add((new DataColumn('total_price')) + ->setName($this->module->l('Total price', self::FILE_NAME)) ->setOptions([ - 'field' => 'unit_price', + 'field' => 'total_price', 'sortable' => true, ]) ) @@ -220,14 +220,14 @@ protected function getFilters() ]) ->setAssociatedColumn('status') ) - ->add((new Filter('unit_price', MoneyType::class)) + ->add((new Filter('total_price', MoneyType::class)) ->setTypeOptions([ 'required' => false, 'attr' => [ - 'placeholder' => $this->module->l('Unit price', self::FILE_NAME), + 'placeholder' => $this->module->l('Total price', self::FILE_NAME), ], ]) - ->setAssociatedColumn('unit_price') + ->setAssociatedColumn('total_price') ) ->add((new Filter('iso_code', TextType::class)) ->setTypeOptions([ diff --git a/subscription/Grid/SubscriptionGridQueryBuilder.php b/subscription/Grid/SubscriptionGridQueryBuilder.php index 61a4db912..307d27150 100644 --- a/subscription/Grid/SubscriptionGridQueryBuilder.php +++ b/subscription/Grid/SubscriptionGridQueryBuilder.php @@ -47,7 +47,7 @@ public function getSearchQueryBuilder(SearchCriteriaInterface $searchCriteria): $qb = $this->getQueryBuilder($searchCriteria->getFilters()) ->select('recurring_order.*') ->addSelect($this->getNameField() . ' as fullname') - ->addSelect('ROUND(orders.total_paid, 2) as unit_price') + ->addSelect('ROUND(recurring_order.total_tax_incl, 2) as total_price') ->addSelect('currency.iso_code') ; @@ -106,7 +106,7 @@ private function applyFilters(array $filters, QueryBuilder $qb): void 'fullname' => $this->getNameField(), 'description' => 'recurring_order.description', 'status' => 'recurring_order.status', - 'unit_price' => 'orders.total_paid', + 'total_price' => 'recurring_order.total_tax_incl', 'iso_code' => 'currency.iso_code', ]; diff --git a/subscription/Handler/SubscriptionCreationHandler.php b/subscription/Handler/SubscriptionCreationHandler.php index 864c0479d..89c5c220a 100644 --- a/subscription/Handler/SubscriptionCreationHandler.php +++ b/subscription/Handler/SubscriptionCreationHandler.php @@ -85,6 +85,7 @@ private function createRecurringOrder(MolRecurringOrdersProduct $recurringOrders $recurringOrder->id_address_invoice = $order->id_address_invoice; $recurringOrder->description = $subscription->description; $recurringOrder->status = $subscription->status; + $recurringOrder->total_tax_incl = (float) $subscription->amount->value; $recurringOrder->payment_method = $method; $recurringOrder->next_payment = $subscription->nextPaymentDate; $recurringOrder->reminder_at = $subscription->nextPaymentDate; //todo: add logic to get reminder date when reminder is done diff --git a/subscription/Install/DatabaseTableInstaller.php b/subscription/Install/DatabaseTableInstaller.php index d8ea0783b..497e6718c 100644 --- a/subscription/Install/DatabaseTableInstaller.php +++ b/subscription/Install/DatabaseTableInstaller.php @@ -13,12 +13,12 @@ public function install(): bool $commands = $this->getCommands(); foreach ($commands as $query) { - if (false == Db::getInstance()->execute($query)) { + if (!Db::getInstance()->execute($query)) { return false; } } - return true; + return $this->alterTableCommands(); } /** @@ -45,6 +45,7 @@ private function getCommands(): array `mollie_customer_id` VARCHAR(64) NOT NULL, `payment_method` VARCHAR(64) NOT NULL, `id_mol_recurring_orders_product` INT(64) NOT NULL, + `total_tax_incl` decimal(20, 6) NOT NULL, `date_add` datetime NOT NULL, `date_update` datetime NOT NULL ) ENGINE=' . _MYSQL_ENGINE_ . ' DEFAULT CHARSET=utf8;'; @@ -61,4 +62,39 @@ private function getCommands(): array return $sql; } + + private function alterTableCommands(): bool + { + $query = ' + SELECT COUNT(*) > 0 AS count + FROM information_schema.columns + WHERE TABLE_SCHEMA = "' . _DB_NAME_ . '" AND table_name = "' . _DB_PREFIX_ . 'mol_recurring_order" AND column_name = "total_tax_incl"; + '; + + /* only run if it doesn't exist */ + if (Db::getInstance()->getValue($query)) { + return true; + } + + $query = ' + ALTER TABLE ' . _DB_PREFIX_ . 'mol_recurring_order + ADD COLUMN total_tax_incl decimal(20, 6) NOT NULL; + '; + + if (!Db::getInstance()->execute($query)) { + return false; + } + + $query = ' + UPDATE ' . _DB_PREFIX_ . 'mol_recurring_order ro + JOIN ' . _DB_PREFIX_ . 'orders o ON ro.id_order = o.id_order + SET ro.total_tax_incl = o.total_paid_tax_incl; + '; + + if (!Db::getInstance()->execute($query)) { + return false; + } + + return true; + } } diff --git a/subscription/Presenter/OrderPresenter.php b/subscription/Presenter/OrderPresenter.php new file mode 100644 index 000000000..c907b7e7c --- /dev/null +++ b/subscription/Presenter/OrderPresenter.php @@ -0,0 +1,35 @@ +getCartProducts(); + + foreach ($orderProducts as $orderProduct) { + if ((int) $orderProduct['id_product_attribute'] !== $recurringOrderProductAttributeId) { + $order->total_paid_tax_excl -= (float) $orderProduct['total_price_tax_excl']; + + continue; + } + + $order->total_products = (float) $orderProduct['total_price_tax_excl']; + $order->total_products_wt = (float) $orderProduct['total_price_tax_incl']; + $order->total_paid_tax_incl = $recurringOrderTotalTaxIncl; + $order->total_paid = $recurringOrderTotalTaxIncl; + + break; + } + + $orderLazyArray = new RecurringOrderLazyArray($order); + + $orderLazyArray->setRecurringOrderProductAttributeId($recurringOrderProductAttributeId); + + return $orderLazyArray; + } +} diff --git a/subscription/Presenter/RecurringOrderLazyArray.php b/subscription/Presenter/RecurringOrderLazyArray.php new file mode 100644 index 000000000..7d91bf59f --- /dev/null +++ b/subscription/Presenter/RecurringOrderLazyArray.php @@ -0,0 +1,40 @@ +recurringOrderProductAttributeId = $recurringOrderProductAttributeId; + } + + /** + * @arrayAccess + * + * @return array + */ + public function getProducts(): array + { + $subscriptionProduct = []; + + $orderProducts = parent::getProducts(); + + foreach ($orderProducts as $orderProduct) { + if ((int) $orderProduct['id_product_attribute'] !== $this->recurringOrderProductAttributeId) { + continue; + } + + $subscriptionProduct[] = $orderProduct; + + break; + } + + return $subscriptionProduct; + } +} diff --git a/subscription/Presenter/RecurringOrderPresenter.php b/subscription/Presenter/RecurringOrderPresenter.php index abb4c60b8..3601cec40 100644 --- a/subscription/Presenter/RecurringOrderPresenter.php +++ b/subscription/Presenter/RecurringOrderPresenter.php @@ -2,15 +2,15 @@ declare(strict_types=1); -namespace Mollie\Subscription\Logger; +namespace Mollie\Subscription\Presenter; use Currency; use Mollie\Adapter\Language; use Mollie\Subscription\Api\MethodApi; use Mollie\Subscription\Repository\RecurringOrderRepositoryInterface; use Mollie\Subscription\Repository\RecurringOrdersProductRepositoryInterface; +use Mollie\Utility\NumberUtility; use Order; -use PrestaShop\PrestaShop\Adapter\Presenter\Order\OrderPresenter; use Product; class RecurringOrderPresenter @@ -23,17 +23,21 @@ class RecurringOrderPresenter private $language; /** @var MethodApi */ private $methodApi; + /** @var OrderPresenter */ + private $orderPresenter; public function __construct( RecurringOrderRepositoryInterface $recurringOrderRepository, RecurringOrdersProductRepositoryInterface $recurringOrdersProductRepository, Language $language, - MethodApi $methodApi + MethodApi $methodApi, + OrderPresenter $orderPresenter ) { $this->recurringOrderRepository = $recurringOrderRepository; $this->recurringOrdersProductRepository = $recurringOrdersProductRepository; $this->language = $language; $this->methodApi = $methodApi; + $this->orderPresenter = $orderPresenter; } public function present(int $recurringOrderId): array @@ -56,7 +60,14 @@ public function present(int $recurringOrderId): array $recurringOrderData['recurring_order'] = $recurringOrder; $recurringOrderData['recurring_product'] = $recurringProduct; $recurringOrderData['product'] = $product; - $recurringOrderData['order'] = (new OrderPresenter())->present($order); + $recurringOrderData['order'] = $this->orderPresenter->present( + $order, + (int) $recurringProduct->id_product_attribute, + NumberUtility::toPrecision( + (float) $recurringOrder->total_tax_incl, + NumberUtility::DECIMAL_PRECISION + ) + ); $recurringOrderData['payment_methods'] = $this->methodApi->getMethodsForFirstPayment($this->language->getContextLanguage()->locale, $currency->iso_code); return $recurringOrderData; diff --git a/subscription/Presenter/RecurringOrdersPresenter.php b/subscription/Presenter/RecurringOrdersPresenter.php index 3557f0f36..42bc1f93b 100644 --- a/subscription/Presenter/RecurringOrdersPresenter.php +++ b/subscription/Presenter/RecurringOrdersPresenter.php @@ -2,19 +2,17 @@ declare(strict_types=1); -namespace Mollie\Subscription\Logger; +namespace Mollie\Subscription\Presenter; use Currency; use Mollie\Adapter\Context; use Mollie\Adapter\Language; use Mollie\Adapter\Link; use Mollie\Adapter\ToolsAdapter; -use Mollie\Repository\OrderRepositoryInterface; use Mollie\Subscription\Repository\RecurringOrderRepositoryInterface; use Mollie\Subscription\Repository\RecurringOrdersProductRepositoryInterface; use Mollie\Utility\NumberUtility; use MolRecurringOrder; -use Order; use Product; class RecurringOrdersPresenter @@ -29,8 +27,6 @@ class RecurringOrdersPresenter private $language; /** @var ToolsAdapter */ private $tools; - /** @var OrderRepositoryInterface */ - private $orderRepository; /** @var Context */ private $context; @@ -40,7 +36,6 @@ public function __construct( Link $link, Language $language, ToolsAdapter $tools, - OrderRepositoryInterface $orderRepository, Context $context ) { $this->recurringOrderRepository = $recurringOrderRepository; @@ -48,7 +43,6 @@ public function __construct( $this->recurringOrdersProductRepository = $recurringOrdersProductRepository; $this->language = $language; $this->tools = $tools; - $this->orderRepository = $orderRepository; $this->context = $context; } @@ -64,11 +58,6 @@ public function present(string $molCustomerId): array $recurringOrdersPresentData = []; /** @var MolRecurringOrder $recurringOrder */ foreach ($recurringOrders as $recurringOrder) { - /** @var Order $order */ - $order = $this->orderRepository->findOneBy([ - 'id_order' => $recurringOrder->id_order, - ]); - $recurringProduct = $this->recurringOrdersProductRepository->findOneBy([ 'id_mol_recurring_orders_product' => $recurringOrder->id, ]); @@ -79,7 +68,7 @@ public function present(string $molCustomerId): array $recurringOrderData['recurring_order'] = $recurringOrder; $recurringOrderData['details_url'] = $this->link->getModuleLink('mollie', 'recurringOrderDetail', ['id_mol_recurring_order' => $recurringOrder->id]); $recurringOrderData['product_name'] = is_array($product->name) ? $product->name[$this->context->getLanguageId()] : $product->name; - $recurringOrderData['total_price'] = $this->tools->displayPrice(NumberUtility::toPrecision((float) $order->total_paid, 2), new Currency($recurringOrder->id_currency)); + $recurringOrderData['total_price'] = $this->tools->displayPrice(NumberUtility::toPrecision((float) $recurringOrder->total_tax_incl, 2), new Currency($recurringOrder->id_currency)); $recurringOrderData['currency'] = new \Currency($recurringOrder->id_currency); $recurringOrdersPresentData[] = $recurringOrderData; } diff --git a/tests/Integration/Subscription/Presenter/OrderPresenterTest.php b/tests/Integration/Subscription/Presenter/OrderPresenterTest.php new file mode 100644 index 000000000..1b3ad9a7a --- /dev/null +++ b/tests/Integration/Subscription/Presenter/OrderPresenterTest.php @@ -0,0 +1,75 @@ + 1, + 'id_product_attribute' => 1, + 'total_price_tax_excl' => 10.00, + 'product_price' => 10.00, + 'total_price' => 10.00, + 'total_price_tax_incl' => 12.10, + 'product_price_wt' => 12.10, + 'total_wt' => 12.10, + 'product_name' => 'test-product-1', + 'product_quantity' => 1, + 'product_id' => 1, + 'id_customization' => 1, + ], + [ + 'product_attribute_id' => 2, + 'id_product_attribute' => 2, + 'total_price_tax_excl' => 100.00, + 'product_price' => 100.00, + 'total_price' => 100.00, + 'total_price_tax_incl' => 121.00, + 'product_price_wt' => 121.00, + 'total_wt' => 121.00, + 'product_name' => 'test-product-2', + 'product_quantity' => 2, + 'product_id' => 2, + 'id_customization' => 1, + ], + [ + 'product_attribute_id' => 3, + 'id_product_attribute' => 3, + 'total_price_tax_excl' => 1000.00, + 'product_price' => 1000.00, + 'total_price' => 1000.00, + 'total_price_tax_incl' => 1210.00, + 'product_price_wt' => 1210.00, + 'total_wt' => 1210.00, + 'product_name' => 'test-product-3', + 'product_quantity' => 3, + 'product_id' => 3, + 'id_customization' => 1, + ], + ]; + + $order = $this->createMock(\Order::class); + $order->total_paid_tax_excl = 1500; + $order->id_currency = 1; + $order->method('getCartProducts')->willReturn($products); + $order->method('getProducts')->willReturn($products); + + /** @var OrderPresenter $orderPresenter */ + $orderPresenter = $this->getService(OrderPresenter::class); + + $result = $orderPresenter->present( + $order, + 3, + 1300 + ); + + $this->assertCount(1, $result->getProducts()); + $this->assertEquals(3, $result->getProducts()[0]['id_product_attribute']); + } +} diff --git a/tests/bootstrap.php b/tests/bootstrap.php index f29c2f9d7..6db43cd14 100644 --- a/tests/bootstrap.php +++ b/tests/bootstrap.php @@ -1,9 +1,21 @@ boot(); +} +// any actions to apply before any given tests can be done here diff --git a/upgrade/Upgrade-6.0.4.php b/upgrade/Upgrade-6.0.4.php index 497c98904..57205a314 100644 --- a/upgrade/Upgrade-6.0.4.php +++ b/upgrade/Upgrade-6.0.4.php @@ -28,6 +28,10 @@ function upgrade_module_6_0_4(Mollie $module): bool updateConfigurationValues604($module); updateOrderStatusNames604($module); + if (!modifyExistingTables604()) { + return false; + } + return true; } @@ -105,3 +109,70 @@ function updateOrderStatusNames604(Mollie $module) $authorizablePaymentStatusAuthorized->save(); } +function modifyExistingTables604(): bool +{ + $sql = ' + SELECT COUNT(*) > 0 AS count + FROM information_schema.columns + WHERE TABLE_SCHEMA = "' . _DB_NAME_ . '" AND table_name = "' . _DB_PREFIX_ . 'mol_recurring_order" AND column_name = "total_tax_incl"; + '; + + /** only add it if it doesn't exist */ + if (!(int) Db::getInstance()->getValue($sql)) { + $sql = ' + ALTER TABLE ' . _DB_PREFIX_ . 'mol_recurring_order + ADD COLUMN total_tax_incl decimal(20, 6) NOT NULL; + '; + + try { + if (!Db::getInstance()->execute($sql)) { + return false; + } + } catch (Exception $e) { + PrestaShopLogger::addLog("Mollie upgrade error: {$e->getMessage()}"); + + return false; + } + } + + $sql = ' + UPDATE ' . _DB_PREFIX_ . 'mol_recurring_order ro + JOIN ' . _DB_PREFIX_ . 'orders o ON ro.id_order = o.id_order + SET ro.total_tax_incl = o.total_paid_tax_incl; + '; + + try { + Db::getInstance()->execute($sql); + } catch (Exception $e) { + PrestaShopLogger::addLog("Mollie upgrade error: {$e->getMessage()}"); + + return false; + } + + $sql = ' + SELECT COUNT(*) > 0 AS count + FROM INFORMATION_SCHEMA.COLUMNS + WHERE TABLE_SCHEMA = "' . _DB_NAME_ . '" AND TABLE_NAME = "' . _DB_PREFIX_ . 'mollie_payments" AND COLUMN_NAME = "mandate_id" + '; + + /** only add it if it doesn't exist */ + if (!Db::getInstance()->getValue($sql)) { + $sql = ' + ALTER TABLE ' . _DB_PREFIX_ . 'mollie_payments + ADD `mandate_id` VARCHAR(64); + '; + + try { + if (!Db::getInstance()->execute($sql)) { + return false; + } + } catch (Exception $e) { + PrestaShopLogger::addLog("Mollie upgrade error: {$e->getMessage()}"); + + return false; + } + } + + return true; +} +