Skip to content

Commit

Permalink
refactor #481 [Checkout] Extract cart assignment from order complete …
Browse files Browse the repository at this point in the history
…(lchrusciel)

This PR was merged into the 1.0-dev branch.

Discussion
----------



Commits
-------

696eb7a [Checkout] Extract cart assignment from order complete
  • Loading branch information
lchrusciel authored Jul 24, 2019
2 parents 2290f35 + 696eb7a commit f24489a
Show file tree
Hide file tree
Showing 13 changed files with 175 additions and 56 deletions.
25 changes: 25 additions & 0 deletions spec/Command/Cart/AssignCustomerToCartSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace spec\Sylius\ShopApiPlugin\Command\Cart;

use PhpSpec\ObjectBehavior;

final class AssignCustomerToCartSpec extends ObjectBehavior
{
function let(): void
{
$this->beConstructedWith('ORDERTOKEN', 'example@customer.com');
}

function it_has_order_token(): void
{
$this->orderToken()->shouldReturn('ORDERTOKEN');
}

function it_has_email(): void
{
$this->email()->shouldReturn('example@customer.com');
}
}
9 changes: 2 additions & 7 deletions spec/Command/Cart/CompleteOrderSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,22 +10,17 @@ final class CompleteOrderSpec extends ObjectBehavior
{
function let(): void
{
$this->beConstructedWith('ORDERTOKEN', 'example@customer.com');
$this->beConstructedWith('ORDERTOKEN');
}

function it_has_order_token(): void
{
$this->orderToken()->shouldReturn('ORDERTOKEN');
}

function it_has_email(): void
{
$this->email()->shouldReturn('example@customer.com');
}

function it_can_have_a_note(): void
{
$this->beConstructedWith('ORDERTOKEN', 'example@customer.com', 'Some order notes');
$this->beConstructedWith('ORDERTOKEN', 'Some order notes');

$this->notes()->shouldReturn('Some order notes');
}
Expand Down
46 changes: 46 additions & 0 deletions spec/Handler/Cart/AssignCustomerToCartHandlerSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
<?php

declare(strict_types=1);

namespace spec\Sylius\ShopApiPlugin\Handler\Cart;

use PhpSpec\ObjectBehavior;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\ShopApiPlugin\Command\Cart\AssignCustomerToCart;
use Sylius\ShopApiPlugin\Provider\CustomerProviderInterface;

final class AssignCustomerToCartHandlerSpec extends ObjectBehavior
{
function let(OrderRepositoryInterface $orderRepository, CustomerProviderInterface $customerProvider): void
{
$this->beConstructedWith($orderRepository, $customerProvider);
}

function it_handles_assigning_customer_to_cart(
CustomerInterface $customer,
CustomerProviderInterface $customerProvider,
OrderInterface $order,
OrderRepositoryInterface $orderRepository
): void {
$orderRepository->findOneBy(['tokenValue' => 'ORDERTOKEN'])->willReturn($order);

$customerProvider->provide('example@customer.com')->willReturn($customer);

$order->setCustomer($customer)->shouldBeCalled();

$this(new AssignCustomerToCart('ORDERTOKEN', 'example@customer.com'));
}

function it_throws_an_exception_if_order_does_not_exist(
OrderRepositoryInterface $orderRepository
): void {
$orderRepository->findOneBy(['tokenValue' => 'ORDERTOKEN'])->willReturn(null);

$this
->shouldThrow(\InvalidArgumentException::class)
->during('__invoke', [new AssignCustomerToCart('ORDERTOKEN', 'example@customer.com')])
;
}
}
29 changes: 7 additions & 22 deletions spec/Handler/Cart/CompleteOrderHandlerSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,65 +7,50 @@
use PhpSpec\ObjectBehavior;
use SM\Factory\FactoryInterface as StateMachineFactoryInterface;
use SM\StateMachine\StateMachineInterface;
use Sylius\Component\Core\Model\CustomerInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\OrderCheckoutTransitions;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\ShopApiPlugin\Command\Cart\CompleteOrder;
use Sylius\ShopApiPlugin\Provider\CustomerProviderInterface;

final class CompleteOrderHandlerSpec extends ObjectBehavior
{
function let(
OrderRepositoryInterface $orderRepository,
CustomerProviderInterface $customerProvider,
StateMachineFactoryInterface $stateMachineFactory
): void {
$this->beConstructedWith($orderRepository, $customerProvider, $stateMachineFactory);
function let(OrderRepositoryInterface $orderRepository, StateMachineFactoryInterface $stateMachineFactory): void
{
$this->beConstructedWith($orderRepository, $stateMachineFactory);
}

function it_handles_order_completion(
CustomerInterface $customer,
CustomerProviderInterface $customerProvider,
OrderInterface $order,
OrderRepositoryInterface $orderRepository,
StateMachineFactoryInterface $stateMachineFactory,
StateMachineInterface $stateMachine
): void {
$orderRepository->findOneBy(['tokenValue' => 'ORDERTOKEN'])->willReturn($order);

$customerProvider->provide('example@customer.com')->willReturn($customer);

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

$order->setNotes(null)->shouldBeCalled();
$order->setCustomer($customer)->shouldBeCalled();
$stateMachine->apply('complete')->shouldBeCalled();

$this(new CompleteOrder('ORDERTOKEN', 'example@customer.com'));
$this(new CompleteOrder('ORDERTOKEN'));
}

function it_handles_order_completion_with_notes(
CustomerInterface $customer,
CustomerProviderInterface $customerProvider,
OrderInterface $order,
OrderRepositoryInterface $orderRepository,
StateMachineFactoryInterface $stateMachineFactory,
StateMachineInterface $stateMachine
): void {
$orderRepository->findOneBy(['tokenValue' => 'ORDERTOKEN'])->willReturn($order);

$customerProvider->provide('example@customer.com')->willReturn($customer);

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

$order->setNotes('Some notes')->shouldBeCalled();
$order->setCustomer($customer)->shouldBeCalled();
$stateMachine->apply('complete')->shouldBeCalled();

$this(new CompleteOrder('ORDERTOKEN', 'example@customer.com', 'Some notes'));
$this(new CompleteOrder('ORDERTOKEN', 'Some notes'));
}

function it_throws_an_exception_if_order_does_not_exist(
Expand All @@ -75,7 +60,7 @@ function it_throws_an_exception_if_order_does_not_exist(

$this
->shouldThrow(\InvalidArgumentException::class)
->during('__invoke', [new CompleteOrder('ORDERTOKEN', 'example@customer.com')])
->during('__invoke', [new CompleteOrder('ORDERTOKEN')])
;
}

Expand All @@ -92,7 +77,7 @@ function it_throws_an_exception_if_order_cannot_be_completed(

$this
->shouldThrow(\InvalidArgumentException::class)
->during('__invoke', [new CompleteOrder('ORDERTOKEN', 'example@customer.com')])
->during('__invoke', [new CompleteOrder('ORDERTOKEN')])
;
}
}
30 changes: 30 additions & 0 deletions src/Command/Cart/AssignCustomerToCart.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Sylius\ShopApiPlugin\Command\Cart;

class AssignCustomerToCart
{
/** @var string */
protected $orderToken;

/** @var string */
protected $email;

public function __construct(string $orderToken, string $email)
{
$this->orderToken = $orderToken;
$this->email = $email;
}

public function orderToken(): string
{
return $this->orderToken;
}

public function email(): string
{
return $this->email;
}
}
11 changes: 1 addition & 10 deletions src/Command/Cart/CompleteOrder.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,12 @@ class CompleteOrder
/** @var string */
protected $orderToken;

/** @var string */
protected $email;

/** @var string|null */
protected $notes;

public function __construct(string $orderToken, string $email, ?string $notes = null)
public function __construct(string $orderToken, ?string $notes = null)
{
$this->orderToken = $orderToken;
$this->email = $email;
$this->notes = $notes;
}

Expand All @@ -27,11 +23,6 @@ public function orderToken(): string
return $this->orderToken;
}

public function email(): string
{
return $this->email;
}

public function notes(): ?string
{
return $this->notes;
Expand Down
9 changes: 8 additions & 1 deletion src/Controller/Checkout/CompleteOrderAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use FOS\RestBundle\View\View;
use FOS\RestBundle\View\ViewHandlerInterface;
use Sylius\ShopApiPlugin\Command\Cart\AssignCustomerToCart;
use Sylius\ShopApiPlugin\Command\Cart\CompleteOrder;
use Sylius\ShopApiPlugin\Exception\WrongUserException;
use Sylius\ShopApiPlugin\Provider\LoggedInShopUserProviderInterface;
Expand Down Expand Up @@ -42,10 +43,16 @@ public function __invoke(Request $request): Response
}

try {
$this->bus->dispatch(
new AssignCustomerToCart(
$request->attributes->get('token'),
$request->request->get('email', $defaultEmail ?? null)
)
);

$this->bus->dispatch(
new CompleteOrder(
$request->attributes->get('token'),
$request->request->get('email', $defaultEmail ?? null),
$request->request->get('notes')
)
);
Expand Down
38 changes: 38 additions & 0 deletions src/Handler/Cart/AssignCustomerToCartHandler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

declare(strict_types=1);

namespace Sylius\ShopApiPlugin\Handler\Cart;

use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\ShopApiPlugin\Command\Cart\AssignCustomerToCart;
use Sylius\ShopApiPlugin\Provider\CustomerProviderInterface;
use Webmozart\Assert\Assert;

final class AssignCustomerToCartHandler
{
/** @var OrderRepositoryInterface */
private $orderRepository;

/** @var CustomerProviderInterface */
private $customerProvider;

public function __construct(OrderRepositoryInterface $orderRepository, CustomerProviderInterface $customerProvider)
{
$this->orderRepository = $orderRepository;
$this->customerProvider = $customerProvider;
}

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

Assert::notNull($order, sprintf('Order with %s token has not been found.', $assignOrderToCustomer->orderToken()));

$customer = $this->customerProvider->provide($assignOrderToCustomer->email());

$order->setCustomer($customer);
}
}
14 changes: 2 additions & 12 deletions src/Handler/Cart/CompleteOrderHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,19 @@
use Sylius\Component\Core\OrderCheckoutTransitions;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\ShopApiPlugin\Command\Cart\CompleteOrder;
use Sylius\ShopApiPlugin\Provider\CustomerProviderInterface;
use Webmozart\Assert\Assert;

final class CompleteOrderHandler
{
/** @var OrderRepositoryInterface */
private $orderRepository;

/** @var CustomerProviderInterface */
private $customerProvider;

/** @var StateMachineFactory */
private $stateMachineFactory;

public function __construct(
OrderRepositoryInterface $orderRepository,
CustomerProviderInterface $customerProvider,
StateMachineFactory $stateMachineFactory
) {
public function __construct(OrderRepositoryInterface $orderRepository, StateMachineFactory $stateMachineFactory)
{
$this->orderRepository = $orderRepository;
$this->customerProvider = $customerProvider;
$this->stateMachineFactory = $stateMachineFactory;
}

Expand All @@ -44,9 +36,7 @@ public function __invoke(CompleteOrder $completeOrder): void

Assert::true($stateMachine->can(OrderCheckoutTransitions::TRANSITION_COMPLETE), sprintf('Order with %s token cannot be completed.', $completeOrder->orderToken()));

$customer = $this->customerProvider->provide($completeOrder->email());
$order->setNotes($completeOrder->notes());
$order->setCustomer($customer);

$stateMachine->apply(OrderCheckoutTransitions::TRANSITION_COMPLETE);
}
Expand Down
8 changes: 7 additions & 1 deletion src/Resources/config/services/handler/cart.xml
Original file line number Diff line number Diff line change
Expand Up @@ -98,10 +98,16 @@
<tag name="messenger.message_handler" />
</service>

<service id="sylius.shop_api_plugin.handler.assign_customer_to_cart_handler"
class="Sylius\ShopApiPlugin\Handler\Cart\AssignCustomerToCartHandler">
<argument type="service" id="sylius.repository.order"/>
<argument type="service" id="sylius.shop_api_plugin.provider.customer_provider" />
<tag name="messenger.message_handler" />
</service>

<service id="sylius.shop_api_plugin.handler.complete_order_handler"
class="Sylius\ShopApiPlugin\Handler\Cart\CompleteOrderHandler">
<argument type="service" id="sylius.repository.order"/>
<argument type="service" id="sylius.shop_api_plugin.provider.customer_provider" />
<argument type="service" id="sm.factory"/>
<tag name="messenger.message_handler" />
</service>
Expand Down
4 changes: 3 additions & 1 deletion tests/Controller/Cart/CartDropCartApiTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

use Sylius\Component\Core\Model\OrderInterface;
use Sylius\ShopApiPlugin\Command\Cart\AddressOrder;
use Sylius\ShopApiPlugin\Command\Cart\AssignCustomerToCart;
use Sylius\ShopApiPlugin\Command\Cart\ChoosePaymentMethod;
use Sylius\ShopApiPlugin\Command\Cart\ChooseShippingMethod;
use Sylius\ShopApiPlugin\Command\Cart\CompleteOrder;
Expand Down Expand Up @@ -68,6 +69,7 @@ public function it_returns_not_found_exception_if_order_is_in_different_state_th
/** @var MessageBusInterface $bus */
$bus = $this->get('sylius_shop_api_plugin.command_bus');
$bus->dispatch(new PickupCart($token, 'WEB_GB'));
$bus->dispatch(new AssignCustomerToCart($token, 'sylius@example.com'));
$bus->dispatch(new PutSimpleItemToCart($token, 'LOGAN_MUG_CODE', 5));
$bus->dispatch(new AddressOrder(
$token,
Expand Down Expand Up @@ -95,7 +97,7 @@ public function it_returns_not_found_exception_if_order_is_in_different_state_th
/** @var OrderInterface $order */
$order = $this->get('sylius.repository.order')->findOneBy(['tokenValue' => $token]);

$bus->dispatch(new CompleteOrder($token, 'sylius@example.com'));
$bus->dispatch(new CompleteOrder($token));

$this->client->request('DELETE', '/shop-api/carts/' . $order->getTokenValue(), [], [], self::CONTENT_TYPE_HEADER);
$response = $this->client->getResponse();
Expand Down
Loading

0 comments on commit f24489a

Please sign in to comment.