Replace productCode to orderItemId

This commit is contained in:
Tomanhez 2020-06-30 23:06:23 +02:00
parent 3b72f18134
commit 7f035b51bb
9 changed files with 97 additions and 91 deletions

View file

@ -20,6 +20,7 @@ use Sylius\Behat\Client\ResponseCheckerInterface;
use Sylius\Behat\Service\SharedStorageInterface; use Sylius\Behat\Service\SharedStorageInterface;
use Sylius\Behat\Service\SprintfResponseEscaper; use Sylius\Behat\Service\SprintfResponseEscaper;
use Sylius\Component\Core\Model\ProductInterface; use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Symfony\Component\HttpFoundation\Request as HttpRequest; use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Response;
use Webmozart\Assert\Assert; use Webmozart\Assert\Assert;
@ -83,7 +84,17 @@ final class CartContext implements Context
*/ */
public function iRemoveProductFromTheCart(ProductInterface $product, string $tokenValue): void public function iRemoveProductFromTheCart(ProductInterface $product, string $tokenValue): void
{ {
$this->removeProductFromCart($product, $tokenValue); $items = $this->responseChecker->getValue($this->cartsClient->show($tokenValue), 'items');
foreach ($items as $item) {
$pathElements = explode('/', $item['variant']['product']);
$productCode = $pathElements[array_key_last($pathElements)];
if ($product->getCode() === $productCode) {
$this->removeOrderItemFromCart((string) $item['id'], $tokenValue);
}
}
} }
/** /**
@ -205,11 +216,11 @@ final class CartContext implements Context
$this->cartsClient->executeCustomRequest($request); $this->cartsClient->executeCustomRequest($request);
} }
private function removeProductFromCart(ProductInterface $product, string $tokenValue): void private function removeOrderItemFromCart(string $orderItemId, string $tokenValue): void
{ {
$request = Request::customItemAction('orders', $tokenValue, HttpRequest::METHOD_PATCH, 'remove'); $request = Request::customItemAction('orders', $tokenValue, HttpRequest::METHOD_PATCH, 'remove');
$request->updateContent(['productCode' => $product->getCode()]); $request->updateContent(['orderItemId' => $orderItemId]);
$this->cartsClient->executeCustomRequest($request); $this->cartsClient->executeCustomRequest($request);
} }

View file

@ -22,16 +22,16 @@ final class RemoveItemFromCart
* @var string * @var string
* @psalm-immutable * @psalm-immutable
*/ */
public $productCode; public $orderItemId;
public function __construct(string $productCode) public function __construct(string $orderItemId)
{ {
$this->productCode = $productCode; $this->orderItemId = $orderItemId;
} }
public static function removeFromData(string $tokenValue, string $productCode): self public static function removeFromData(string $tokenValue, string $orderItemId): self
{ {
$command = new self($productCode); $command = new self($orderItemId);
$command->tokenValue = $tokenValue; $command->tokenValue = $tokenValue;

View file

@ -15,22 +15,17 @@ namespace Sylius\Bundle\ApiBundle\CommandHandler\Cart;
use Sylius\Bundle\ApiBundle\Command\Cart\RemoveItemFromCart; use Sylius\Bundle\ApiBundle\Command\Cart\RemoveItemFromCart;
use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface; use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Sylius\Component\Order\Modifier\OrderModifierInterface; use Sylius\Component\Order\Modifier\OrderModifierInterface;
use Sylius\Component\Order\Processor\OrderProcessorInterface; use Sylius\Component\Order\Processor\OrderProcessorInterface;
use Sylius\Component\Product\Resolver\ProductVariantResolverInterface; use Sylius\Component\Order\Repository\OrderItemRepositoryInterface;
use Symfony\Component\Messenger\Handler\MessageHandlerInterface; use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
use Webmozart\Assert\Assert; use Webmozart\Assert\Assert;
final class RemoveItemFromCartHandler implements MessageHandlerInterface final class RemoveItemFromCartHandler implements MessageHandlerInterface
{ {
/** @var OrderRepositoryInterface */ /** @var OrderItemRepositoryInterface */
private $orderRepository; private $orderItemRepository;
/** @var ProductRepositoryInterface */
private $productRepository;
/** @var OrderModifierInterface */ /** @var OrderModifierInterface */
private $orderModifier; private $orderModifier;
@ -38,43 +33,32 @@ final class RemoveItemFromCartHandler implements MessageHandlerInterface
/** @var OrderProcessorInterface */ /** @var OrderProcessorInterface */
private $orderProcessor; private $orderProcessor;
/** @var ProductVariantResolverInterface */
private $variantResolver;
public function __construct( public function __construct(
OrderRepositoryInterface $orderRepository, OrderItemRepositoryInterface $orderItemRepository,
ProductRepositoryInterface $productRepository,
OrderModifierInterface $orderModifier, OrderModifierInterface $orderModifier,
OrderProcessorInterface $orderProcessor, OrderProcessorInterface $orderProcessor
ProductVariantResolverInterface $variantResolver
) { ) {
$this->orderRepository = $orderRepository; $this->orderItemRepository = $orderItemRepository;
$this->productRepository = $productRepository;
$this->orderModifier = $orderModifier; $this->orderModifier = $orderModifier;
$this->orderProcessor = $orderProcessor; $this->orderProcessor = $orderProcessor;
$this->variantResolver = $variantResolver;
} }
public function __invoke(RemoveItemFromCart $removeItemFromCart): OrderInterface public function __invoke(RemoveItemFromCart $removeItemFromCart): OrderInterface
{ {
$product = $this->productRepository->findOneByCode($removeItemFromCart->productCode); /** @var OrderItemInterface|null $orderItem */
$orderItem = $this->orderItemRepository->findOneByIdAndCartTokenValue(
$removeItemFromCart->orderItemId,
$removeItemFromCart->tokenValue
);
Assert::notNull($product); Assert::notNull($orderItem);
/** @var OrderInterface|null $cart */ /** @var OrderInterface $cart */
$cart = $this->orderRepository->findOneBy([ $cart = $orderItem->getOrder();
'state' => OrderInterface::STATE_CART,
'tokenValue' => $removeItemFromCart->tokenValue,
]);
Assert::notNull($cart); Assert::same($cart->getTokenValue(), $removeItemFromCart->tokenValue);
$orderItemUnits = $cart->getItemUnitsByVariant($this->variantResolver->getVariant($product)); $this->orderModifier->removeFromOrder($cart, $orderItem);
/** @var OrderItemUnitInterface $orderItemUnit */
$orderItemUnit = $orderItemUnits->first();
$this->orderModifier->removeFromOrder($cart, $orderItemUnit->getOrderItem());
$this->orderProcessor->process($cart); $this->orderProcessor->process($cart);

View file

@ -16,7 +16,7 @@
xsi:schemaLocation="http://symfony.com/schema/dic/serializer-mapping https://symfony.com/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd" xsi:schemaLocation="http://symfony.com/schema/dic/serializer-mapping https://symfony.com/schema/dic/serializer-mapping/serializer-mapping-1.0.xsd"
> >
<class name="Sylius\Bundle\ApiBundle\Command\Cart\RemoveItemFromCart"> <class name="Sylius\Bundle\ApiBundle\Command\Cart\RemoveItemFromCart">
<attribute name="productCode"> <attribute name="orderItemId">
<group>cart:remove_item</group> <group>cart:remove_item</group>
</attribute> </attribute>
</class> </class>

View file

@ -43,11 +43,9 @@
</service> </service>
<service id="Sylius\Bundle\ApiBundle\CommandHandler\Cart\RemoveItemFromCartHandler"> <service id="Sylius\Bundle\ApiBundle\CommandHandler\Cart\RemoveItemFromCartHandler">
<argument type="service" id="sylius.repository.order" /> <argument type="service" id="sylius.repository.order_item"/>
<argument type="service" id="sylius.repository.product" />
<argument type="service" id="sylius.order_modifier" /> <argument type="service" id="sylius.order_modifier" />
<argument type="service" id="sylius.order_processing.order_processor" /> <argument type="service" id="sylius.order_processing.order_processor" />
<argument type="service" id="sylius.product_variant_resolver.default"/>
<tag name="messenger.message_handler" /> <tag name="messenger.message_handler" />
</service> </service>
</services> </services>

View file

@ -13,17 +13,11 @@ declare(strict_types=1);
namespace spec\Sylius\Bundle\ApiBundle\CommandHandler\Cart; namespace spec\Sylius\Bundle\ApiBundle\CommandHandler\Cart;
use Doctrine\Common\Collections\ArrayCollection;
use PhpSpec\ObjectBehavior; use PhpSpec\ObjectBehavior;
use Sylius\Bundle\ApiBundle\Command\Cart\RemoveItemFromCart; use Sylius\Bundle\ApiBundle\Command\Cart\RemoveItemFromCart;
use Sylius\Bundle\OrderBundle\Doctrine\ORM\OrderItemRepository;
use Sylius\Component\Core\Model\OrderInterface; use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\OrderItemInterface; use Sylius\Component\Core\Model\OrderItemInterface;
use Sylius\Component\Core\Model\OrderItemUnitInterface;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Sylius\Component\Core\Repository\OrderRepositoryInterface;
use Sylius\Component\Core\Repository\ProductRepositoryInterface;
use Sylius\Component\Order\Modifier\OrderItemQuantityModifierInterface;
use Sylius\Component\Order\Modifier\OrderModifierInterface; use Sylius\Component\Order\Modifier\OrderModifierInterface;
use Sylius\Component\Order\Processor\OrderProcessorInterface; use Sylius\Component\Order\Processor\OrderProcessorInterface;
use Sylius\Component\Product\Resolver\ProductVariantResolverInterface; use Sylius\Component\Product\Resolver\ProductVariantResolverInterface;
@ -32,15 +26,13 @@ use Symfony\Component\Messenger\Handler\MessageHandlerInterface;
final class RemoveItemFromCartHandlerSpec extends ObjectBehavior final class RemoveItemFromCartHandlerSpec extends ObjectBehavior
{ {
function let( function let(
OrderRepositoryInterface $orderRepository, OrderItemRepository $orderItemRepository,
ProductRepositoryInterface $productRepository,
OrderModifierInterface $orderModifier, OrderModifierInterface $orderModifier,
OrderProcessorInterface $orderProcessor, OrderProcessorInterface $orderProcessor,
ProductVariantResolverInterface $variantResolver ProductVariantResolverInterface $variantResolver
): void { ): void {
$this->beConstructedWith( $this->beConstructedWith(
$orderRepository, $orderItemRepository,
$productRepository,
$orderModifier, $orderModifier,
$orderProcessor, $orderProcessor,
$variantResolver $variantResolver
@ -52,68 +44,72 @@ final class RemoveItemFromCartHandlerSpec extends ObjectBehavior
$this->shouldImplement(MessageHandlerInterface::class); $this->shouldImplement(MessageHandlerInterface::class);
} }
function it_removes_simple_product_from_cart( function it_removes_order_item_from_cart(
OrderRepositoryInterface $orderRepository, OrderItemRepository $orderItemRepository,
ProductRepositoryInterface $productRepository,
OrderModifierInterface $orderModifier, OrderModifierInterface $orderModifier,
OrderProcessorInterface $orderProcessor, OrderProcessorInterface $orderProcessor,
ProductVariantResolverInterface $variantResolver,
ProductInterface $product,
OrderInterface $cart, OrderInterface $cart,
ProductVariantInterface $productVariant,
OrderItemUnitInterface $cartItemUnit,
OrderItemInterface $cartItem OrderItemInterface $cartItem
): void { ): void {
$productRepository->findOneByCode('PRODUCT_CODE')->willReturn($product); $orderItemRepository->findOneByIdAndCartTokenValue(
$orderRepository->findOneBy(['state' => OrderInterface::STATE_CART, 'tokenValue' => 'TOKEN'])->willReturn($cart); 'ORDER_ITEM_ID',
'TOKEN_VALUE'
)->willReturn($cartItem);
$variantResolver->getVariant($product)->willReturn($productVariant); $cartItem->getOrder()->willReturn($cart);
$orderItemUnits = new ArrayCollection([$cartItemUnit->getWrappedObject()]); $cart->getTokenValue()->willReturn('TOKEN_VALUE');
$cartItemUnit->getOrderItem()->willReturn($cartItem);
$cart->getItemUnitsByVariant($productVariant)->willReturn($orderItemUnits);
$orderModifier->removeFromOrder($cart, $cartItem)->shouldBeCalled(); $orderModifier->removeFromOrder($cart, $cartItem)->shouldBeCalled();
$orderProcessor->process($cart)->shouldBeCalled(); $orderProcessor->process($cart)->shouldBeCalled();
$this(RemoveItemFromCart::removeFromData('TOKEN', 'PRODUCT_CODE'))->shouldReturn($cart); $this(RemoveItemFromCart::removeFromData('TOKEN_VALUE', 'ORDER_ITEM_ID'))->shouldReturn($cart);
} }
function it_throws_an_exception_if_product_was_not_found( function it_throws_an_exception_if_order_item_was_not_found(
OrderRepositoryInterface $orderRepository, OrderItemRepository $orderItemRepository,
ProductRepositoryInterface $productRepository OrderItemInterface $cartItem
): void { ): void {
$productRepository->findOneByCode('PRODUCT_CODE')->willReturn(null); $orderItemRepository->findOneByIdAndCartTokenValue(
'ORDER_ITEM_ID',
'TOKEN_VALUE'
)->willReturn(null);
$orderRepository->findOneBy([ $cartItem->getOrder()->shouldNotBeCalled();
'state' => OrderInterface::STATE_CART,
'tokenValue' => 'TOKEN',
])->shouldNotBeCalled();
$this $this
->shouldThrow(\InvalidArgumentException::class) ->shouldThrow(\InvalidArgumentException::class)
->during('__invoke', [RemoveItemFromCart::removeFromData('TOKEN', 'PRODUCT_CODE')]) ->during(
'__invoke',
[RemoveItemFromCart::removeFromData('TOKEN_VALUE', 'ORDER_ITEM_ID')]
)
; ;
} }
function it_throws_an_exception_if_cart_was_not_found( function it_throws_an_exception_if_cart_token_value_was_not_properly(
OrderRepositoryInterface $orderRepository, OrderItemRepository $orderItemRepository,
ProductRepositoryInterface $productRepository, OrderModifierInterface $orderModifier,
ProductInterface $product, OrderItemInterface $cartItem,
ProductVariantInterface $productVariant,
OrderInterface $cart OrderInterface $cart
): void { ): void {
$productRepository->findOneByCode('PRODUCT_CODE')->willReturn($product); $orderItemRepository->findOneByIdAndCartTokenValue(
$orderRepository->findOneBy(['state' => OrderInterface::STATE_CART, 'tokenValue' => 'TOKEN'])->willReturn(null); 'ORDER_ITEM_ID',
'TOKEN_VALUE'
)->willReturn($cartItem);
$cart->getItemUnitsByVariant($productVariant)->shouldNotBeCalled(); $cartItem->getOrder()->willReturn($cart);
$cart->getTokenValue()->willReturn('WRONG_TOKEN_VALUE_');
$orderModifier->removeFromOrder(null, $cartItem)->shouldNotBeCalled();
$this $this
->shouldThrow(\InvalidArgumentException::class) ->shouldThrow(\InvalidArgumentException::class)
->during('__invoke', [RemoveItemFromCart::removeFromData('TOKEN', 'PRODUCT_CODE')]) ->during(
'__invoke',
[RemoveItemFromCart::removeFromData('TOKEN_VALUE', 'ORDER_ITEM_ID')]
)
; ;
} }
} }

View file

@ -34,4 +34,19 @@ class OrderItemRepository extends EntityRepository implements OrderItemRepositor
->getOneOrNullResult() ->getOneOrNullResult()
; ;
} }
public function findOneByIdAndCartTokenValue($id, $tokenValue): ?OrderItemInterface
{
return $this->createQueryBuilder('o')
->innerJoin('o.order', 'cart')
->andWhere('cart.state = :state')
->andWhere('o.id = :id')
->andWhere('cart.tokenValue = :tokenValue')
->setParameter('state', OrderInterface::STATE_CART)
->setParameter('id', $id)
->setParameter('tokenValue', $tokenValue)
->getQuery()
->getOneOrNullResult()
;
}
} }

View file

@ -19,4 +19,6 @@ use Sylius\Component\Resource\Repository\RepositoryInterface;
interface OrderItemRepositoryInterface extends RepositoryInterface interface OrderItemRepositoryInterface extends RepositoryInterface
{ {
public function findOneByIdAndCartId($id, $cartId): ?OrderItemInterface; public function findOneByIdAndCartId($id, $cartId): ?OrderItemInterface;
public function findOneByIdAndCartTokenValue($id, $tokenValue): ?OrderItemInterface;
} }