From d4ed0dcfa1834b904b610dbf7a3093e1a91b8a52 Mon Sep 17 00:00:00 2001 From: Michiel Gerritsen Date: Thu, 12 Oct 2023 13:20:01 +0200 Subject: [PATCH] Bugfix: When a new payment comes in, the Next Payment Date is updated --- Controller/Api/Webhook.php | 10 +++- Service/Mollie/UpdateNextPaymentDate.php | 33 +++++++++++ .../Controller/Api/WebhookTest.php | 57 +++++++++++++++++++ 3 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 Service/Mollie/UpdateNextPaymentDate.php diff --git a/Controller/Api/Webhook.php b/Controller/Api/Webhook.php index 572d39a..1b5ab10 100644 --- a/Controller/Api/Webhook.php +++ b/Controller/Api/Webhook.php @@ -28,6 +28,7 @@ use Mollie\Subscriptions\Service\Magento\CreateOrderFromSubscription; use Mollie\Subscriptions\Service\Mollie\RetryUsingOtherStoreViews; use Mollie\Subscriptions\Service\Mollie\SendAdminNotification; +use Mollie\Subscriptions\Service\Mollie\UpdateNextPaymentDate; class Webhook extends Action implements CsrfAwareActionInterface { @@ -89,6 +90,10 @@ class Webhook extends Action implements CsrfAwareActionInterface * @var OrderCommentHistory */ private $orderCommentHistory; + /** + * @var UpdateNextPaymentDate + */ + private $updateNextPaymentDate; public function __construct( Context $context, @@ -102,7 +107,8 @@ public function __construct( LinkTransactionToOrder $linkTransactionToOrder, OrderCommentHistory $orderCommentHistory, SendAdminNotification $sendAdminNotification, - CreateOrderFromSubscription $createOrderFromSubscription + CreateOrderFromSubscription $createOrderFromSubscription, + UpdateNextPaymentDate $updateNextPaymentDate ) { parent::__construct($context); @@ -117,6 +123,7 @@ public function __construct( $this->orderCommentHistory = $orderCommentHistory; $this->sendAdminNotification = $sendAdminNotification; $this->createOrderFromSubscription = $createOrderFromSubscription; + $this->updateNextPaymentDate = $updateNextPaymentDate; } public function execute() @@ -145,6 +152,7 @@ public function execute() try { $molliePayment = $this->getPayment($id); $subscription = $this->api->subscriptions->getForId($molliePayment->customerId, $molliePayment->subscriptionId); + $this->updateNextPaymentDate->execute($subscription); $order = $this->createOrderFromSubscription->execute($this->api, $molliePayment, $subscription); diff --git a/Service/Mollie/UpdateNextPaymentDate.php b/Service/Mollie/UpdateNextPaymentDate.php new file mode 100644 index 0000000..e855f73 --- /dev/null +++ b/Service/Mollie/UpdateNextPaymentDate.php @@ -0,0 +1,33 @@ +subscriptionToProductRepository = $subscriptionToProductRepository; + } + + public function execute(Subscription $subscription): void + { + $row = $this->subscriptionToProductRepository->getBySubscriptionId($subscription->id); + $row->setNextPaymentDate($subscription->nextPaymentDate); + $this->subscriptionToProductRepository->save($row); + } +} diff --git a/Test/Integration/Controller/Api/WebhookTest.php b/Test/Integration/Controller/Api/WebhookTest.php index 05836d7..ca37ba2 100644 --- a/Test/Integration/Controller/Api/WebhookTest.php +++ b/Test/Integration/Controller/Api/WebhookTest.php @@ -20,10 +20,17 @@ use Mollie\Payment\Model\Mollie; use Mollie\Payment\Test\Fakes\FakeEncryptor; use Mollie\Payment\Test\Integration\MolliePaymentBuilder; +use Mollie\Subscriptions\Api\Data\SubscriptionToProductInterface; +use Mollie\Subscriptions\Api\SubscriptionToProductRepositoryInterface; use Mollie\Subscriptions\Service\Mollie\MollieSubscriptionApi; class WebhookTest extends ControllerTestCase { + /** + * @var Subscription + */ + private $subscription; + public function testAcceptsPost() { $instance = $this->_objectManager->get(FakeEncryptor::class); @@ -113,6 +120,38 @@ public function testDoesNotCreateMultipleOrders(): void $this->assertEquals(0, $spy->getInvocationCount()); } + /** + * @magentoDataFixture Magento/Customer/_files/customer_with_addresses.php + * @magentoDataFixture Magento/Catalog/_files/product_simple.php + * @magentoConfigFixture default_store mollie_subscriptions/general/shipping_method flatrate_flatrate + */ + public function testUpdatesNextPaymentDate(): void + { + $transactionId = 'tr_testtransaction'; + + $this->createMollieCustomer(); + $api = $this->getApi($transactionId); + + $mollieSubscriptionApi = $this->createMock(MollieSubscriptionApi::class); + $mollieSubscriptionApi->method('loadByStore')->willReturn($api); + $this->_objectManager->addSharedInstance($mollieSubscriptionApi, MollieSubscriptionApi::class); + + // Check how many orders there are before the webhook is called + $ordersCount = count($this->getOrderIdsByTransactionId($transactionId)); + + $mollieMock = $this->createMock(Mollie::class); + $mollieMock->method('processTransactionForOrder'); + $this->_objectManager->addSharedInstance($mollieMock, Mollie::class); + + $this->dispatch('mollie-subscriptions/api/webhook?id=' . $transactionId); + $this->assertEquals(200, $this->getResponse()->getStatusCode()); + + $repository = $this->_objectManager->create(SubscriptionToProductRepositoryInterface::class); + $subscription = $repository->getBySubscriptionId('sub_testsubscription'); + + $this->assertEquals('2019-11-19', $subscription->getNextPaymentDate()); + } + private function createMollieCustomer(): void { /** @var CustomerRepositoryInterface $customerRepository */ @@ -155,9 +194,11 @@ private function getSubscription(): Subscription { /** @var Subscription $subscription */ $subscription = $this->_objectManager->get(Subscription::class); + $subscription->id = 'sub_testsubscription'; $subscription->customerId = 'cst_testcustomer'; $subscription->metadata = new \stdClass(); $subscription->metadata->sku = 'simple'; + $subscription->nextPaymentDate = '2019-11-19'; return $subscription; } @@ -169,6 +210,7 @@ private function getPayment(string $transactionId): Payment $payment->id = $transactionId; $payment->customerId = 'cst_testcustomer'; + $payment->subscriptionId = 'sub_testsubscription'; $payment->_links = new \stdClass(); $payment->_links->subscription = new \stdClass(); $payment->_links->subscription->href = 'https://example.com/mollie/subscriptions/sub_testsubscription'; @@ -179,6 +221,9 @@ private function getPayment(string $transactionId): Payment private function getApi(string $transactionId): MollieApiClient { $subscription = $this->getSubscription(); + $this->subscription = $subscription; + + $this->createSubscriptionDatabaseRecord(); $subscriptionsEndpointMock = $this->createMock(SubscriptionEndpoint::class); $subscriptionsEndpointMock->method('getForId')->willReturn($subscription); @@ -206,4 +251,16 @@ private function loadOrderById($orderId): OrderInterface return array_shift($orderList); } + + private function createSubscriptionDatabaseRecord(): void + { + /** @var SubscriptionToProductInterface $subscription */ + $subscription = $this->_objectManager->create(SubscriptionToProductInterface::class); + $subscription->setSubscriptionId('sub_testsubscription'); + $subscription->setNextPaymentDate('2019-11-12'); + $subscription->setCustomerId('cst_testcustomer'); + $subscription->setProductId(1); + + $this->_objectManager->get(SubscriptionToProductRepositoryInterface::class)->save($subscription); + } }