From d23bb6d47338f688cff0d7341cfae8942e9e908b Mon Sep 17 00:00:00 2001 From: mandan2 Date: Tue, 26 Sep 2023 16:37:18 +0300 Subject: [PATCH] PIPRES-261: Subscription order detail view refactoring --- controllers/front/recurringOrderDetail.php | 21 +- src/Adapter/Context.php | 14 + src/Repository/ProductRepository.php | 23 ++ src/Repository/ProductRepositoryInterface.php | 10 + src/ServiceProvider/BaseServiceProvider.php | 6 + .../Exception/CouldNotPresentOrderDetail.php | 38 +++ subscription/Exception/ExceptionCode.php | 20 +- .../Presenter/OrderDetailPresenter.php | 130 ++++++++ subscription/Presenter/OrderPresenter.php | 35 --- .../Presenter/RecurringOrderLazyArray.php | 40 --- .../Presenter/RecurringOrderPresenter.php | 24 +- .../Repository/OrderDetailRepository.php | 11 + .../OrderDetailRepositoryInterface.php | 9 + .../Presenter/OrderPresenterTest.php | 75 ----- .../Presenter/OrderDetailPresenterTest.php | 283 ++++++++++++++++++ .../subscription/customer_order_detail.css | 7 + .../customerRecurringOrderDetail.tpl | 5 +- .../customerRecurringOrderDetailProduct.tpl | 31 ++ 18 files changed, 604 insertions(+), 178 deletions(-) create mode 100644 src/Repository/ProductRepository.php create mode 100644 src/Repository/ProductRepositoryInterface.php create mode 100644 subscription/Exception/CouldNotPresentOrderDetail.php create mode 100644 subscription/Presenter/OrderDetailPresenter.php delete mode 100644 subscription/Presenter/OrderPresenter.php delete mode 100644 subscription/Presenter/RecurringOrderLazyArray.php create mode 100644 subscription/Repository/OrderDetailRepository.php create mode 100644 subscription/Repository/OrderDetailRepositoryInterface.php delete mode 100644 tests/Integration/Subscription/Presenter/OrderPresenterTest.php create mode 100644 tests/Unit/Subscription/Presenter/OrderDetailPresenterTest.php create mode 100644 views/templates/front/subscription/customerRecurringOrderDetailProduct.tpl diff --git a/controllers/front/recurringOrderDetail.php b/controllers/front/recurringOrderDetail.php index 6fe4b7b86..300f83372 100644 --- a/controllers/front/recurringOrderDetail.php +++ b/controllers/front/recurringOrderDetail.php @@ -25,6 +25,7 @@ */ use Mollie\Controller\AbstractMollieController; +use Mollie\Logger\PrestaLoggerInterface; use Mollie\Subscription\Handler\FreeOrderCreationHandler; use Mollie\Subscription\Handler\SubscriptionCancellationHandler; use Mollie\Subscription\Presenter\RecurringOrderPresenter; @@ -74,13 +75,25 @@ public function initContent() Tools::redirect(Context::getContext()->link->getModuleLink($this->module->name, 'subscriptions', [], true)); } + /** @var PrestaLoggerInterface $logger */ + $logger = $this->module->getService(PrestaLoggerInterface::class); + /** @var RecurringOrderPresenter $recurringOrderPresenter */ $recurringOrderPresenter = $this->module->getService(RecurringOrderPresenter::class); - $this->context->smarty->assign([ - 'recurringOrderData' => $recurringOrderPresenter->present($recurringOrderId), - 'token' => Tools::getToken(), - ]); + try { + $this->context->smarty->assign([ + 'recurringOrderData' => $recurringOrderPresenter->present($recurringOrderId), + 'token' => Tools::getToken(), + ]); + } catch (Throwable $exception) { + $logger->error('Failed to present subscription order', [ + 'Exception message' => $exception->getMessage(), + 'Exception code' => $exception->getCode(), + ]); + + Tools::redirect(Context::getContext()->link->getModuleLink($this->module->name, 'subscriptions', [], true)); + } parent::initContent(); $this->context->controller->addCSS($this->module->getPathUri() . 'views/css/front/subscription/customer_order_detail.css'); diff --git a/src/Adapter/Context.php b/src/Adapter/Context.php index 2bdf0a9d5..27629cad5 100644 --- a/src/Adapter/Context.php +++ b/src/Adapter/Context.php @@ -130,4 +130,18 @@ public function getShopGroupId(): int { return (int) PrestashopContext::getContext()->shop->id_shop_group; } + + public function formatPrice(float $price, string $isoCode): string + { + $locale = PrestashopContext::getContext()->getCurrentLocale(); + + if (!$locale) { + return (string) $price; + } + + return $locale->formatPrice( + $price, + $isoCode + ); + } } diff --git a/src/Repository/ProductRepository.php b/src/Repository/ProductRepository.php new file mode 100644 index 000000000..dafa55496 --- /dev/null +++ b/src/Repository/ProductRepository.php @@ -0,0 +1,23 @@ +addService($container, RetryHandlerInterface::class, $container->get(RetryHandler::class)); + $this->addService($container, ProductRepositoryInterface::class, $container->get(ProductRepository::class)); + $this->addService($container, OrderDetailRepositoryInterface::class, $container->get(OrderDetailRepository::class)); $this->addService($container, CountryRepositoryInterface::class, $container->get(CountryRepository::class)); $this->addService($container, PaymentMethodRepositoryInterface::class, $container->get(PaymentMethodRepository::class)); $this->addService($container, GenderRepositoryInterface::class, $container->get(GenderRepository::class)); diff --git a/subscription/Exception/CouldNotPresentOrderDetail.php b/subscription/Exception/CouldNotPresentOrderDetail.php new file mode 100644 index 000000000..2b07862b9 --- /dev/null +++ b/subscription/Exception/CouldNotPresentOrderDetail.php @@ -0,0 +1,38 @@ +orderDetailRepository = $orderDetailRepository; + $this->context = $context; + $this->orderRepository = $orderRepository; + $this->productRepository = $productRepository; + $this->currencyRepository = $currencyRepository; + } + + /** + * @throws CouldNotPresentOrderDetail + */ + public function present( + \MolRecurringOrder $recurringOrder, + \MolRecurringOrdersProduct $recurringProduct + ): array { + $result = []; + + /** @var \Order|null $order */ + $order = $this->orderRepository->findOneBy([ + 'id_order' => (int) $recurringOrder->id_order, + ]); + + if (!$order) { + throw CouldNotPresentOrderDetail::failedToFindOrder(); + } + + /** @var \OrderDetail|null $orderDetail */ + $orderDetail = $this->orderDetailRepository->findOneBy([ + 'id_order' => (int) $recurringOrder->id_order, + 'product_id' => (int) $recurringProduct->id_product, + 'product_attribute_id' => (int) $recurringProduct->id_product_attribute, + ]); + + if (!$orderDetail) { + throw CouldNotPresentOrderDetail::failedToFindOrderDetail(); + } + + /** @var \Product|null $product */ + $product = $this->productRepository->findOneBy([ + 'id_product' => (int) $recurringProduct->id_product, + ]); + + if (!$product) { + throw CouldNotPresentOrderDetail::failedToFindProduct(); + } + + /** @var \Currency|null $currency */ + $currency = $this->currencyRepository->findOneBy([ + 'id_currency' => (int) $order->id_currency, + ]); + + if (!$currency) { + throw CouldNotPresentOrderDetail::failedToFindCurrency(); + } + + $linkRewrite = is_array($product->link_rewrite) && isset($product->link_rewrite[$order->id_lang]) + ? $product->link_rewrite[$order->id_lang] + : $product->link_rewrite; + + $image = $this->productRepository->getCombinationImageById((int) $recurringProduct->id_product_attribute, (int) $order->id_lang); + + if (!$image) { + $image = $this->productRepository->getCover((int) $recurringProduct->id_product); + } + + $result['name'] = $orderDetail->product_name; + $result['link'] = $this->context->getProductLink($product); + $result['img'] = $this->context->getImageLink($linkRewrite, (string) $image['id_image']); + $result['quantity'] = $orderDetail->product_quantity; + $result['unit_price'] = $this->context->formatPrice( + NumberUtility::toPrecision( + (float) $orderDetail->unit_price_tax_incl, + NumberUtility::DECIMAL_PRECISION + ), + $currency->iso_code + ); + $result['total'] = $this->context->formatPrice( + NumberUtility::toPrecision( + (float) $recurringOrder->total_tax_incl, + NumberUtility::DECIMAL_PRECISION + ), + $currency->iso_code + ); + + $result['status'] = $recurringOrder->status; + $result['start_date'] = $recurringOrder->date_add; + + if ($recurringOrder->status === SubscriptionStatus::STATUS_ACTIVE) { + $result['next_payment_date'] = $recurringOrder->next_payment; + } + + if ($recurringOrder->status === SubscriptionStatus::STATUS_CANCELED) { + $result['cancelled_date'] = $recurringOrder->cancelled_at; + } + + return $result; + } +} diff --git a/subscription/Presenter/OrderPresenter.php b/subscription/Presenter/OrderPresenter.php deleted file mode 100644 index c907b7e7c..000000000 --- a/subscription/Presenter/OrderPresenter.php +++ /dev/null @@ -1,35 +0,0 @@ -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 deleted file mode 100644 index 7d91bf59f..000000000 --- a/subscription/Presenter/RecurringOrderLazyArray.php +++ /dev/null @@ -1,40 +0,0 @@ -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 3601cec40..0c73f39e2 100644 --- a/subscription/Presenter/RecurringOrderPresenter.php +++ b/subscription/Presenter/RecurringOrderPresenter.php @@ -9,8 +9,8 @@ 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,23 +23,26 @@ class RecurringOrderPresenter private $language; /** @var MethodApi */ private $methodApi; - /** @var OrderPresenter */ - private $orderPresenter; + /** @var OrderDetailPresenter */ + private $orderDetailPresenter; public function __construct( RecurringOrderRepositoryInterface $recurringOrderRepository, RecurringOrdersProductRepositoryInterface $recurringOrdersProductRepository, Language $language, MethodApi $methodApi, - OrderPresenter $orderPresenter + OrderDetailPresenter $orderDetailPresenter ) { $this->recurringOrderRepository = $recurringOrderRepository; $this->recurringOrdersProductRepository = $recurringOrdersProductRepository; $this->language = $language; $this->methodApi = $methodApi; - $this->orderPresenter = $orderPresenter; + $this->orderDetailPresenter = $orderDetailPresenter; } + /** + * @throws \Throwable + */ public function present(int $recurringOrderId): array { $recurringOrder = $this->recurringOrderRepository->findOneBy(['id_mol_recurring_order' => $recurringOrderId]); @@ -60,13 +63,10 @@ public function present(int $recurringOrderId): array $recurringOrderData['recurring_order'] = $recurringOrder; $recurringOrderData['recurring_product'] = $recurringProduct; $recurringOrderData['product'] = $product; - $recurringOrderData['order'] = $this->orderPresenter->present( - $order, - (int) $recurringProduct->id_product_attribute, - NumberUtility::toPrecision( - (float) $recurringOrder->total_tax_incl, - NumberUtility::DECIMAL_PRECISION - ) + $recurringOrderData['order'] = (new OrderPresenter())->present($order); + $recurringOrderData['order_detail'] = $this->orderDetailPresenter->present( + $recurringOrder, + $recurringProduct ); $recurringOrderData['payment_methods'] = $this->methodApi->getMethodsForFirstPayment($this->language->getContextLanguage()->locale, $currency->iso_code); diff --git a/subscription/Repository/OrderDetailRepository.php b/subscription/Repository/OrderDetailRepository.php new file mode 100644 index 000000000..5afa02e64 --- /dev/null +++ b/subscription/Repository/OrderDetailRepository.php @@ -0,0 +1,11 @@ + 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/Unit/Subscription/Presenter/OrderDetailPresenterTest.php b/tests/Unit/Subscription/Presenter/OrderDetailPresenterTest.php new file mode 100644 index 000000000..62663ba1a --- /dev/null +++ b/tests/Unit/Subscription/Presenter/OrderDetailPresenterTest.php @@ -0,0 +1,283 @@ +orderDetailRepository = $this->createMock(OrderDetailRepositoryInterface::class); + $this->context = $this->createMock(Context::class); + $this->orderRepository = $this->createMock(OrderRepositoryInterface::class); + $this->productRepository = $this->createMock(ProductRepositoryInterface::class); + $this->currencyRepository = $this->createMock(CurrencyRepositoryInterface::class); + + parent::setUp(); + } + + public function testItSuccessfullyPresentsOrderDetail(): void + { + /** @var \Order $order */ + $order = $this->createMock(\Order::class); + $order->id_lang = 1; + + /** @var \OrderDetail $orderDetail */ + $orderDetail = $this->createMock(\OrderDetail::class); + $orderDetail->unit_price_tax_incl = 1.11; + + /** @var \Product $product */ + $product = $this->createMock(\Product::class); + + /** @var \Currency $currency */ + $currency = $this->createMock(\Currency::class); + $currency->iso_code = 'EUR'; + + /** @var \MolRecurringOrder $recurringOrder */ + $recurringOrder = $this->createMock(\MolRecurringOrder::class); + $recurringOrder->total_tax_incl = 1.11; + $recurringOrder->status = SubscriptionStatus::STATUS_ACTIVE; + + /** @var \MolRecurringOrdersProduct $recurringProduct */ + $recurringProduct = $this->createMock(\MolRecurringOrdersProduct::class); + $recurringProduct->id_product = 1; + $recurringProduct->id_product_attribute = 1; + + $this->orderRepository->expects($this->once())->method('findOneBy')->willReturn($order); + $this->orderDetailRepository->expects($this->once())->method('findOneBy')->willReturn($orderDetail); + $this->productRepository->expects($this->once())->method('findOneBy')->willReturn($product); + $this->productRepository->expects($this->once())->method('getCombinationImageById')->willReturn(['id_image' => 1]); + $this->currencyRepository->expects($this->once())->method('findOneBy')->willReturn($currency); + + $this->context->expects($this->once())->method('getProductLink')->willReturn('test-link'); + $this->context->expects($this->once())->method('getImageLink')->willReturn('test-link'); + $this->context->expects($this->exactly(2))->method('formatPrice')->willReturn('123.33$'); + + $orderDetailPresenter = new OrderDetailPresenter( + $this->orderDetailRepository, + $this->context, + $this->orderRepository, + $this->productRepository, + $this->currencyRepository + ); + + $result = $orderDetailPresenter->present($recurringOrder, $recurringProduct); + + $this->assertArrayHasKey('next_payment_date', $result); + $this->assertArrayNotHasKey('cancelled_date', $result); + } + + public function testItSuccessfullyPresentsCancelledOrderDetailWithDefaultProductImage(): void + { + /** @var \Order $order */ + $order = $this->createMock(\Order::class); + $order->id_lang = 1; + + /** @var \OrderDetail $orderDetail */ + $orderDetail = $this->createMock(\OrderDetail::class); + $orderDetail->unit_price_tax_incl = 1.11; + + /** @var \Product $product */ + $product = $this->createMock(\Product::class); + + /** @var \Currency $currency */ + $currency = $this->createMock(\Currency::class); + $currency->iso_code = 'EUR'; + + /** @var \MolRecurringOrder $recurringOrder */ + $recurringOrder = $this->createMock(\MolRecurringOrder::class); + $recurringOrder->total_tax_incl = 1.11; + $recurringOrder->status = SubscriptionStatus::STATUS_CANCELED; + + /** @var \MolRecurringOrdersProduct $recurringProduct */ + $recurringProduct = $this->createMock(\MolRecurringOrdersProduct::class); + $recurringProduct->id_product = 1; + $recurringProduct->id_product_attribute = 1; + + $this->orderRepository->expects($this->once())->method('findOneBy')->willReturn($order); + $this->orderDetailRepository->expects($this->once())->method('findOneBy')->willReturn($orderDetail); + $this->productRepository->expects($this->once())->method('findOneBy')->willReturn($product); + $this->productRepository->expects($this->once())->method('getCombinationImageById')->willReturn(null); + $this->productRepository->expects($this->once())->method('getCover')->willReturn(['id_image' => 1]); + $this->currencyRepository->expects($this->once())->method('findOneBy')->willReturn($currency); + + $this->context->expects($this->once())->method('getProductLink')->willReturn('test-link'); + $this->context->expects($this->once())->method('getImageLink')->willReturn('test-link'); + $this->context->expects($this->exactly(2))->method('formatPrice')->willReturn('123.33$'); + + $orderDetailPresenter = new OrderDetailPresenter( + $this->orderDetailRepository, + $this->context, + $this->orderRepository, + $this->productRepository, + $this->currencyRepository + ); + + $result = $orderDetailPresenter->present($recurringOrder, $recurringProduct); + + $this->assertArrayNotHasKey('next_payment_date', $result); + $this->assertArrayHasKey('cancelled_date', $result); + } + + public function testItUnsuccessfullyPresentsOrderDetailMissingOrder(): void + { + /** @var \MolRecurringOrder $recurringOrder */ + $recurringOrder = $this->createMock(\MolRecurringOrder::class); + $recurringOrder->total_tax_incl = 1.11; + $recurringOrder->status = SubscriptionStatus::STATUS_CANCELED; + + /** @var \MolRecurringOrdersProduct $recurringProduct */ + $recurringProduct = $this->createMock(\MolRecurringOrdersProduct::class); + $recurringProduct->id_product = 1; + $recurringProduct->id_product_attribute = 1; + + $this->orderRepository->expects($this->once())->method('findOneBy')->willReturn(null); + + $orderDetailPresenter = new OrderDetailPresenter( + $this->orderDetailRepository, + $this->context, + $this->orderRepository, + $this->productRepository, + $this->currencyRepository + ); + + $this->expectException(CouldNotPresentOrderDetail::class); + $this->expectExceptionCode(ExceptionCode::ORDER_FAILED_TO_FIND_ORDER); + + $orderDetailPresenter->present($recurringOrder, $recurringProduct); + } + + public function testItUnsuccessfullyPresentsOrderDetailMissingOrderDetail(): void + { + /** @var \Order $order */ + $order = $this->createMock(\Order::class); + $order->id_lang = 1; + + /** @var \MolRecurringOrder $recurringOrder */ + $recurringOrder = $this->createMock(\MolRecurringOrder::class); + $recurringOrder->total_tax_incl = 1.11; + $recurringOrder->status = SubscriptionStatus::STATUS_CANCELED; + + /** @var \MolRecurringOrdersProduct $recurringProduct */ + $recurringProduct = $this->createMock(\MolRecurringOrdersProduct::class); + $recurringProduct->id_product = 1; + $recurringProduct->id_product_attribute = 1; + + $this->orderRepository->expects($this->once())->method('findOneBy')->willReturn($order); + $this->orderDetailRepository->expects($this->once())->method('findOneBy')->willReturn(null); + + $orderDetailPresenter = new OrderDetailPresenter( + $this->orderDetailRepository, + $this->context, + $this->orderRepository, + $this->productRepository, + $this->currencyRepository + ); + + $this->expectException(CouldNotPresentOrderDetail::class); + $this->expectExceptionCode(ExceptionCode::ORDER_FAILED_TO_FIND_ORDER_DETAIL); + + $orderDetailPresenter->present($recurringOrder, $recurringProduct); + } + + public function testItUnsuccessfullyPresentsOrderDetailMissingProduct(): void + { + /** @var \Order $order */ + $order = $this->createMock(\Order::class); + $order->id_lang = 1; + + /** @var \OrderDetail $orderDetail */ + $orderDetail = $this->createMock(\OrderDetail::class); + $orderDetail->unit_price_tax_incl = 1.11; + + /** @var \MolRecurringOrder $recurringOrder */ + $recurringOrder = $this->createMock(\MolRecurringOrder::class); + $recurringOrder->total_tax_incl = 1.11; + $recurringOrder->status = SubscriptionStatus::STATUS_CANCELED; + + /** @var \MolRecurringOrdersProduct $recurringProduct */ + $recurringProduct = $this->createMock(\MolRecurringOrdersProduct::class); + $recurringProduct->id_product = 1; + $recurringProduct->id_product_attribute = 1; + + $this->orderRepository->expects($this->once())->method('findOneBy')->willReturn($order); + $this->orderDetailRepository->expects($this->once())->method('findOneBy')->willReturn($orderDetail); + $this->productRepository->expects($this->once())->method('findOneBy')->willReturn(null); + + $orderDetailPresenter = new OrderDetailPresenter( + $this->orderDetailRepository, + $this->context, + $this->orderRepository, + $this->productRepository, + $this->currencyRepository + ); + + $this->expectException(CouldNotPresentOrderDetail::class); + $this->expectExceptionCode(ExceptionCode::ORDER_FAILED_TO_FIND_PRODUCT); + + $orderDetailPresenter->present($recurringOrder, $recurringProduct); + } + + public function testItUnsuccessfullyPresentsOrderDetailMissingCurrency(): void + { + /** @var \Order $order */ + $order = $this->createMock(\Order::class); + $order->id_lang = 1; + + /** @var \OrderDetail $orderDetail */ + $orderDetail = $this->createMock(\OrderDetail::class); + $orderDetail->unit_price_tax_incl = 1.11; + + /** @var \Product $product */ + $product = $this->createMock(\Product::class); + + /** @var \MolRecurringOrder $recurringOrder */ + $recurringOrder = $this->createMock(\MolRecurringOrder::class); + $recurringOrder->total_tax_incl = 1.11; + $recurringOrder->status = SubscriptionStatus::STATUS_CANCELED; + + /** @var \MolRecurringOrdersProduct $recurringProduct */ + $recurringProduct = $this->createMock(\MolRecurringOrdersProduct::class); + $recurringProduct->id_product = 1; + $recurringProduct->id_product_attribute = 1; + + $this->orderRepository->expects($this->once())->method('findOneBy')->willReturn($order); + $this->orderDetailRepository->expects($this->once())->method('findOneBy')->willReturn($orderDetail); + $this->productRepository->expects($this->once())->method('findOneBy')->willReturn($product); + $this->currencyRepository->expects($this->once())->method('findOneBy')->willReturn(null); + + $orderDetailPresenter = new OrderDetailPresenter( + $this->orderDetailRepository, + $this->context, + $this->orderRepository, + $this->productRepository, + $this->currencyRepository + ); + + $this->expectException(CouldNotPresentOrderDetail::class); + $this->expectExceptionCode(ExceptionCode::ORDER_FAILED_TO_FIND_CURRENCY); + + $orderDetailPresenter->present($recurringOrder, $recurringProduct); + } +} diff --git a/views/css/front/subscription/customer_order_detail.css b/views/css/front/subscription/customer_order_detail.css index 594d30507..dbcfc504e 100644 --- a/views/css/front/subscription/customer_order_detail.css +++ b/views/css/front/subscription/customer_order_detail.css @@ -8,3 +8,10 @@ .addresses { margin: 0 -.9375rem } + +@media only screen and (max-width: 991px) { + .recurring-method-form .product-info .product-img { + text-align: center; + margin-bottom: 20px; + } +} diff --git a/views/templates/front/subscription/customerRecurringOrderDetail.tpl b/views/templates/front/subscription/customerRecurringOrderDetail.tpl index dc9dffec8..64a6745c9 100644 --- a/views/templates/front/subscription/customerRecurringOrderDetail.tpl +++ b/views/templates/front/subscription/customerRecurringOrderDetail.tpl @@ -67,9 +67,8 @@ {/block} - {block name='order_detail'} - {include file='customer/_partials/order-detail-no-return.tpl' order=$recurringOrderData.order} - {/block} + {include file='module:mollie/views/templates/front/subscription/customerRecurringOrderDetailProduct.tpl' order=$recurringOrderData.order_detail} + {if $recurringOrderData.recurring_order->status !== 'canceled'} {block name='recurring_method'} diff --git a/views/templates/front/subscription/customerRecurringOrderDetailProduct.tpl b/views/templates/front/subscription/customerRecurringOrderDetailProduct.tpl new file mode 100644 index 000000000..167253d1b --- /dev/null +++ b/views/templates/front/subscription/customerRecurringOrderDetailProduct.tpl @@ -0,0 +1,31 @@ +
+
+
+
+
+ +
+
+

{l s='Product:' mod='mollie'} {$order.name}

+

{$order.quantity}

+

{l s='Unit price:' mod='mollie'} {$order.unit_price}

+
+
+
+
+

{l s='Total:' mod='mollie'} {$order.total}

+

{l s='Subscription status:' mod='mollie'} {$order.status}

+

{l s='Subscription start date:' mod='mollie'} {$order.start_date}

+ + {if isset($order.next_payment_date)} +

{l s='Next payment date:' mod='mollie'} {$order.next_payment_date}

+ {/if} + + {if isset($order.cancelled_date)} +

{l s='Cancelled date:' mod='mollie'} {$order.cancelled_date}

+ {/if} +
+
+