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\SprintfResponseEscaper;
use Sylius\Component\Core\Model\ProductInterface;
use Sylius\Component\Core\Model\ProductVariantInterface;
use Symfony\Component\HttpFoundation\Request as HttpRequest;
use Symfony\Component\HttpFoundation\Response;
use Webmozart\Assert\Assert;
@ -83,7 +84,17 @@ final class CartContext implements Context
*/
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);
}
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->updateContent(['productCode' => $product->getCode()]);
$request->updateContent(['orderItemId' => $orderItemId]);
$this->cartsClient->executeCustomRequest($request);
}

View file

@ -22,16 +22,16 @@ final class RemoveItemFromCart
* @var string
* @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;

View file

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

View file

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

View file

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

@ -63,7 +63,7 @@ class OrderRepository extends EntityRepository implements OrderRepositoryInterfa
->addOrderBy('o.checkoutCompletedAt', 'DESC')
->getQuery()
->getOneOrNullResult()
;
;
}
public function findOneByNumber(string $number): ?OrderInterface

View file

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