From 37eaceeee235d99bb67c2ec14d2935054cdb6ada Mon Sep 17 00:00:00 2001 From: Patrick McLain Date: Fri, 15 Feb 2019 08:54:04 -0500 Subject: [PATCH] Mutation for updating cart item quantities --- .../Model/Cart/UpdateCartItems.php | 58 +++++++ .../Model/Resolver/UpdateCartItems.php | 74 +++++++++ .../Magento/QuoteGraphQl/etc/schema.graphqls | 15 ++ .../GraphQl/Quote/UpdateCartItemsTest.php | 143 ++++++++++++++++++ 4 files changed, 290 insertions(+) create mode 100644 app/code/Magento/QuoteGraphQl/Model/Cart/UpdateCartItems.php create mode 100644 app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php create mode 100644 dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/UpdateCartItemsTest.php diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Cart/UpdateCartItems.php new file mode 100644 index 0000000000000..c2148dbe09933 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/UpdateCartItems.php @@ -0,0 +1,58 @@ +quoteRepository = $quoteRepository; + $this->guestCartRepository = $guestCartRepository; + } + + public function update(string $maskedCartId, array $items): Quote + { + $quote = $this->guestCartRepository->get($maskedCartId); + + foreach ($items as $item) { + $quoteItem = $quote->getItemById($item['item_id']); + if ($quoteItem === false) { + throw new NoSuchEntityException(__('Could not find cart item with id: %1', $item['item_id'])); + } + + $qty = $item['qty']; + + if ($qty <= 0.0) { + $quote->removeItem($quoteItem->getItemId()); + continue; + } + + $quoteItem->setQty($qty); + } + + $this->quoteRepository->save($quote); + + return $quote; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php new file mode 100644 index 0000000000000..1dfbb7cb9fb8d --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/UpdateCartItems.php @@ -0,0 +1,74 @@ +extractDataFromCart = $extractDataFromCart; + $this->arrayManager = $arrayManager; + $this->updateCartItems = $updateCartItems; + } + + public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) + { + $cartItems = $this->arrayManager->get('input/cart_items', $args); + $maskedCartId = $this->arrayManager->get('input/cart_id', $args); + + if (!$maskedCartId) { + throw new GraphQlInputException(__('Required parameter "cart_id" is missing')); + } + if (!$cartItems) { + throw new GraphQlInputException(__('Required parameter "cart_items " is missing')); + } + + try { + $cart = $this->updateCartItems->update($maskedCartId, $cartItems); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__($e->getMessage())); + } + + $cartData = $this->extractDataFromCart->execute($cart); + + return ['cart' => array_merge(['cart_id' => $maskedCartId], $cartData)]; + } +} diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index 2050a2d3ca790..853629d75e71c 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -14,6 +14,7 @@ type Mutation { setShippingAddressesOnCart(input: SetShippingAddressesOnCartInput): SetShippingAddressesOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingAddressesOnCart") setBillingAddressOnCart(input: SetBillingAddressOnCartInput): SetBillingAddressOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetBillingAddressOnCart") setShippingMethodsOnCart(input: SetShippingMethodsOnCartInput): SetShippingMethodsOnCartOutput @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\SetShippingMethodsOnCart") + updateCartItems(input: UpdateCartItemsInput): UpdateCartItemsOutput @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\UpdateCartItems") } input AddSimpleProductsToCartInput { @@ -206,6 +207,20 @@ type AddVirtualProductsToCartOutput { cart: Cart! } +input UpdateCartItemsInput { + cart_id: String! + cart_items: [UpdateCartItemInput!]! +} + +input UpdateCartItemInput { + item_id: String! + qty: Float! +} + +type UpdateCartItemsOutput { + cart: Cart! +} + type SimpleCartItem implements CartItemInterface @doc(description: "Simple Cart Item") { customizable_options: [SelectedCustomizableOption] @resolver(class: "Magento\\QuoteGraphQl\\Model\\Resolver\\CustomizableOptions") } diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/UpdateCartItemsTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/UpdateCartItemsTest.php new file mode 100644 index 0000000000000..66948b68ac43c --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/UpdateCartItemsTest.php @@ -0,0 +1,143 @@ +quoteResource = $objectManager->create(QuoteResource::class); + $this->quote = $objectManager->create(Quote::class); + $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->productRepository = $objectManager->get(ProductRepositoryInterface::class); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + */ + public function testUpdateCartItemQty() + { + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $quoteItem = $this->quote->getItemByProduct($this->productRepository->get('simple')); + $qty = $quoteItem->getQty() + 2; + + $query = $this->prepareUpdateItemsQuery($maskedQuoteId, (string) $quoteItem->getItemId(), $qty); + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('updateCartItems', $response); + $this->assertArrayHasKey('cart', $response['updateCartItems']); + + $responseCart = $response['updateCartItems']['cart']; + $item = current($responseCart['items']); + + $this->assertEquals($quoteItem->getItemId(), $item['id']); + $this->assertEquals($qty, $item['qty']); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + */ + public function testRemoveCartItemByZeroQuantityUpdate() + { + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + $quoteItem = $this->quote->getItemByProduct($this->productRepository->get('simple')); + + $query = $this->prepareUpdateItemsQuery($maskedQuoteId, (string) $quoteItem->getItemId(), 0); + $response = $this->graphQlQuery($query); + + $this->assertArrayHasKey('updateCartItems', $response); + $this->assertArrayHasKey('cart', $response['updateCartItems']); + + $responseCart = $response['updateCartItems']['cart']; + $this->assertCount(0, $responseCart['items']); + } + + /** + * @magentoApiDataFixture Magento/Checkout/_files/quote_with_simple_product_saved.php + * @expectedException \Exception + * @expectedExceptionMessage Could not find cart item with id + */ + public function testUpdateCartItemNoSuchItemEntity() + { + $this->quoteResource->load( + $this->quote, + 'test_order_with_simple_product_without_address', + 'reserved_order_id' + ); + $maskedQuoteId = $this->quoteIdToMaskedId->execute((int)$this->quote->getId()); + + $query = $this->prepareUpdateItemsQuery($maskedQuoteId, '999', 4); + $this->graphQlQuery($query); + } + + private function prepareUpdateItemsQuery(string $maskedQuoteId, string $itemId, float $qty): string + { + return <<