Skip to content

Commit

Permalink
Adding an assertion that the payment method needs to be available.
Browse files Browse the repository at this point in the history
  • Loading branch information
mamazu authored and lchrusciel committed Jun 30, 2021
1 parent ce3073f commit c33e3f8
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 14 deletions.
41 changes: 37 additions & 4 deletions spec/Handler/Cart/ChoosePaymentMethodHandlerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,26 +15,29 @@
use Sylius\Component\Core\OrderCheckoutTransitions;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Core\Repository\PaymentMethodRepositoryInterface;
use Sylius\Component\Payment\Resolver\PaymentMethodsResolverInterface;
use Sylius\ShopApiPlugin\Command\Cart\ChoosePaymentMethod;

final class ChoosePaymentMethodHandlerSpec extends ObjectBehavior
{
function let(
OrderRepositoryInterface $orderRepository,
PaymentMethodRepositoryInterface $paymentMethodRepository,
FactoryInterface $stateMachineFactory
FactoryInterface $stateMachineFactory,
PaymentMethodsResolverInterface $paymentMethodsResolver
): void {
$this->beConstructedWith($orderRepository, $paymentMethodRepository, $stateMachineFactory);
$this->beConstructedWith($orderRepository, $paymentMethodRepository, $stateMachineFactory, $paymentMethodsResolver);
}

function it_assignes_choosen_payment_method_to_specified_payment(
function it_assigns_chosen_payment_method_to_specified_payment(
OrderRepositoryInterface $orderRepository,
OrderInterface $order,
PaymentMethodRepositoryInterface $paymentMethodRepository,
PaymentMethodInterface $paymentMethod,
PaymentInterface $payment,
FactoryInterface $stateMachineFactory,
StateMachineInterface $stateMachine
StateMachineInterface $stateMachine,
PaymentMethodsResolverInterface $paymentMethodsResolver
): void {
$orderRepository->findOneBy(['tokenValue' => 'ORDERTOKEN'])->willReturn($order);
$order->getPayments()->willReturn(new ArrayCollection([$payment->getWrappedObject()]));
Expand All @@ -43,6 +46,8 @@ function it_assignes_choosen_payment_method_to_specified_payment(
$stateMachineFactory->get($order, OrderCheckoutTransitions::GRAPH)->willReturn($stateMachine);
$stateMachine->can('select_payment')->willReturn(true);

$paymentMethodsResolver->getSupportedMethods($payment)->willReturn([$paymentMethod]);

$payment->setMethod($paymentMethod)->shouldBeCalled();
$stateMachine->apply('select_payment')->shouldBeCalled();

Expand Down Expand Up @@ -98,6 +103,7 @@ function it_throws_an_exception_if_payment_method_with_given_code_has_not_been_f
StateMachineInterface $stateMachine
): void {
$orderRepository->findOneBy(['tokenValue' => 'ORDERTOKEN'])->willReturn($order);
$order->getPayments()->willReturn(new ArrayCollection([]));
$paymentMethodRepository->findOneBy(['code' => 'CASH_ON_DELIVERY_METHOD'])->willReturn(null);
$stateMachineFactory->get($order, OrderCheckoutTransitions::GRAPH)->willReturn($stateMachine);
$stateMachine->can('select_payment')->willReturn(true);
Expand Down Expand Up @@ -138,4 +144,31 @@ function it_throws_an_exception_if_ordered_payment_has_not_been_found(
])
;
}

function it_throws_an_exception_if_the_payment_method_is_not_available(
OrderRepositoryInterface $orderRepository,
OrderInterface $order,
PaymentMethodRepositoryInterface $paymentMethodRepository,
PaymentMethodInterface $paymentMethod,
PaymentMethodInterface $availableMethod,
PaymentInterface $payment,
FactoryInterface $stateMachineFactory,
StateMachineInterface $stateMachine,
PaymentMethodsResolverInterface $paymentMethodsResolver
): void {
$orderRepository->findOneBy(['tokenValue' => 'ORDERTOKEN'])->willReturn($order);
$order->getPayments()->willReturn(new ArrayCollection([$payment->getWrappedObject()]));
$paymentMethodRepository->findOneBy(['code' => 'CASH_ON_DELIVERY_METHOD'])->willReturn($paymentMethod);

$stateMachineFactory->get($order, OrderCheckoutTransitions::GRAPH)->willReturn($stateMachine);
$stateMachine->can('select_payment')->willReturn(true);

$paymentMethodsResolver->getSupportedMethods($payment)->willReturn([$availableMethod]);

$payment->setMethod($paymentMethod)->shouldNotBeCalled();
$stateMachine->apply('select_payment')->shouldNotBeCalled();

$this->shouldThrow(\InvalidArgumentException::class)
->during('__invoke', [new ChoosePaymentMethod('ORDERTOKEN', 0, 'CASH_ON_DELIVERY_METHOD')]);
}
}
38 changes: 28 additions & 10 deletions src/Handler/Cart/ChoosePaymentMethodHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@

use SM\Factory\FactoryInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\PaymentInterface;
use Sylius\Component\Core\Model\PaymentMethodInterface;
use Sylius\Component\Core\OrderCheckoutTransitions;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Core\Repository\PaymentMethodRepositoryInterface;
use Sylius\Component\Payment\Resolver\PaymentMethodsResolverInterface;
use Sylius\ShopApiPlugin\Command\Cart\ChoosePaymentMethod;
use Webmozart\Assert\Assert;

Expand All @@ -24,36 +26,52 @@ final class ChoosePaymentMethodHandler
/** @var FactoryInterface */
private $stateMachineFactory;

/** @var PaymentMethodsResolverInterface */
private $paymentMethodsResolver;

public function __construct(
OrderRepositoryInterface $orderRepository,
PaymentMethodRepositoryInterface $paymentMethodRepository,
FactoryInterface $stateMachineFactory
FactoryInterface $stateMachineFactory,
PaymentMethodsResolverInterface $paymentMethodsResolver
) {
$this->orderRepository = $orderRepository;
$this->paymentMethodRepository = $paymentMethodRepository;
$this->stateMachineFactory = $stateMachineFactory;
$this->paymentMethodsResolver = $paymentMethodsResolver;
}

public function __invoke(ChoosePaymentMethod $choosePaymentMethod): void
{
/** @var OrderInterface $cart */
$cart = $this->orderRepository->findOneBy(['tokenValue' => $choosePaymentMethod->orderToken()]);

Assert::notNull($cart, 'Cart has not been found.');

$stateMachine = $this->stateMachineFactory->get($cart, OrderCheckoutTransitions::GRAPH);

Assert::true($stateMachine->can(OrderCheckoutTransitions::TRANSITION_SELECT_PAYMENT), 'Order cannot have payment method assigned.');

/** @var PaymentMethodInterface $paymentMethod */
$paymentMethod = $this->paymentMethodRepository->findOneBy(['code' => $choosePaymentMethod->paymentMethod()]);

Assert::notNull($paymentMethod, 'Payment method has not been found');
Assert::true(isset($cart->getPayments()[$choosePaymentMethod->paymentIdentifier()]), 'Can not find payment with given identifier.');

$payment = $cart->getPayments()[$choosePaymentMethod->paymentIdentifier()];
$payment = $this->getPayment($cart, $choosePaymentMethod->paymentIdentifier());
$paymentMethod = $this->getPaymentMethod($choosePaymentMethod->paymentMethod());
Assert::inArray($paymentMethod, $this->paymentMethodsResolver->getSupportedMethods($payment), 'Payment does not support the selected payment method');

$payment->setMethod($paymentMethod);
$stateMachine->apply(OrderCheckoutTransitions::TRANSITION_SELECT_PAYMENT);
}

private function getPayment(OrderInterface $cart, $identifier): PaymentInterface
{
$allPayments = $cart->getPayments();
Assert::true(isset($allPayments[$identifier]), 'Can not find payment with given identifier.');

return $allPayments[$identifier];
}

private function getPaymentMethod(string $paymentMethodCode): PaymentMethodInterface
{
/** @var PaymentMethodInterface|null $paymentMethod */
$paymentMethod = $this->paymentMethodRepository->findOneBy(['code' => $paymentMethodCode]);
Assert::notNull($paymentMethod, 'Payment method has not been found');

return $paymentMethod;
}
}
1 change: 1 addition & 0 deletions src/Resources/config/services/handler/cart.xml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<argument type="service" id="sylius.repository.order"/>
<argument type="service" id="sylius.repository.payment_method"/>
<argument type="service" id="sm.factory"/>
<argument type="service" id="sylius.payment_methods_resolver" />
<tag name="messenger.message_handler" bus="sylius_shop_api_plugin.command_bus"/>
</service>

Expand Down

0 comments on commit c33e3f8

Please sign in to comment.