diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AssignBillingAddressToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AssignBillingAddressToCart.php index 370501e9c6e8..dd6478b4873c 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AssignBillingAddressToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AssignBillingAddressToCart.php @@ -11,9 +11,9 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; +use Magento\Quote\Api\Data\AddressInterface; use Magento\Quote\Api\Data\CartInterface; use Magento\Quote\Api\BillingAddressManagementInterface; -use Magento\Quote\Model\Quote\Address as QuoteAddress; /** * Set billing address for a specified shopping cart @@ -38,22 +38,22 @@ public function __construct( * Assign billing address to cart * * @param CartInterface $cart - * @param QuoteAddress $billingAddress + * @param AddressInterface $billingAddress * @param bool $useForShipping * @throws GraphQlInputException * @throws GraphQlNoSuchEntityException */ public function execute( CartInterface $cart, - QuoteAddress $billingAddress, + AddressInterface $billingAddress, bool $useForShipping ): void { try { $this->billingAddressManagement->assign($cart->getId(), $billingAddress, $useForShipping); } catch (NoSuchEntityException $e) { - throw new GraphQlNoSuchEntityException(__($e->getMessage())); + throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); } catch (LocalizedException $e) { - throw new GraphQlInputException(__($e->getMessage())); + throw new GraphQlInputException(__($e->getMessage()), $e); } } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingAddressToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingAddressToCart.php index 47f90edb04be..527999b245a4 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingAddressToCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingAddressToCart.php @@ -11,8 +11,8 @@ use Magento\Framework\Exception\NoSuchEntityException; use Magento\Framework\GraphQl\Exception\GraphQlInputException; use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; +use Magento\Quote\Api\Data\AddressInterface; use Magento\Quote\Api\Data\CartInterface; -use Magento\Quote\Model\Quote\Address as QuoteAddress; use Magento\Quote\Model\ShippingAddressManagementInterface; /** @@ -38,20 +38,20 @@ public function __construct( * Assign shipping address to cart * * @param CartInterface $cart - * @param QuoteAddress $shippingAddress + * @param AddressInterface $shippingAddress * @throws GraphQlInputException * @throws GraphQlNoSuchEntityException */ public function execute( CartInterface $cart, - QuoteAddress $shippingAddress + AddressInterface $shippingAddress ): void { try { $this->shippingAddressManagement->assign($cart->getId(), $shippingAddress); } catch (NoSuchEntityException $e) { - throw new GraphQlNoSuchEntityException(__($e->getMessage())); + throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); } catch (LocalizedException $e) { - throw new GraphQlInputException(__($e->getMessage())); + throw new GraphQlInputException(__($e->getMessage()), $e); } } } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingMethodToCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingMethodToCart.php new file mode 100644 index 000000000000..5b30c0774c22 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/AssignShippingMethodToCart.php @@ -0,0 +1,82 @@ +shippingInformationFactory = $shippingInformationFactory; + $this->shippingInformationManagement = $shippingInformationManagement; + } + + /** + * Assign shipping method to cart + * + * @param CartInterface $cart + * @param AddressInterface $quoteAddress + * @param string $carrierCode + * @param string $methodCode + * @throws GraphQlInputException + * @throws GraphQlNoSuchEntityException + */ + public function execute( + CartInterface $cart, + AddressInterface $quoteAddress, + string $carrierCode, + string $methodCode + ): void { + /** @var ShippingInformationInterface $shippingInformation */ + $shippingInformation = $this->shippingInformationFactory->create([ + 'data' => [ + /* If the address is not a shipping address (but billing) the system will find the proper shipping + address for the selected cart and set the information there (actual for single shipping address) */ + ShippingInformationInterface::SHIPPING_ADDRESS => $quoteAddress, + ShippingInformationInterface::SHIPPING_CARRIER_CODE => $carrierCode, + ShippingInformationInterface::SHIPPING_METHOD_CODE => $methodCode, + ], + ]); + + try { + $this->shippingInformationManagement->saveAddressInformation($cart->getId(), $shippingInformation); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); + } catch (LocalizedException $e) { + throw new GraphQlInputException(__($e->getMessage()), $e); + } + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromAddress.php b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromAddress.php index a52745a8bb74..04fe14600810 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromAddress.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/ExtractDataFromAddress.php @@ -51,12 +51,6 @@ public function execute(QuoteAddress $address): array 'label' => $address->getRegion() ], 'street' => $address->getStreet(), - 'selected_shipping_method' => [ - 'code' => $address->getShippingMethod(), - 'label' => $address->getShippingDescription(), - 'free_shipping' => $address->getFreeShipping(), - 'amount' => $address->getShippingAmount() - ], 'items_weight' => $address->getWeight(), 'customer_notes' => $address->getCustomerNotes() ]); diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php b/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php index 93c888a1d0bd..039324abf685 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/GetCustomerAddress.php @@ -16,7 +16,7 @@ use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException; /** - * Get customer address. Throws exception if customer is not owner of address + * Get customer address */ class GetCustomerAddress { @@ -52,7 +52,7 @@ public function execute(int $addressId, int $customerId): AddressInterface __('Could not find a address with ID "%address_id"', ['address_id' => $addressId]) ); } catch (LocalizedException $e) { - throw new GraphQlInputException(__($e->getMessage())); + throw new GraphQlInputException(__($e->getMessage()), $e); } if ((int)$customerAddress->getCustomerId() !== $customerId) { diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/GetQuoteAddress.php b/app/code/Magento/QuoteGraphQl/Model/Cart/GetQuoteAddress.php new file mode 100644 index 000000000000..1fb737d96413 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/GetQuoteAddress.php @@ -0,0 +1,82 @@ +quoteAddressFactory = $quoteAddressFactory; + $this->quoteAddressResource = $quoteAddressResource; + } + + /** + * Get quote address + * + * @param int $quoteAddressId + * @param int|null $customerId + * @return AddressInterface + * @throws GraphQlInputException + * @throws GraphQlNoSuchEntityException + * @throws GraphQlAuthorizationException + */ + public function execute(int $quoteAddressId, ?int $customerId): AddressInterface + { + $quoteAddress = $this->quoteAddressFactory->create(); + + $this->quoteAddressResource->load($quoteAddress, $quoteAddressId); + if (null === $quoteAddress->getId()) { + throw new GraphQlNoSuchEntityException( + __('Could not find a cart address with ID "%cart_address_id"', ['cart_address_id' => $quoteAddressId]) + ); + } + + $quoteAddressCustomerId = (int)$quoteAddress->getCustomerId(); + + /* Guest cart, allow operations */ + if (!$quoteAddressCustomerId && null === $customerId) { + return $quoteAddress; + } + + if ($quoteAddressCustomerId !== $customerId) { + throw new GraphQlAuthorizationException( + __( + 'The current user cannot use cart address with ID "%cart_address_id"', + ['cart_address_id' => $quoteAddressId] + ) + ); + } + return $quoteAddress; + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php index 7dfea0836e8d..76bdc7461113 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/QuoteAddressFactory.php @@ -60,7 +60,7 @@ public function createBasedOnCustomerAddress(CustomerAddress $customerAddress): try { $quoteAddress->importCustomerAddressData($customerAddress); } catch (LocalizedException $e) { - throw new GraphQlInputException(__($e->getMessage())); + throw new GraphQlInputException(__($e->getMessage()), $e); } return $quoteAddress; } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php index 04b7bfcfe0e6..cf277c729cdf 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetBillingAddressOnCart.php @@ -63,19 +63,19 @@ public function __construct( * * @param ContextInterface $context * @param CartInterface $cart - * @param array $billingAddress + * @param array $billingAddressInput * @return void * @throws GraphQlInputException * @throws GraphQlAuthenticationException * @throws GraphQlAuthorizationException * @throws GraphQlNoSuchEntityException */ - public function execute(ContextInterface $context, CartInterface $cart, array $billingAddress): void + public function execute(ContextInterface $context, CartInterface $cart, array $billingAddressInput): void { - $customerAddressId = $billingAddress['customer_address_id'] ?? null; - $addressInput = $billingAddress['address'] ?? null; - $useForShipping = isset($billingAddress['use_for_shipping']) - ? (bool)$billingAddress['use_for_shipping'] : false; + $customerAddressId = $billingAddressInput['customer_address_id'] ?? null; + $addressInput = $billingAddressInput['address'] ?? null; + $useForShipping = isset($billingAddressInput['use_for_shipping']) + ? (bool)$billingAddressInput['use_for_shipping'] : false; if (null === $customerAddressId && null === $addressInput) { throw new GraphQlInputException( diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php similarity index 88% rename from app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php rename to app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php index 1a1442485349..8e54ab0d3fee 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCart.php @@ -15,7 +15,7 @@ /** * Set single shipping address for a specified shopping cart */ -class SetShippingAddressOnCart implements SetShippingAddressesOnCartInterface +class SetShippingAddressesOnCart implements SetShippingAddressesOnCartInterface { /** * @var QuoteAddressFactory @@ -58,16 +58,16 @@ public function __construct( /** * @inheritdoc */ - public function execute(ContextInterface $context, CartInterface $cart, array $shippingAddresses): void + public function execute(ContextInterface $context, CartInterface $cart, array $shippingAddressesInput): void { - if (count($shippingAddresses) > 1) { + if (count($shippingAddressesInput) > 1) { throw new GraphQlInputException( __('You cannot specify multiple shipping addresses.') ); } - $shippingAddress = current($shippingAddresses); - $customerAddressId = $shippingAddress['customer_address_id'] ?? null; - $addressInput = $shippingAddress['address'] ?? null; + $shippingAddressInput = current($shippingAddressesInput); + $customerAddressId = $shippingAddressInput['customer_address_id'] ?? null; + $addressInput = $shippingAddressInput['address'] ?? null; if (null === $customerAddressId && null === $addressInput) { throw new GraphQlInputException( diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCartInterface.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCartInterface.php index 81da47933e81..eb0f3522102c 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCartInterface.php +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingAddressesOnCartInterface.php @@ -27,12 +27,12 @@ interface SetShippingAddressesOnCartInterface * * @param ContextInterface $context * @param CartInterface $cart - * @param array $shippingAddresses + * @param array $shippingAddressesInput * @return void * @throws GraphQlInputException * @throws GraphQlAuthorizationException * @throws GraphQlAuthenticationException * @throws GraphQlNoSuchEntityException */ - public function execute(ContextInterface $context, CartInterface $cart, array $shippingAddresses): void; + public function execute(ContextInterface $context, CartInterface $cart, array $shippingAddressesInput): void; } diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodOnCart.php deleted file mode 100644 index a630b2d07c7d..000000000000 --- a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodOnCart.php +++ /dev/null @@ -1,101 +0,0 @@ -shippingInformationManagement = $shippingInformationManagement; - $this->quoteAddressResource = $quoteAddressResource; - $this->quoteAddressFactory = $quoteAddressFactory; - $this->shippingInformationFactory = $shippingInformationFactory; - } - - /** - * Sets shipping method for a specified shopping cart address - * - * @param Quote $cart - * @param int $cartAddressId - * @param string $carrierCode - * @param string $methodCode - * @throws GraphQlInputException - * @throws GraphQlNoSuchEntityException - */ - public function execute(Quote $cart, int $cartAddressId, string $carrierCode, string $methodCode): void - { - $quoteAddress = $this->quoteAddressFactory->create(); - $this->quoteAddressResource->load($quoteAddress, $cartAddressId); - - /** @var ShippingInformation $shippingInformation */ - $shippingInformation = $this->shippingInformationFactory->create(); - - /* If the address is not a shipping address (but billing) the system will find the proper shipping address for - the selected cart and set the information there (actual for single shipping address) */ - $shippingInformation->setShippingAddress($quoteAddress); - $shippingInformation->setShippingCarrierCode($carrierCode); - $shippingInformation->setShippingMethodCode($methodCode); - - try { - $this->shippingInformationManagement->saveAddressInformation($cart->getId(), $shippingInformation); - } catch (NoSuchEntityException $exception) { - throw new GraphQlNoSuchEntityException(__($exception->getMessage())); - } catch (StateException $exception) { - throw new GraphQlInputException(__($exception->getMessage())); - } catch (InputException $exception) { - throw new GraphQlInputException(__($exception->getMessage())); - } - } -} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php new file mode 100644 index 000000000000..37e011842374 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCart.php @@ -0,0 +1,76 @@ +getQuoteAddress = $getQuoteAddress; + $this->assignShippingMethodToCart = $assignShippingMethodToCart; + } + + /** + * @inheritdoc + */ + public function execute(ContextInterface $context, CartInterface $cart, array $shippingMethodsInput): void + { + if (count($shippingMethodsInput) > 1) { + throw new GraphQlInputException( + __('You cannot specify multiple shipping methods.') + ); + } + $shippingMethodInput = current($shippingMethodsInput); + + if (!isset($shippingMethodInput['cart_address_id']) || empty($shippingMethodInput['cart_address_id'])) { + throw new GraphQlInputException(__('Required parameter "cart_address_id" is missing.')); + } + $cartAddressId = $shippingMethodInput['cart_address_id']; + + if (!isset($shippingMethodInput['carrier_code']) || empty($shippingMethodInput['carrier_code'])) { + throw new GraphQlInputException(__('Required parameter "carrier_code" is missing.')); + } + $carrierCode = $shippingMethodInput['carrier_code']; + + if (!isset($shippingMethodInput['method_code']) || empty($shippingMethodInput['method_code'])) { + throw new GraphQlInputException(__('Required parameter "method_code" is missing.')); + } + $methodCode = $shippingMethodInput['method_code']; + + $quoteAddress = $this->getQuoteAddress->execute($cartAddressId, $context->getUserId()); + + $this->assignShippingMethodToCart->execute($cart, $quoteAddress, $carrierCode, $methodCode); + } +} diff --git a/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCartInterface.php b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCartInterface.php new file mode 100644 index 000000000000..fa6c6cf0923e --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Cart/SetShippingMethodsOnCartInterface.php @@ -0,0 +1,38 @@ +couponManagement->set($cartId, $couponCode); - } catch (NoSuchEntityException $exception) { - throw new GraphQlNoSuchEntityException(__($exception->getMessage())); - } catch (CouldNotSaveException $exception) { - throw new LocalizedException(__($exception->getMessage())); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); + } catch (CouldNotSaveException $e) { + throw new LocalizedException(__($e->getMessage()), $e); } return [ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php index 730c927c32a0..68925c6e8944 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveCouponFromCart.php @@ -61,10 +61,10 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value try { $this->couponManagement->remove($cartId); - } catch (NoSuchEntityException $exception) { - throw new GraphQlNoSuchEntityException(__($exception->getMessage())); - } catch (CouldNotDeleteException $exception) { - throw new LocalizedException(__($exception->getMessage())); + } catch (NoSuchEntityException $e) { + throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); + } catch (CouldNotDeleteException $e) { + throw new LocalizedException(__($e->getMessage()), $e); } return [ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php index 1838f17369ff..c8f0ef06c759 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/RemoveItemFromCart.php @@ -64,9 +64,9 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value try { $this->guestCartItemRepository->deleteById($maskedCartId, $itemId); } catch (NoSuchEntityException $e) { - throw new GraphQlNoSuchEntityException(__($e->getMessage())); + throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); } catch (LocalizedException $e) { - throw new GraphQlInputException(__($e->getMessage())); + throw new GraphQlInputException(__($e->getMessage()), $e); } return [ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php index ffd1bf37f477..a93c8032c996 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetPaymentMethodOnCart.php @@ -86,9 +86,9 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value try { $this->paymentMethodManagement->set($cart->getId(), $payment); } catch (NoSuchEntityException $e) { - throw new GraphQlNoSuchEntityException(__($e->getMessage())); + throw new GraphQlNoSuchEntityException(__($e->getMessage()), $e); } catch (LocalizedException $e) { - throw new GraphQlInputException(__($e->getMessage())); + throw new GraphQlInputException(__($e->getMessage()), $e); } return [ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php index f2e5be797dbd..e69ba47e7adf 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/SetShippingMethodsOnCart.php @@ -11,9 +11,8 @@ use Magento\Framework\GraphQl\Query\ResolverInterface; use Magento\Framework\GraphQl\Config\Element\Field; use Magento\Framework\GraphQl\Schema\Type\ResolveInfo; -use Magento\Framework\Stdlib\ArrayManager; use Magento\QuoteGraphQl\Model\Cart\GetCartForUser; -use Magento\QuoteGraphQl\Model\Cart\SetShippingMethodOnCart; +use Magento\QuoteGraphQl\Model\Cart\SetShippingMethodsOnCartInterface; /** * Mutation resolver for setting shipping methods for shopping cart @@ -21,33 +20,25 @@ class SetShippingMethodsOnCart implements ResolverInterface { /** - * @var SetShippingMethodOnCart - */ - private $setShippingMethodOnCart; - - /** - * @var ArrayManager + * @var GetCartForUser */ - private $arrayManager; + private $getCartForUser; /** - * @var GetCartForUser + * @var SetShippingMethodsOnCartInterface */ - private $getCartForUser; + private $setShippingMethodsOnCart; /** - * @param ArrayManager $arrayManager * @param GetCartForUser $getCartForUser - * @param SetShippingMethodOnCart $setShippingMethodOnCart + * @param SetShippingMethodsOnCartInterface $setShippingMethodsOnCart */ public function __construct( - ArrayManager $arrayManager, GetCartForUser $getCartForUser, - SetShippingMethodOnCart $setShippingMethodOnCart + SetShippingMethodsOnCartInterface $setShippingMethodsOnCart ) { - $this->arrayManager = $arrayManager; $this->getCartForUser = $getCartForUser; - $this->setShippingMethodOnCart = $setShippingMethodOnCart; + $this->setShippingMethodsOnCart = $setShippingMethodsOnCart; } /** @@ -55,37 +46,18 @@ public function __construct( */ public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null) { - $shippingMethods = $this->arrayManager->get('input/shipping_methods', $args); - $maskedCartId = $this->arrayManager->get('input/cart_id', $args); - - if (!$maskedCartId) { + if (!isset($args['input']['cart_id']) || empty($args['input']['cart_id'])) { throw new GraphQlInputException(__('Required parameter "cart_id" is missing')); } - if (!$shippingMethods) { - throw new GraphQlInputException(__('Required parameter "shipping_methods" is missing')); - } + $maskedCartId = $args['input']['cart_id']; - $shippingMethod = reset($shippingMethods); // This point can be extended for multishipping - - if (!isset($shippingMethod['cart_address_id']) || empty($shippingMethod['cart_address_id'])) { - throw new GraphQlInputException(__('Required parameter "cart_address_id" is missing')); - } - if (!isset($shippingMethod['carrier_code']) || empty($shippingMethod['carrier_code'])) { - throw new GraphQlInputException(__('Required parameter "shipping_carrier_code" is missing')); - } - if (!isset($shippingMethod['method_code']) || empty($shippingMethod['method_code'])) { - throw new GraphQlInputException(__('Required parameter "shipping_method_code" is missing')); + if (!isset($args['input']['shipping_methods']) || empty($args['input']['shipping_methods'])) { + throw new GraphQlInputException(__('Required parameter "shipping_methods" is missing')); } + $shippingMethods = $args['input']['shipping_methods']; - $userId = $context->getUserId(); - $cart = $this->getCartForUser->execute((string) $maskedCartId, $userId); - - $this->setShippingMethodOnCart->execute( - $cart, - $shippingMethod['cart_address_id'], - $shippingMethod['carrier_code'], - $shippingMethod['method_code'] - ); + $cart = $this->getCartForUser->execute($maskedCartId, $context->getUserId()); + $this->setShippingMethodsOnCart->execute($context, $cart, $shippingMethods); return [ 'cart' => [ diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAdress/AvailableShippingMethods.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php similarity index 97% rename from app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAdress/AvailableShippingMethods.php rename to app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php index 7804b8defe37..a9e0ba59d15d 100644 --- a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAdress/AvailableShippingMethods.php +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/AvailableShippingMethods.php @@ -5,7 +5,7 @@ */ declare(strict_types=1); -namespace Magento\QuoteGraphQl\Model\Resolver\ShippingAdress; +namespace Magento\QuoteGraphQl\Model\Resolver\ShippingAddress; use Magento\Framework\Api\ExtensibleDataObjectConverter; use Magento\Framework\Exception\LocalizedException; diff --git a/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php new file mode 100644 index 000000000000..c58affa064c8 --- /dev/null +++ b/app/code/Magento/QuoteGraphQl/Model/Resolver/ShippingAddress/SelectedShippingMethod.php @@ -0,0 +1,43 @@ +getShippingMethod()) { + list($carrierCode, $methodCode) = explode('_', $address->getShippingMethod(), 2); + $shippingAmount = $address->getShippingAmount(); + } + + return [ + 'carrier_code' => $carrierCode ?? null, + 'method_code' => $methodCode ?? null, + 'label' => $address->getShippingDescription(), + 'amount' => $shippingAmount ?? null, + ]; + } +} diff --git a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml index 86bc954ae4ac..c7389cf66784 100644 --- a/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml +++ b/app/code/Magento/QuoteGraphQl/etc/graphql/di.xml @@ -7,5 +7,7 @@ --> + type="Magento\QuoteGraphQl\Model\Cart\SetShippingAddressesOnCart"/> + diff --git a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls index e4ced2351572..5f65a990bac2 100644 --- a/app/code/Magento/QuoteGraphQl/etc/schema.graphqls +++ b/app/code/Magento/QuoteGraphQl/etc/schema.graphqls @@ -66,12 +66,6 @@ input SetShippingAddressesOnCartInput { input ShippingAddressInput { customer_address_id: Int # If provided then will be used address from address book address: CartAddressInput - cart_items: [CartItemQuantityInput!] -} - -input CartItemQuantityInput { - cart_item_id: Int! - quantity: Float! } input SetBillingAddressOnCartInput { @@ -100,10 +94,10 @@ input CartAddressInput { input SetShippingMethodsOnCartInput { cart_id: String! - shipping_methods: [ShippingMethodForAddressInput!]! + shipping_methods: [ShippingMethodInput!]! } -input ShippingMethodForAddressInput { +input ShippingMethodInput { cart_address_id: Int! carrier_code: String! method_code: String! @@ -117,10 +111,6 @@ input SetPaymentMethodOnCartInput { input PaymentMethodInput { code: String! @doc(description:"Payment method code") purchase_order_number: String @doc(description:"Purchase order number") - additional_data: PaymentMethodAdditionalDataInput -} - -input PaymentMethodAdditionalDataInput { } type SetPaymentMethodOnCartOutput { @@ -164,8 +154,8 @@ type CartAddress { country: CartAddressCountry telephone: String address_type: AdressTypeEnum - available_shipping_methods: [AvailableShippingMethod] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAdress\\AvailableShippingMethods") - selected_shipping_method: SelectedShippingMethod + available_shipping_methods: [AvailableShippingMethod] @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddress\\AvailableShippingMethods") + selected_shipping_method: SelectedShippingMethod @resolver(class: "\\Magento\\QuoteGraphQl\\Model\\Resolver\\ShippingAddress\\SelectedShippingMethod") items_weight: Float customer_notes: String cart_items: [CartItemQuantity] @@ -187,7 +177,10 @@ type CartAddressCountry { } type SelectedShippingMethod { - amount: Float! + carrier_code: String + method_code: String + label: String + amount: Float } type AvailableShippingMethod { @@ -210,10 +203,6 @@ type AvailablePaymentMethod { type SelectedPaymentMethod { code: String @doc(description: "The payment method code") purchase_order_number: String @doc(description: "The purchase order number.") - additional_data: SelectedPaymentMethodAdditionalData -} - -type SelectedPaymentMethodAdditionalData { } enum AdressTypeEnum { diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php new file mode 100644 index 000000000000..736ea6944075 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Customer/SetShippingMethodsOnCartTest.php @@ -0,0 +1,206 @@ +quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteFactory = $objectManager->get(QuoteFactory::class); + $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + $this->customerTokenService = $objectManager->get(CustomerTokenServiceInterface::class); + } + + public function testShippingMethodWithVirtualProduct() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testShippingMethodWithSimpleProduct() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testShippingMethodWithSimpleProductWithoutAddress() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testSetShippingMethodWithMissedRequiredParameters() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testSetNonExistentShippingMethod() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testSetShippingMethodIfAddressIsNotBelongToCart() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testSetShippingMethodToNonExistentCart() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testSetShippingMethodToGuestCart() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testSetShippingMethodToAnotherCustomerCart() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testSetShippingMethodToNonExistentCartAddress() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testSetShippingMethodToGuestCartAddress() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testSetShippingMethodToAnotherCustomerCartAddress() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + public function testSetMultipleShippingMethods() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/423'); + } + + /** + * @param string $maskedQuoteId + * @param string $shippingMethodCode + * @param string $shippingCarrierCode + * @param string $shippingAddressId + * @return string + * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + */ + private function prepareMutationQuery( + string $maskedQuoteId, + string $shippingMethodCode, + string $shippingCarrierCode, + string $shippingAddressId + ) : string { + return <<quoteFactory->create(); + $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id'); + + return $this->quoteIdToMaskedId->execute((int)$quote->getId()); + } + + /** + * @param string $reversedQuoteId + * @param int $customerId + * @return string + * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + */ + private function assignQuoteToCustomer( + string $reversedQuoteId, + int $customerId + ): string { + $quote = $this->quoteFactory->create(); + $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id'); + $quote->setCustomerId($customerId); + $this->quoteResource->save($quote); + return $this->quoteIdToMaskedId->execute((int)$quote->getId()); + } + + /** + * @param string $username + * @param string $password + * @return array + * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + */ + private function getHeaderMap(string $username = 'customer@example.com', string $password = 'password'): array + { + $customerToken = $this->customerTokenService->createCustomerAccessToken($username, $password); + $headerMap = ['Authorization' => 'Bearer ' . $customerToken]; + return $headerMap; + } +} diff --git a/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php new file mode 100644 index 000000000000..f159cb6f6151 --- /dev/null +++ b/dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/Guest/SetShippingMethodsOnCartTest.php @@ -0,0 +1,167 @@ +quoteResource = $objectManager->get(QuoteResource::class); + $this->quoteFactory = $objectManager->get(QuoteFactory::class); + $this->quoteIdToMaskedId = $objectManager->get(QuoteIdToMaskedQuoteIdInterface::class); + } + + public function testShippingMethodWithVirtualProduct() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testShippingMethodWithSimpleProduct() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testShippingMethodWithSimpleProductWithoutAddress() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testSetShippingMethodWithMissedRequiredParameters() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testSetNonExistentShippingMethod() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testSetShippingMethodIfAddressIsNotBelongToCart() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testSetShippingMethodToNonExistentCart() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testSetShippingMethodToGuestCart() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testSetShippingMethodToAnotherCustomerCart() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testSetShippingMethodToNonExistentCartAddress() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testSetShippingMethodToGuestCartAddress() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testSetShippingMethodToAnotherCustomerCartAddress() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + public function testSetMultipleShippingMethods() + { + $this->markTestIncomplete('https://github.com/magento/graphql-ce/issues/422'); + } + + /** + * @param string $maskedQuoteId + * @param string $shippingMethodCode + * @param string $shippingCarrierCode + * @param string $shippingAddressId + * @return string + * @SuppressWarnings(PHPMD.UnusedPrivateMethod) + */ + private function prepareMutationQuery( + string $maskedQuoteId, + string $shippingMethodCode, + string $shippingCarrierCode, + string $shippingAddressId + ) : string { + return <<quoteFactory->create(); + $this->quoteResource->load($quote, $reversedQuoteId, 'reserved_order_id'); + + return $this->quoteIdToMaskedId->execute((int)$quote->getId()); + } +} diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/enable_all_shipping_methods.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/enable_all_shipping_methods.php new file mode 100644 index 000000000000..dd48975aa2b0 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/enable_all_shipping_methods.php @@ -0,0 +1,26 @@ +create(WriterInterface::class); + +$configWriter->save('carriers/flatrate/active', 1); +$configWriter->save('carriers/tablerate/active', 1); +$configWriter->save('carriers/freeshipping/active', 1); +$configWriter->save('carriers/ups/active', 1); +$configWriter->save('carriers/usps/active', 1); +$configWriter->save('carriers/fedex/active', 1); +$configWriter->save('carriers/dhl/active', 1); + +$scopeConfig = $objectManager->get(ScopeConfigInterface::class); +$scopeConfig->clean(); diff --git a/dev/tests/integration/testsuite/Magento/Checkout/_files/enable_all_shipping_methods_rollback.php b/dev/tests/integration/testsuite/Magento/Checkout/_files/enable_all_shipping_methods_rollback.php new file mode 100644 index 000000000000..7a3ca79febf6 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/Checkout/_files/enable_all_shipping_methods_rollback.php @@ -0,0 +1,22 @@ +create(WriterInterface::class); + +$configWriter->delete('carriers/flatrate/active'); +$configWriter->delete('carriers/tablerate/active'); +$configWriter->delete('carriers/freeshipping/active'); +$configWriter->delete('carriers/ups/active'); +$configWriter->delete('carriers/usps/active'); +$configWriter->delete('carriers/fedex/active'); +$configWriter->delete('carriers/dhl/active'); diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight.php new file mode 100644 index 000000000000..40e01a81ac80 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight.php @@ -0,0 +1,29 @@ +get(\Magento\Framework\App\ResourceConnection::class); +$connection = $resource->getConnection(); +$resourceModel = $objectManager->create(\Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate::class); +$entityTable = $resourceModel->getTable('shipping_tablerate'); +$data = + [ + 'website_id' => 1, + 'dest_country_id' => 'US', + 'dest_region_id' => 0, + 'dest_zip' => '*', + 'condition_name' => 'package_weight', + 'condition_value' => 0, + 'price' => 10, + 'cost' => 0 + ]; +$connection->query( + "INSERT INTO {$entityTable} (`website_id`, `dest_country_id`, `dest_region_id`, `dest_zip`, `condition_name`," + . "`condition_value`, `price`, `cost`) VALUES (:website_id, :dest_country_id, :dest_region_id, :dest_zip," + . " :condition_name, :condition_value, :price, :cost);", + $data +); diff --git a/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight_rollback.php b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight_rollback.php new file mode 100644 index 000000000000..cb6e9353b897 --- /dev/null +++ b/dev/tests/integration/testsuite/Magento/OfflineShipping/_files/tablerates_weight_rollback.php @@ -0,0 +1,8 @@ +