diff --git a/features/cart/shopping_cart/changing_quantity_of_product_in_cart.feature b/features/cart/shopping_cart/changing_quantity_of_product_in_cart.feature index fe83b0f6dff..64f739c748b 100644 --- a/features/cart/shopping_cart/changing_quantity_of_product_in_cart.feature +++ b/features/cart/shopping_cart/changing_quantity_of_product_in_cart.feature @@ -9,14 +9,14 @@ Feature: Changing quantity of a product in cart And the store has a product "T-shirt banana" priced at "$12.54" And I add this product to the cart - @ui + @ui @api Scenario: Increasing quantity of an item in cart Given I see the summary of my cart - When I change "T-shirt banana" quantity to 2 + When I change product "T-shirt banana" quantity to 2 in my cart Then I should see "T-shirt banana" with quantity 2 in my cart - @ui + @ui @api Scenario: Increasing quantity of an item in cart beyond the threshold Given I see the summary of my cart - When I change "T-shirt banana" quantity to 20000 + When I change product "T-shirt banana" quantity to 20000 in my cart Then I should see "T-shirt banana" with quantity 9999 in my cart diff --git a/src/Sylius/Behat/Context/Api/Shop/CartContext.php b/src/Sylius/Behat/Context/Api/Shop/CartContext.php index b400bd82702..773c45ea4fb 100644 --- a/src/Sylius/Behat/Context/Api/Shop/CartContext.php +++ b/src/Sylius/Behat/Context/Api/Shop/CartContext.php @@ -83,22 +83,22 @@ public function iAddOfThemToMyCart(int $quantity, ProductInterface $product, str $this->putProductToCart($product, $tokenValue, $quantity); } + /** + * @When /^I change (product "[^"]+") quantity to (\d+) in my (cart)$/ + */ + public function iChangeQuantityToInMyCart(ProductInterface $product, int $quantity, string $tokenValue): void + { + $itemId = $this->geOrderItemIdForProductInCart($product, $tokenValue); + $this->changeQuantityOfOrderItem($itemId, $quantity, $tokenValue); + } + /** * @When /^I remove (product "[^"]+") from the (cart)$/ */ public function iRemoveProductFromTheCart(ProductInterface $product, string $tokenValue): void { - $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); - } - } + $itemId = $this->geOrderItemIdForProductInCart($product, $tokenValue); + $this->removeOrderItemFromCart($itemId, $tokenValue); } /** @@ -244,4 +244,33 @@ private function getProductForItem(array $item): Response return $this->productsClient->show(StringInflector::nameToSlug($productCode)); } + + private function getOrderItemProductCode(array $item): string + { + $pathElements = explode('/', $item['variant']['product']); + + return $pathElements[array_key_last($pathElements)]; + } + + private function geOrderItemIdForProductInCart(ProductInterface $product, string $tokenValue): ?string + { + $items = $this->responseChecker->getValue($this->cartsClient->show($tokenValue), 'items'); + + foreach ($items as $item) { + if ($product->getCode() === $this->getOrderItemProductCode($item)) { + return (string) $item['id']; + } + } + + return null; + } + + private function changeQuantityOfOrderItem(string $orderItemId, int $quantity, string $tokenValue): void + { + $request = Request::customItemAction('orders', $tokenValue, HttpRequest::METHOD_PATCH, 'change-quantity'); + + $request->updateContent(['orderItemId' => $orderItemId, 'newQuantity' => $quantity]); + + $this->cartsClient->executeCustomRequest($request); + } } diff --git a/src/Sylius/Behat/Context/Ui/Shop/CartContext.php b/src/Sylius/Behat/Context/Ui/Shop/CartContext.php index 49911c175a5..633c9424ef1 100644 --- a/src/Sylius/Behat/Context/Ui/Shop/CartContext.php +++ b/src/Sylius/Behat/Context/Ui/Shop/CartContext.php @@ -90,6 +90,7 @@ public function iRemoveProductFromTheCart(string $productName): void /** * @Given I change :productName quantity to :quantity + * @Given I change product :productName quantity to :quantity in my cart */ public function iChangeQuantityTo($productName, $quantity) { diff --git a/src/Sylius/Bundle/ApiBundle/Command/Cart/ChangeItemQuantityInCart.php b/src/Sylius/Bundle/ApiBundle/Command/Cart/ChangeItemQuantityInCart.php new file mode 100644 index 00000000000..0adecc1bda8 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Command/Cart/ChangeItemQuantityInCart.php @@ -0,0 +1,59 @@ +orderItemId = $orderItemId; + $this->newQuantity = $newQuantity; + } + + public static function createFromData(string $tokenValue, string $orderItemId, int $newQuantity): self + { + $command = new self($orderItemId, $newQuantity); + + $command->orderTokenValue = $tokenValue; + + return $command; + } + + public function getOrderTokenValue(): ?string + { + return $this->orderTokenValue; + } + + public function setOrderTokenValue(?string $orderTokenValue): void + { + $this->orderTokenValue = $orderTokenValue; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/CommandHandler/Cart/ChangeItemQuantityInCartHandler.php b/src/Sylius/Bundle/ApiBundle/CommandHandler/Cart/ChangeItemQuantityInCartHandler.php new file mode 100644 index 00000000000..07120781910 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/CommandHandler/Cart/ChangeItemQuantityInCartHandler.php @@ -0,0 +1,66 @@ +orderItemRepository = $orderItemRepository; + $this->orderItemQuantityModifier = $orderItemQuantityModifier; + $this->orderProcessor = $orderProcessor; + } + + public function __invoke(ChangeItemQuantityInCart $command): OrderInterface + { + /** @var OrderItemInterface|null $orderItem */ + $orderItem = $this->orderItemRepository->findOneByIdAndCartTokenValue( + $command->orderItemId, + $command->orderTokenValue + ); + + Assert::notNull($orderItem); + + /** @var OrderInterface $cart */ + $cart = $orderItem->getOrder(); + + Assert::same($cart->getTokenValue(), $command->orderTokenValue); + + $this->orderItemQuantityModifier->modify($orderItem, $command->newQuantity); + $this->orderProcessor->process($cart); + + return $cart; + } +} diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Order.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Order.xml index 06850db2854..ca92d0393f0 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Order.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/api_resources/Order.xml @@ -143,6 +143,20 @@ cart:remove_item + + + is_granted('IS_AUTHENTICATED_ANONYMOUSLY') + + Change quantity of order item + + PATCH + /orders/{id}/change-quantity + input + Sylius\Bundle\ApiBundle\Command\Cart\ChangeItemQuantityInCart + + cart:change_quantity + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Cart/ChangeItemQuantityInCart.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Cart/ChangeItemQuantityInCart.xml new file mode 100644 index 00000000000..30394dfd163 --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/serialization/Commands/Cart/ChangeItemQuantityInCart.xml @@ -0,0 +1,27 @@ + + + + + + + + cart:change_quantity + + + + cart:change_quantity + + + diff --git a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml index 1995f8f1c1c..be48bcc0d4c 100644 --- a/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml +++ b/src/Sylius/Bundle/ApiBundle/Resources/config/services/command_handlers.xml @@ -77,5 +77,12 @@ + + + + + + + diff --git a/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Cart/ChangeItemQuantityInCartHandlerSpec.php b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Cart/ChangeItemQuantityInCartHandlerSpec.php new file mode 100644 index 00000000000..69047747c4d --- /dev/null +++ b/src/Sylius/Bundle/ApiBundle/spec/CommandHandler/Cart/ChangeItemQuantityInCartHandlerSpec.php @@ -0,0 +1,62 @@ +beConstructedWith($orderItemRepository, $orderItemQuantityModifier, $orderProcessor); + } + + function it_is_a_message_handler(): void + { + $this->shouldImplement(MessageHandlerInterface::class); + } + + function it_changes_order_item_quantity( + OrderItemRepositoryInterface $orderItemRepository, + OrderItemQuantityModifierInterface $orderItemQuantityModifier, + OrderProcessorInterface $orderProcessor, + OrderInterface $cart, + OrderItemInterface $cartItem + ): void { + $orderItemRepository->findOneByIdAndCartTokenValue( + 'ORDER_ITEM_ID', + 'TOKEN_VALUE' + )->willReturn($cartItem); + + $cartItem->getOrder()->willReturn($cart); + + $cart->getTokenValue()->willReturn('TOKEN_VALUE'); + + $orderItemQuantityModifier->modify($cartItem, 5)->shouldBeCalled(); + $orderProcessor->process($cart)->shouldBeCalled(); + + $this(ChangeItemQuantityInCart::createFromData( 'TOKEN_VALUE', 'ORDER_ITEM_ID', 5)); + } +}