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));
+ }
+}