From 183afce10b87a618da4a43d824cc901bb1b146c6 Mon Sep 17 00:00:00 2001 From: Michiel Gerritsen Date: Tue, 7 Apr 2026 11:24:08 +0200 Subject: [PATCH 1/3] Bugfix: Trim template name --- etc/config.xml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/etc/config.xml b/etc/config.xml index 85225c3..c8a95d4 100755 --- a/etc/config.xml +++ b/etc/config.xml @@ -41,8 +41,7 @@ 0 Mollie_Subscriptions_emails_customer_cancel_notification_template 1 - Mollie_Subscriptions_emails_admin_failure_notification_template - + Mollie_Subscriptions_emails_admin_failure_notification_template From 5f616a4b75cae901c1f0489173bf7fe147dfc82f Mon Sep 17 00:00:00 2001 From: Michiel Gerritsen Date: Mon, 13 Apr 2026 10:00:19 +0200 Subject: [PATCH 2/3] Improvement: Add fallback shipping method --- Model/Carrier/SubscriptionShipping.php | 36 +++++++++++++++++ .../Magento/CreateOrderFromSubscription.php | 37 +++++++++++++++++- .../CreateOrderFromSubscriptionTest.php | 39 +++++++++++++++++++ etc/config.xml | 9 +++++ .../checkout/summary/trial-discount.html | 2 +- 5 files changed, 121 insertions(+), 2 deletions(-) create mode 100644 Model/Carrier/SubscriptionShipping.php diff --git a/Model/Carrier/SubscriptionShipping.php b/Model/Carrier/SubscriptionShipping.php new file mode 100644 index 0000000..f12b7e6 --- /dev/null +++ b/Model/Carrier/SubscriptionShipping.php @@ -0,0 +1,36 @@ + $this->getConfigData('name') ?: 'Mollie Subscriptions Fallback Shipping']; + } +} diff --git a/Service/Magento/CreateOrderFromSubscription.php b/Service/Magento/CreateOrderFromSubscription.php index 5d7f45d..4b82b24 100644 --- a/Service/Magento/CreateOrderFromSubscription.php +++ b/Service/Magento/CreateOrderFromSubscription.php @@ -19,6 +19,8 @@ use Magento\Quote\Api\Data\AddressInterface; use Magento\Quote\Api\Data\AddressInterfaceFactory; use Magento\Quote\Api\Data\CartInterface; +use Magento\Quote\Model\Quote\Address as QuoteAddress; +use Magento\Quote\Model\Quote\Address\RateFactory; use Magento\Sales\Api\Data\OrderAddressInterface; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Api\OrderAddressRepositoryInterface; @@ -29,6 +31,7 @@ use Mollie\Payment\Api\MollieCustomerRepositoryInterface; use Mollie\Payment\Logger\MollieLogger; use Mollie\Subscriptions\Config; +use Mollie\Subscriptions\Model\Carrier\SubscriptionShipping; class CreateOrderFromSubscription { @@ -97,6 +100,10 @@ class CreateOrderFromSubscription * @var SubscriptionAddProductToCart */ private $subscriptionAddToCart; + /** + * @var RateFactory + */ + private $rateFactory; public function __construct( Config $config, @@ -110,7 +117,8 @@ public function __construct( AddressInterfaceFactory $addressFactory, MollieLogger $mollieLogger, OrderAddressRepositoryInterface $orderAddressRepository, - SubscriptionAddProductToCart $addProductToCart + SubscriptionAddProductToCart $addProductToCart, + RateFactory $rateFactory ) { $this->mollieCustomerRepository = $mollieCustomerRepository; $this->customerRepository = $customerRepository; @@ -124,6 +132,7 @@ public function __construct( $this->mollieLogger = $mollieLogger; $this->orderAddressRepository = $orderAddressRepository; $this->subscriptionAddToCart = $addProductToCart; + $this->rateFactory = $rateFactory; } public function execute(MollieApiClient $api, Payment $molliePayment, Subscription $subscription): OrderInterface @@ -222,6 +231,32 @@ private function configureShipping(CartInterface $cart) ', switched to ' . $newMethod ); } + + if ($shippingAddress->getShippingRateByCode($shippingAddress->getShippingMethod()) === false) { + $this->applyFallbackShippingMethod($shippingAddress); + } + } + + private function applyFallbackShippingMethod(QuoteAddress $shippingAddress): void + { + $fallbackCode = 'mollie_subscriptions_fallback_shipping'; + + $rate = $this->rateFactory->create(); + $rate->setCarrier(SubscriptionShipping::CARRIER_CODE); + $rate->setCarrierTitle('Mollie Subscriptions Shipping Fallback'); + $rate->setMethod('fallback_shipping'); + $rate->setMethodTitle('Subscription Shipping'); + $rate->setPrice(0); + $rate->setCost(0); + $rate->setCode($fallbackCode); + + $shippingAddress->addShippingRate($rate); + $shippingAddress->setShippingMethod($fallbackCode); + + $this->mollieLogger->addInfoLog( + 'subscriptions', + 'No shipping rates available at all, using Mollie Subscriptions fallback carrier' + ); } /** diff --git a/Test/Integration/Service/Magento/CreateOrderFromSubscriptionTest.php b/Test/Integration/Service/Magento/CreateOrderFromSubscriptionTest.php index ed2f9ca..9ae8df8 100644 --- a/Test/Integration/Service/Magento/CreateOrderFromSubscriptionTest.php +++ b/Test/Integration/Service/Magento/CreateOrderFromSubscriptionTest.php @@ -99,6 +99,45 @@ public function testHandlesVirtualProductsCorrect(): void $this->assertSame(1, $order->getIsVirtual()); } + /** + * @magentoDataFixture Magento/Customer/_files/customer_with_addresses.php + * @magentoDataFixture Magento/Sales/_files/order.php + * @magentoConfigFixture default_store carriers/flatrate/active 0 + * @magentoConfigFixture default_store carriers/freeshipping/active 0 + * @magentoConfigFixture default_store carriers/tablerate/active 0 + * @magentoConfigFixture default_store mollie_subscriptions/general/shipping_method flatrate_flatrate + * + * @return void + */ + public function testFallsBackToSubscriptionShippingWhenNoRatesAvailable(): void + { + $this->createMollieCustomer(); + $order = $this->loadOrderById('100000001'); + + $molliePaymentBuilder = $this->objectManager->get(MolliePaymentBuilder::class); + $molliePaymentBuilder->setMethod('ideal'); + + $payment = $molliePaymentBuilder->build(); + $payment->customerId = 'cst_testcustomer'; + + $subscription = $this->objectManager->get(Subscription::class); + $subscription->amount = new stdClass(); + $subscription->amount->value = 100; + $subscription->amount->currency = 'EUR'; + $subscription->customerId = 'cst_testcustomer'; + $subscription->metadata = new stdClass(); + $subscription->metadata->quantity = '1'; + $subscription->metadata->sku = 'simple'; + $subscription->metadata->billingAddressId = $order->getBillingAddressId(); + $subscription->metadata->shippingAddressId = $order->getBillingAddressId(); + + $instance = $this->objectManager->create(CreateOrderFromSubscription::class); + + $result = $instance->execute(new MollieApiClient(), $payment, $subscription); + + $this->assertSame('mollie_subscriptions_fallback_shipping', $result->getShippingMethod()); + } + private function createMollieCustomer(): void { /** @var CustomerRepositoryInterface $customerRepository */ diff --git a/etc/config.xml b/etc/config.xml index 9d3bd24..b768cc4 100755 --- a/etc/config.xml +++ b/etc/config.xml @@ -45,5 +45,14 @@ + + + 1 + Mollie\Subscriptions\Model\Carrier\SubscriptionShipping + Mollie Subscriptions Fallback Shipping + Mollie Subscriptions Shipping Fallback + 0 + + diff --git a/view/frontend/web/template/checkout/summary/trial-discount.html b/view/frontend/web/template/checkout/summary/trial-discount.html index e9f1e86..d33eff1 100644 --- a/view/frontend/web/template/checkout/summary/trial-discount.html +++ b/view/frontend/web/template/checkout/summary/trial-discount.html @@ -18,7 +18,7 @@ - + From 78bd9e94c9a1edc4e127c1ca1b09df3b0acc3ad2 Mon Sep 17 00:00:00 2001 From: Michiel Gerritsen Date: Mon, 13 Apr 2026 10:08:00 +0200 Subject: [PATCH 3/3] Improvement: Only delete subscription row if deletion is successful --- Controller/Adminhtml/Subscriptions/Cancel.php | 8 ++++++-- Controller/Index/Cancel.php | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Controller/Adminhtml/Subscriptions/Cancel.php b/Controller/Adminhtml/Subscriptions/Cancel.php index c60380a..b0461c1 100644 --- a/Controller/Adminhtml/Subscriptions/Cancel.php +++ b/Controller/Adminhtml/Subscriptions/Cancel.php @@ -53,9 +53,11 @@ public function execute() $api = $this->mollieSubscriptionApi->loadByStore($this->getRequest()->getParam('store_id')); $customerId = $this->getRequest()->getParam('customer_id'); $subscriptionId = $this->getRequest()->getParam('subscription_id'); + $canceled = false; try { $api->subscriptions->cancelForId($customerId, $subscriptionId); + $canceled = true; $model = $this->subscriptionToProductRepository->getBySubscriptionId($subscriptionId); $this->eventManager->dispatch('mollie_subscription_after_cancelled', ['subscription' => $model]); } catch (\Exception $exception) { @@ -69,8 +71,10 @@ public function execute() return $this->_redirect('*/*/'); } finally { - $this->subscriptionToProductRepository->deleteBySubscriptionId($customerId, $subscriptionId); - $this->eventManager->dispatch('mollie_subscription_cancelled', ['subscription_id' => $subscriptionId]); + if ($canceled) { + $this->subscriptionToProductRepository->deleteBySubscriptionId($customerId, $subscriptionId); + $this->eventManager->dispatch('mollie_subscription_cancelled', ['subscription_id' => $subscriptionId]); + } } $this->messageManager->addSuccessMessage( diff --git a/Controller/Index/Cancel.php b/Controller/Index/Cancel.php index 2e72541..540be6d 100644 --- a/Controller/Index/Cancel.php +++ b/Controller/Index/Cancel.php @@ -95,6 +95,7 @@ public function execute() { $customer = $this->currentCustomer->getCustomer(); $extensionAttributes = $customer->getExtensionAttributes(); + $canceled = false; $api = $this->mollieSubscriptionApi->loadByStore($customer->getStoreId()); $subscriptionId = $this->getRequest()->getParam('subscription_id'); @@ -102,6 +103,7 @@ public function execute() try { $model = $this->subscriptionToProductRepository->getBySubscriptionId($subscriptionId); $api->subscriptions->cancelForId($extensionAttributes->getMollieCustomerId(), $subscriptionId); + $canceled = true; $this->sendAdminCancelNotificationEmail->execute($model); $this->sendCustomerCancelNotificationEmail->execute($model); @@ -116,7 +118,9 @@ public function execute() return $this->_redirect('*/*/'); } finally { - $this->deleteSubscriptionReference($extensionAttributes->getMollieCustomerId(), $subscriptionId); + if ($canceled) { + $this->deleteSubscriptionReference($extensionAttributes->getMollieCustomerId(), $subscriptionId); + } } $this->messageManager->addSuccessMessage(