diff --git a/composer.json b/composer.json index bd3185024..de66fd50b 100644 --- a/composer.json +++ b/composer.json @@ -39,7 +39,8 @@ "friends-of-behat/variadic-extension": "^1.1", "lakion/mink-debug-extension": "^1.2.3", "phpspec/phpspec": "^4.0", - "phpstan/phpstan-shim": "^0.9.2", + "phpstan/phpstan-shim": "^0.10", + "phpstan/phpstan-webmozart-assert": "^0.10.0", "phpunit/phpunit": "^6.5", "sylius-labs/coding-standard": "^2.0", "symfony/browser-kit": "^3.4|^4.1", @@ -62,5 +63,8 @@ "vendor/bin/phpstan.phar analyse -c phpstan.neon -l max src/", "vendor/bin/ecs check src/ spec/" ] + }, + "config": { + "sort-packages": true } } diff --git a/features/refunding_single_order_unit.feature b/features/refunding_single_order_unit.feature index 9cd1f8401..a87c5cb1c 100644 --- a/features/refunding_single_order_unit.feature +++ b/features/refunding_single_order_unit.feature @@ -57,13 +57,15 @@ Feature: Refunding a single order unit Then I should not be able to see refunds button @ui - Scenario: Being able to choose refund payment method + Scenario: Being able to choose only offline payment methods Given the order "#00000022" is already paid And the store allows paying with "Another offline payment method" + And the store has a payment method "ElonPay" with a code "IN_THRUST_WE_TRUST" and Paypal Express Checkout gateway When I want to refund some units of order "#00000022" Then I should be able to choose refund payment method And there should be "Space money" payment method And there should be "Another offline payment method" payment method + And there should not be "ElonPay" payment method @application Scenario: Not being able to refund unit from an order that is unpaid diff --git a/phpstan.neon b/phpstan.neon index 98566716e..5fb202c1d 100644 --- a/phpstan.neon +++ b/phpstan.neon @@ -1,3 +1,6 @@ +includes: + - vendor/phpstan/phpstan-webmozart-assert/extension.neon + parameters: excludes_analyse: # Makes PHPStan crash diff --git a/spec/Provider/OfflineRefundPaymentMethodsProviderSpec.php b/spec/Provider/OfflineRefundPaymentMethodsProviderSpec.php new file mode 100644 index 000000000..30ba4cfd6 --- /dev/null +++ b/spec/Provider/OfflineRefundPaymentMethodsProviderSpec.php @@ -0,0 +1,53 @@ +beConstructedWith($paymentMethodRepository); + } + + function it_implements_refund_payment_methods_provider_interface(): void + { + $this->shouldImplement(RefundPaymentMethodsProviderInterface::class); + } + + function it_provides_only_offline_payment_methods( + PaymentMethodRepositoryInterface $paymentMethodRepository, + ChannelInterface $channel, + PaymentMethodInterface $offlinePaymentMethod, + PaymentMethodInterface $payPalPaymentMethod, + PaymentMethodInterface $stripePaymentMethod, + GatewayConfigInterface $offlineGatewayConfig, + GatewayConfigInterface $payPalGatewayConfig, + GatewayConfigInterface $stripeGatewayConfig + ): void { + $paymentMethodRepository->findEnabledForChannel($channel)->willReturn([ + $offlinePaymentMethod, + $payPalPaymentMethod, + $stripePaymentMethod, + ]); + + $offlinePaymentMethod->getGatewayConfig()->willReturn($offlineGatewayConfig); + $offlineGatewayConfig->getFactoryName()->willReturn('offline'); + + $payPalPaymentMethod->getGatewayConfig()->willReturn($payPalGatewayConfig); + $payPalGatewayConfig->getFactoryName()->willReturn('paypal'); + + $stripePaymentMethod->getGatewayConfig()->willReturn($stripeGatewayConfig); + $stripeGatewayConfig->getFactoryName()->willReturn('stripe'); + + $this->findForChannel($channel)->shouldReturn([$offlinePaymentMethod]); + } +} diff --git a/src/Action/Admin/OrderRefundsListAction.php b/src/Action/Admin/OrderRefundsListAction.php index 1742923c3..89784061a 100644 --- a/src/Action/Admin/OrderRefundsListAction.php +++ b/src/Action/Admin/OrderRefundsListAction.php @@ -6,8 +6,8 @@ use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Repository\OrderRepositoryInterface; -use Sylius\Component\Core\Repository\PaymentMethodRepositoryInterface; use Sylius\RefundPlugin\Checker\OrderRefundingAvailabilityCheckerInterface; +use Sylius\RefundPlugin\Provider\RefundPaymentMethodsProviderInterface; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -23,8 +23,8 @@ final class OrderRefundsListAction /** @var OrderRefundingAvailabilityCheckerInterface */ private $orderRefundingAvailabilityChecker; - /** @var PaymentMethodRepositoryInterface */ - private $paymentMethodRepository; + /** @var RefundPaymentMethodsProviderInterface */ + private $refundPaymentMethodsProvider; /** @var Environment */ private $twig; @@ -38,14 +38,14 @@ final class OrderRefundsListAction public function __construct( OrderRepositoryInterface $orderRepository, OrderRefundingAvailabilityCheckerInterface $orderRefundingAvailabilityChecker, - PaymentMethodRepositoryInterface $paymentMethodRepository, + RefundPaymentMethodsProviderInterface $refundPaymentMethodsProvider, Environment $twig, Session $session, UrlGeneratorInterface $router ) { $this->orderRepository = $orderRepository; $this->orderRefundingAvailabilityChecker = $orderRefundingAvailabilityChecker; - $this->paymentMethodRepository = $paymentMethodRepository; + $this->refundPaymentMethodsProvider = $refundPaymentMethodsProvider; $this->twig = $twig; $this->session = $session; $this->router = $router; @@ -60,12 +60,10 @@ public function __invoke(Request $request): Response return $this->redirectToReferer($order); } - $paymentMethods = $this->paymentMethodRepository->findEnabledForChannel($order->getChannel()); - return new Response( $this->twig->render('@SyliusRefundPlugin/orderRefunds.html.twig', [ 'order' => $order, - 'payment_methods' => $paymentMethods, + 'payment_methods' => $this->refundPaymentMethodsProvider->findForChannel($order->getChannel()), ]) ); } diff --git a/src/Action/Admin/RefundUnitsAction.php b/src/Action/Admin/RefundUnitsAction.php index 5aa763dd1..a8af48579 100644 --- a/src/Action/Admin/RefundUnitsAction.php +++ b/src/Action/Admin/RefundUnitsAction.php @@ -12,6 +12,7 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Webmozart\Assert\Assert; final class RefundUnitsAction { @@ -46,6 +47,7 @@ public function __invoke(Request $request): Response $this->session->getFlashBag()->add('success', 'sylius_refund.units_successfully_refunded'); } catch (CommandDispatchException $exception) { + Assert::notNull($exception->getPrevious()); $this->session->getFlashBag()->add('error', $exception->getPrevious()->getMessage()); } catch (\InvalidArgumentException $exception) { $this->session->getFlashBag()->add('error', $exception->getMessage()); diff --git a/src/Entity/CreditMemoUnit.php b/src/Entity/CreditMemoUnit.php index c16108768..1d297a33f 100644 --- a/src/Entity/CreditMemoUnit.php +++ b/src/Entity/CreditMemoUnit.php @@ -40,11 +40,17 @@ public function getTaxesTotal(): int public function serialize(): string { - return json_encode([ + $serialized = json_encode([ 'product_name' => $this->productName, 'total' => $this->total, 'taxes_total' => $this->taxesTotal, ]); + + if ($serialized === false) { + throw new \Exception('Credit memo unit could have not been serialized'); + } + + return $serialized; } public static function unserialize(string $serialized): self diff --git a/src/Provider/OfflineRefundPaymentMethodsProvider.php b/src/Provider/OfflineRefundPaymentMethodsProvider.php new file mode 100644 index 000000000..1dcbc158f --- /dev/null +++ b/src/Provider/OfflineRefundPaymentMethodsProvider.php @@ -0,0 +1,33 @@ +paymentMethodRepository = $paymentMethodRepository; + } + + public function findForChannel(ChannelInterface $channel): array + { + return array_filter( + $this->paymentMethodRepository->findEnabledForChannel($channel), + function (PaymentMethodInterface $paymentMethod): bool { + Assert::notNull($paymentMethod->getGatewayConfig()); + + return $paymentMethod->getGatewayConfig()->getFactoryName() === 'offline'; + } + ); + } +} diff --git a/src/Provider/RefundPaymentMethodsProviderInterface.php b/src/Provider/RefundPaymentMethodsProviderInterface.php new file mode 100644 index 000000000..f0f274112 --- /dev/null +++ b/src/Provider/RefundPaymentMethodsProviderInterface.php @@ -0,0 +1,14 @@ + - + diff --git a/src/Resources/config/services/provider.xml b/src/Resources/config/services/provider.xml index 9add5e643..7f8353335 100644 --- a/src/Resources/config/services/provider.xml +++ b/src/Resources/config/services/provider.xml @@ -31,5 +31,9 @@ + + + + diff --git a/tests/Behat/Context/Ui/RefundingContext.php b/tests/Behat/Context/Ui/RefundingContext.php index da64caab8..07547ad4e 100644 --- a/tests/Behat/Context/Ui/RefundingContext.php +++ b/tests/Behat/Context/Ui/RefundingContext.php @@ -303,6 +303,14 @@ public function thereShouldBePaymentMethod(string $payment): void Assert::true($this->orderRefundsPage->isPaymentMethodVisible($payment)); } + /** + * @Then there should not be :payment payment method + */ + public function thereShouldNotBePaymentMethod(string $payment): void + { + Assert::false($this->orderRefundsPage->isPaymentMethodVisible($payment)); + } + private function provideLongComment(): string { return 'Tu ne quaesieris scire nefas, quem mihi quem tibi finem di dederint, Leuconoe, nec Babylonios temptaris numeros. Ut melius quidquid erit pati. Seu plures hiemes sue tribuit Iuppiter ultimam. Qae nunc oppositis debilitat pumicibus mare Tyrrenum: sapias vina liques et spatio brevi. Spem longam resecens. Dum loquimur fugerit invida Aetas: CARPE DIEM, quam minimum credula postero.';