From 0935602f5a1d55cca290044e42078689d7cb09d4 Mon Sep 17 00:00:00 2001 From: david Date: Thu, 10 Aug 2023 14:06:21 +0300 Subject: [PATCH 1/2] split guest & customer carts for REST api --- Api/CartDonationManagementInterface.php | 24 +++++++ Api/DonationManagementInterface.php | 20 ------ Api/GuestCartDonationManagementInterface.php | 24 +++++++ Model/CartDonationManagement.php | 62 ++++++++++++++++++ Model/DonationManagement.php | 5 +- Model/GuestCartDonationManagement.php | 42 ++++++++++++ etc/di.xml | 4 +- etc/webapi.xml | 28 ++++++-- view/frontend/web/js/view/cart/donmo-block.js | 65 +++++++++---------- .../js/view/checkout/summary/donmo-block.js | 63 +++++++++--------- 10 files changed, 242 insertions(+), 95 deletions(-) create mode 100644 Api/CartDonationManagementInterface.php create mode 100644 Api/GuestCartDonationManagementInterface.php create mode 100644 Model/CartDonationManagement.php create mode 100644 Model/GuestCartDonationManagement.php diff --git a/Api/CartDonationManagementInterface.php b/Api/CartDonationManagementInterface.php new file mode 100644 index 0000000..a37b7c4 --- /dev/null +++ b/Api/CartDonationManagementInterface.php @@ -0,0 +1,24 @@ +cartRepository = $cartRepository; + $this->serializer = $serializer; + } + + /** + @inheritdoc + */ + public function addDonationToCart(int $cartId, float $donationAmount): string + { + try { + $quote = $this->cartRepository->get($cartId); + + if ($donationAmount > 0) { + $quote->setDonmodonation($donationAmount)->collectTotals(); + $this->cartRepository->save($quote); + + return $this->serializer->serialize(['message' => 'Success']); + } else { + return $this->serializer->serialize(['message' => 'Invalid donation']); + } + } catch (NoSuchEntityException) { + throw new NoSuchEntityException(__('The quote could not be loaded')); + } catch (\Exception $e) { + throw new \Exception('Some error has occurred'); + } + } + + /** + * @inheritdoc + */ + public function removeDonationFromCart(int $cartId): string + { + try { + $quote = $this->cartRepository->get($cartId); + + $quote->setDonmodonation(0)->collectTotals(); + $this->cartRepository->save($quote); + + return $this->serializer->serialize(['message' => 'Success']); + } catch (NoSuchEntityException) { + throw new NoSuchEntityException(__('The quote could not be loaded')); + } catch (\Exception $e) { + throw new \Exception('Some error has occurred'); + } + } +} diff --git a/Model/DonationManagement.php b/Model/DonationManagement.php index 2849a67..649c017 100644 --- a/Model/DonationManagement.php +++ b/Model/DonationManagement.php @@ -99,7 +99,7 @@ public function getByOrder(Order $order): DonationInterface // REST API Services - public function addDonationToQuote(string $cartId, float $donationAmount): string + public function addDonationToCart(string $cartId, float $donationAmount): string { try { $quoteId = $this->maskedQuoteIdToQuoteId->execute($cartId); @@ -126,7 +126,7 @@ public function addDonationToQuote(string $cartId, float $donationAmount): strin * @param string $cartId * @return string */ - public function removeDonationFromQuote(string $cartId): string + public function removeDonationFromCart(string $cartId): string { try { $quoteId = $this->maskedQuoteIdToQuoteId->execute($cartId); @@ -142,4 +142,5 @@ public function removeDonationFromQuote(string $cartId): string return $this->serializer->serialize(["message" => "An error has occurred: " . $e->getMessage()]); } } + } diff --git a/Model/GuestCartDonationManagement.php b/Model/GuestCartDonationManagement.php new file mode 100644 index 0000000..4d10255 --- /dev/null +++ b/Model/GuestCartDonationManagement.php @@ -0,0 +1,42 @@ +logger = $logger; + $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; + $this->cartDonationManagement = $cartDonationManagement; + } + + /** + * @inheritdoc + */ + public function addDonationToCart(string $cartId, float $donationAmount): string + { + $this->logger->info('addDonationToCart guest'); + return $this->cartDonationManagement->addDonationToCart($this->maskedQuoteIdToQuoteId->execute($cartId), $donationAmount); + } + + /** + * @inheritdoc + */ + public function removeDonationFromCart(string $cartId): string + { + return $this->cartDonationManagement->removeDonationFromCart($this->maskedQuoteIdToQuoteId->execute($cartId)); + } +} diff --git a/etc/di.xml b/etc/di.xml index f61acdf..65f244b 100644 --- a/etc/di.xml +++ b/etc/di.xml @@ -1,8 +1,10 @@ - + + + diff --git a/etc/webapi.xml b/etc/webapi.xml index c220f99..41bdede 100644 --- a/etc/webapi.xml +++ b/etc/webapi.xml @@ -1,17 +1,37 @@ - - + + - - + + + + + + + + + + %cart_id% + + + + + + + + + + %cart_id% + + diff --git a/view/frontend/web/js/view/cart/donmo-block.js b/view/frontend/web/js/view/cart/donmo-block.js index e022d8e..6e35a58 100644 --- a/view/frontend/web/js/view/cart/donmo-block.js +++ b/view/frontend/web/js/view/cart/donmo-block.js @@ -3,52 +3,49 @@ define([ 'ko', 'Magento_Checkout/js/model/totals', 'Magento_Checkout/js/model/quote', - 'mage/url', - 'Magento_Checkout/js/action/get-payment-information' -], function (Component, ko, totals, quote, url, getTotalsAction) { + 'Magento_Customer/js/model/customer', + 'Magento_Checkout/js/model/url-builder', + 'Magento_Checkout/js/action/get-payment-information', + 'mage/storage' +], function (Component, ko, totals, quote, customer, urlBuilder, getPaymentInformation, storage) { return Component.extend({ defaults: { template: 'Donmo_Roundup/checkout/summary/donmo-block', }, grandTotal: ko.observable(quote.totals()['grand_total']), + addDonation: ({ donationAmount }) => { const cartId = quote.getQuoteId(); - const path = url.build(`rest/V1/donmo/add_donation`) + let serviceUrl + if (!customer.isLoggedIn()) { + serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/add_donmo_donation', { cartId }); + } else { + serviceUrl = urlBuilder.createUrl('/carts/mine/add_donmo_donation', {}); + } - fetch(path, { - method: 'POST', - headers: { - 'X-Requested-With': 'XMLHttpRequest', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - donationAmount, - cartId - }) - }).then(response => { - if(!response.ok) { - throw new Error(); - } - return response.json() - }).then(() => getTotalsAction()) + const payload = { + cartId, + donationAmount + }; + + return storage.post( + serviceUrl, + JSON.stringify(payload) + ).then(() => getPaymentInformation()) }, + removeDonation: () => { - const cartId = quote.getQuoteId(); - const path = url.build(`rest/V1/donmo/remove_donation/${cartId}`) + let serviceUrl + if (!customer.isLoggedIn()) { + serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/remove_donmo_donation', { + cartId: quote.getQuoteId() + }); + } else { + serviceUrl = urlBuilder.createUrl('/carts/mine/remove_donmo_donation', {}); + } - return fetch(path, { - method: 'DELETE', - headers: { - 'X-Requested-With': 'XMLHttpRequest' - } - }).then(response => { - if(! response.ok) { - throw new Error(); - } - return response.json() - }).then( - () => getTotalsAction()) + return storage.delete(serviceUrl).then(() => getPaymentInformation()) }, insertIntegration: function (){ diff --git a/view/frontend/web/js/view/checkout/summary/donmo-block.js b/view/frontend/web/js/view/checkout/summary/donmo-block.js index 3b64e2a..6e35a58 100644 --- a/view/frontend/web/js/view/checkout/summary/donmo-block.js +++ b/view/frontend/web/js/view/checkout/summary/donmo-block.js @@ -3,9 +3,11 @@ define([ 'ko', 'Magento_Checkout/js/model/totals', 'Magento_Checkout/js/model/quote', - 'mage/url', - 'Magento_Checkout/js/action/get-payment-information' -], function (Component, ko, totals, quote, url, getTotalsAction) { + 'Magento_Customer/js/model/customer', + 'Magento_Checkout/js/model/url-builder', + 'Magento_Checkout/js/action/get-payment-information', + 'mage/storage' +], function (Component, ko, totals, quote, customer, urlBuilder, getPaymentInformation, storage) { return Component.extend({ defaults: { template: 'Donmo_Roundup/checkout/summary/donmo-block', @@ -15,42 +17,35 @@ define([ addDonation: ({ donationAmount }) => { const cartId = quote.getQuoteId(); - const path = url.build(`rest/V1/donmo/add_donation`) + let serviceUrl + if (!customer.isLoggedIn()) { + serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/add_donmo_donation', { cartId }); + } else { + serviceUrl = urlBuilder.createUrl('/carts/mine/add_donmo_donation', {}); + } - fetch(path, { - method: 'POST', - headers: { - 'X-Requested-With': 'XMLHttpRequest', - 'Content-Type': 'application/json' - }, - body: JSON.stringify({ - donationAmount, - cartId - }) - }).then(response => { - if(!response.ok) { - throw new Error(); - } - return response.json() - }).then(() => getTotalsAction()) + const payload = { + cartId, + donationAmount + }; + + return storage.post( + serviceUrl, + JSON.stringify(payload) + ).then(() => getPaymentInformation()) }, removeDonation: () => { - const cartId = quote.getQuoteId(); - const path = url.build(`rest/V1/donmo/remove_donation/${cartId}`) + let serviceUrl + if (!customer.isLoggedIn()) { + serviceUrl = urlBuilder.createUrl('/guest-carts/:cartId/remove_donmo_donation', { + cartId: quote.getQuoteId() + }); + } else { + serviceUrl = urlBuilder.createUrl('/carts/mine/remove_donmo_donation', {}); + } - return fetch(path, { - method: 'DELETE', - headers: { - 'X-Requested-With': 'XMLHttpRequest' - } - }).then(response => { - if(! response.ok) { - throw new Error(); - } - return response.json() - }).then( - () => getTotalsAction()) + return storage.delete(serviceUrl).then(() => getPaymentInformation()) }, insertIntegration: function (){ From 5adf8ade72505f95fd8f17aa4b519b5043f4b2ec Mon Sep 17 00:00:00 2001 From: david Date: Thu, 10 Aug 2023 14:07:47 +0300 Subject: [PATCH 2/2] improve cart handling in graphql resolvers --- ...ationToQuote.php => AddDonationToCart.php} | 28 ++++++++++--------- ...omQuote.php => RemoveDonationFromCart.php} | 22 +++++++-------- etc/schema.graphqls | 9 ++++-- 3 files changed, 33 insertions(+), 26 deletions(-) rename Model/Resolver/{AddDonationToQuote.php => AddDonationToCart.php} (58%) rename Model/Resolver/{RemoveDonationFromQuote.php => RemoveDonationFromCart.php} (55%) diff --git a/Model/Resolver/AddDonationToQuote.php b/Model/Resolver/AddDonationToCart.php similarity index 58% rename from Model/Resolver/AddDonationToQuote.php rename to Model/Resolver/AddDonationToCart.php index 7e4d9fa..f22bbd7 100644 --- a/Model/Resolver/AddDonationToQuote.php +++ b/Model/Resolver/AddDonationToCart.php @@ -6,39 +6,41 @@ use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; use Magento\Framework\GraphQl\Exception\GraphQlInputException; - use Magento\Quote\Api\CartRepositoryInterface; -class AddDonationToQuote implements ResolverInterface +use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; + + +class AddDonationToCart implements ResolverInterface { private Logger $logger; - private MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId; private CartRepositoryInterface $cartRepository; + private GetCartForUser $getCartForUser; public function __construct( Logger $logger, CartRepositoryInterface $cartRepository, - MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId, + GetCartForUser $getCartForUser ) { $this->logger = $logger; $this->cartRepository = $cartRepository; - $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; + $this->getCartForUser = $getCartForUser; } public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null): array { - $maskedId = $args['cartId']; - $quoteId = $this->maskedQuoteIdToQuoteId->execute($maskedId); - $quote = $this->cartRepository->get($quoteId); - - $donationAmount = $args['donationAmount']; + $donationAmount = $args['input']['donation_amount']; if (!is_numeric($donationAmount) || $donationAmount < 0) { throw new GraphQlInputException(__('Invalid donation')); } - $quote->setDonmodonation($donationAmount)->collectTotals(); - $this->cartRepository->save($quote); + $maskedCartId = $args['input']['cart_id']; + $currentUserId = $context->getUserId(); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId, $storeId); + + $cart->setDonmodonation($donationAmount)->collectTotals(); + $this->cartRepository->save($cart); return ['message' => 'success']; } diff --git a/Model/Resolver/RemoveDonationFromQuote.php b/Model/Resolver/RemoveDonationFromCart.php similarity index 55% rename from Model/Resolver/RemoveDonationFromQuote.php rename to Model/Resolver/RemoveDonationFromCart.php index 5988757..10489ee 100644 --- a/Model/Resolver/RemoveDonationFromQuote.php +++ b/Model/Resolver/RemoveDonationFromCart.php @@ -8,33 +8,33 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; use Magento\Quote\Api\CartRepositoryInterface; -use Magento\Quote\Model\MaskedQuoteIdToQuoteIdInterface; +use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; -class RemoveDonationFromQuote implements ResolverInterface +class RemoveDonationFromCart implements ResolverInterface { private Logger $logger; private CartRepositoryInterface $cartRepository; - private MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId; + private GetCartForUser $getCartForUser; public function __construct( Logger $logger, CartRepositoryInterface $cartRepository, - MaskedQuoteIdToQuoteIdInterface $maskedQuoteIdToQuoteId, + GetCartForUser $getCartForUser, ) { $this->logger = $logger; $this->cartRepository = $cartRepository; - $this->maskedQuoteIdToQuoteId = $maskedQuoteIdToQuoteId; + $this->getCartForUser = $getCartForUser; } - public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null): array { - $maskedId = $args['cartId']; - $quoteId = $this->maskedQuoteIdToQuoteId->execute($maskedId); - $quote = $this->cartRepository->get($quoteId); + $maskedCartId = $args['cart_id']; + $currentUserId = $context->getUserId(); + $storeId = (int)$context->getExtensionAttributes()->getStore()->getId(); + $cart = $this->getCartForUser->execute($maskedCartId, $currentUserId, $storeId); - $quote->setDonmodonation(0)->collectTotals(); - $this->cartRepository->save($quote); + $cart->setDonmodonation(0)->collectTotals(); + $this->cartRepository->save($cart); return ['message' => 'success']; } diff --git a/etc/schema.graphqls b/etc/schema.graphqls index 1cafa06..c14ae71 100644 --- a/etc/schema.graphqls +++ b/etc/schema.graphqls @@ -5,9 +5,14 @@ type CartPrices @doc(description: "Contains details about the final price of it } type Mutation { - addDonationToQuote(cartId: String!, donationAmount: Float!): DonmoDonationOutput @resolver(class: "\\Donmo\\Roundup\\Model\\Resolver\\AddDonationToQuote") @doc(description:"Add Donmo donation to quote") + addDonationToCart(input: AddDonationToCartInput): DonmoDonationOutput @resolver(class: "\\Donmo\\Roundup\\Model\\Resolver\\AddDonationToCart") @doc(description:"Add Donmo donation to cart") - removeDonationFromQuote(cartId: String!): DonmoDonationOutput @resolver(class: "\\Donmo\\Roundup\\Model\\Resolver\\RemoveDonationFromQuote") @doc(description:"Remove Donmo donation from quote") + removeDonationFromCart(cart_id: String!): DonmoDonationOutput @resolver(class: "\\Donmo\\Roundup\\Model\\Resolver\\RemoveDonationFromCart") @doc(description:"Remove Donmo donation from cart") +} + +input AddDonationToCartInput @doc(description: "Specifies the coupon code to apply to the cart.") { + cart_id: String! @doc(description: "The unique ID of a `Cart` object.") + donation_amount: Float! @doc(description: "Donation amount.") } type DonmoDonationOutput {