Skip to content

Commit deb8bfa

Browse files
author
Valeriy Naida
authored
ENGCOM-3456: Setting shipping method for shopping cart (single address shipping) #211
2 parents 5f976fa + b97a008 commit deb8bfa

File tree

6 files changed

+462
-1
lines changed

6 files changed

+462
-1
lines changed
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Model\Cart\Address;
9+
10+
use Magento\Framework\Api\ExtensibleDataObjectConverter;
11+
use Magento\Quote\Api\Data\AddressInterface;
12+
use Magento\Quote\Api\Data\CartInterface;
13+
use Magento\Quote\Model\Quote\Address as QuoteAddress;
14+
15+
/**
16+
* Class AddressDataProvider
17+
*
18+
* Collect and return information about cart shipping and billing addresses
19+
*/
20+
class AddressDataProvider
21+
{
22+
/**
23+
* @var ExtensibleDataObjectConverter
24+
*/
25+
private $dataObjectConverter;
26+
27+
/**
28+
* AddressDataProvider constructor.
29+
*
30+
* @param ExtensibleDataObjectConverter $dataObjectConverter
31+
*/
32+
public function __construct(
33+
ExtensibleDataObjectConverter $dataObjectConverter
34+
) {
35+
$this->dataObjectConverter = $dataObjectConverter;
36+
}
37+
38+
/**
39+
* Collect and return information about shipping and billing addresses
40+
*
41+
* @param CartInterface $cart
42+
* @return array
43+
*/
44+
public function getCartAddresses(CartInterface $cart): array
45+
{
46+
$addressData = [];
47+
$shippingAddress = $cart->getShippingAddress();
48+
$billingAddress = $cart->getBillingAddress();
49+
50+
if ($shippingAddress) {
51+
$shippingData = $this->dataObjectConverter->toFlatArray($shippingAddress, [], AddressInterface::class);
52+
$shippingData['address_type'] = 'SHIPPING';
53+
$addressData[] = array_merge($shippingData, $this->extractAddressData($shippingAddress));
54+
}
55+
56+
if ($billingAddress) {
57+
$billingData = $this->dataObjectConverter->toFlatArray($billingAddress, [], AddressInterface::class);
58+
$billingData['address_type'] = 'BILLING';
59+
$addressData[] = array_merge($billingData, $this->extractAddressData($billingAddress));
60+
}
61+
62+
return $addressData;
63+
}
64+
65+
/**
66+
* Extract the necessary address fields from address model
67+
*
68+
* @param QuoteAddress $address
69+
* @return array
70+
*/
71+
private function extractAddressData(QuoteAddress $address): array
72+
{
73+
$addressData = [
74+
'country' => [
75+
'code' => $address->getCountryId(),
76+
'label' => $address->getCountry()
77+
],
78+
'region' => [
79+
'code' => $address->getRegionCode(),
80+
'label' => $address->getRegion()
81+
],
82+
'street' => $address->getStreet(),
83+
'selected_shipping_method' => [
84+
'code' => $address->getShippingMethod(),
85+
'label' => $address->getShippingDescription(),
86+
'free_shipping' => $address->getFreeShipping(),
87+
],
88+
'items_weight' => $address->getWeight(),
89+
'customer_notes' => $address->getCustomerNotes()
90+
];
91+
92+
return $addressData;
93+
}
94+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Model\Cart;
9+
10+
use Magento\Framework\Exception\InputException;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Framework\Exception\StateException;
13+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
14+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
15+
use Magento\Quote\Model\Quote;
16+
use Magento\Quote\Model\Quote\AddressFactory as QuoteAddressFactory;
17+
use Magento\Quote\Model\ResourceModel\Quote\Address as QuoteAddressResource;
18+
use Magento\Checkout\Model\ShippingInformationFactory;
19+
use Magento\Checkout\Api\ShippingInformationManagementInterface;
20+
use Magento\Checkout\Model\ShippingInformation;
21+
22+
/**
23+
* Class SetShippingMethodsOnCart
24+
*
25+
* Set shipping method for a specified shopping cart address
26+
*/
27+
class SetShippingMethodOnCart
28+
{
29+
/**
30+
* @var ShippingInformationFactory
31+
*/
32+
private $shippingInformationFactory;
33+
34+
/**
35+
* @var QuoteAddressFactory
36+
*/
37+
private $quoteAddressFactory;
38+
39+
/**
40+
* @var QuoteAddressResource
41+
*/
42+
private $quoteAddressResource;
43+
44+
/**
45+
* @var ShippingInformationManagementInterface
46+
*/
47+
private $shippingInformationManagement;
48+
49+
/**
50+
* @param ShippingInformationManagementInterface $shippingInformationManagement
51+
* @param QuoteAddressFactory $quoteAddressFactory
52+
* @param QuoteAddressResource $quoteAddressResource
53+
* @param ShippingInformationFactory $shippingInformationFactory
54+
*/
55+
public function __construct(
56+
ShippingInformationManagementInterface $shippingInformationManagement,
57+
QuoteAddressFactory $quoteAddressFactory,
58+
QuoteAddressResource $quoteAddressResource,
59+
ShippingInformationFactory $shippingInformationFactory
60+
) {
61+
$this->shippingInformationManagement = $shippingInformationManagement;
62+
$this->quoteAddressResource = $quoteAddressResource;
63+
$this->quoteAddressFactory = $quoteAddressFactory;
64+
$this->shippingInformationFactory = $shippingInformationFactory;
65+
}
66+
67+
/**
68+
* Sets shipping method for a specified shopping cart address
69+
*
70+
* @param Quote $cart
71+
* @param int $cartAddressId
72+
* @param string $carrierCode
73+
* @param string $methodCode
74+
* @throws GraphQlInputException
75+
* @throws GraphQlNoSuchEntityException
76+
*/
77+
public function execute(Quote $cart, int $cartAddressId, string $carrierCode, string $methodCode): void
78+
{
79+
$quoteAddress = $this->quoteAddressFactory->create();
80+
$this->quoteAddressResource->load($quoteAddress, $cartAddressId);
81+
82+
/** @var ShippingInformation $shippingInformation */
83+
$shippingInformation = $this->shippingInformationFactory->create();
84+
85+
/* If the address is not a shipping address (but billing) the system will find the proper shipping address for
86+
the selected cart and set the information there (actual for single shipping address) */
87+
$shippingInformation->setShippingAddress($quoteAddress);
88+
$shippingInformation->setShippingCarrierCode($carrierCode);
89+
$shippingInformation->setShippingMethodCode($methodCode);
90+
91+
try {
92+
$this->shippingInformationManagement->saveAddressInformation($cart->getId(), $shippingInformation);
93+
} catch (NoSuchEntityException $exception) {
94+
throw new GraphQlNoSuchEntityException(__($exception->getMessage()));
95+
} catch (StateException $exception) {
96+
throw new GraphQlInputException(__($exception->getMessage()));
97+
} catch (InputException $exception) {
98+
throw new GraphQlInputException(__($exception->getMessage()));
99+
}
100+
}
101+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\Exception\LocalizedException;
11+
use Magento\Framework\GraphQl\Config\Element\Field;
12+
use Magento\Framework\GraphQl\Query\ResolverInterface;
13+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
14+
use Magento\QuoteGraphQl\Model\Cart\Address\AddressDataProvider;
15+
16+
/**
17+
* @inheritdoc
18+
*/
19+
class CartAddresses implements ResolverInterface
20+
{
21+
/**
22+
* @var AddressDataProvider
23+
*/
24+
private $addressDataProvider;
25+
26+
/**
27+
* @param AddressDataProvider $addressDataProvider
28+
*/
29+
public function __construct(
30+
AddressDataProvider $addressDataProvider
31+
) {
32+
$this->addressDataProvider = $addressDataProvider;
33+
}
34+
35+
/**
36+
* @inheritdoc
37+
*/
38+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
39+
{
40+
if (!isset($value['model'])) {
41+
throw new LocalizedException(__('"model" value should be specified'));
42+
}
43+
44+
$cart = $value['model'];
45+
46+
return $this->addressDataProvider->getCartAddresses($cart);
47+
}
48+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\QuoteGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
11+
use Magento\Framework\GraphQl\Query\ResolverInterface;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
14+
use Magento\Framework\Stdlib\ArrayManager;
15+
use Magento\QuoteGraphQl\Model\Cart\GetCartForUser;
16+
use Magento\QuoteGraphQl\Model\Cart\SetShippingMethodOnCart;
17+
18+
/**
19+
* Class SetShippingMethodsOnCart
20+
*
21+
* Mutation resolver for setting shipping methods for shopping cart
22+
*/
23+
class SetShippingMethodsOnCart implements ResolverInterface
24+
{
25+
/**
26+
* @var SetShippingMethodOnCart
27+
*/
28+
private $setShippingMethodOnCart;
29+
30+
/**
31+
* @var ArrayManager
32+
*/
33+
private $arrayManager;
34+
35+
/**
36+
* @var GetCartForUser
37+
*/
38+
private $getCartForUser;
39+
40+
/**
41+
* @param ArrayManager $arrayManager
42+
* @param GetCartForUser $getCartForUser
43+
* @param SetShippingMethodOnCart $setShippingMethodOnCart
44+
*/
45+
public function __construct(
46+
ArrayManager $arrayManager,
47+
GetCartForUser $getCartForUser,
48+
SetShippingMethodOnCart $setShippingMethodOnCart
49+
) {
50+
$this->arrayManager = $arrayManager;
51+
$this->getCartForUser = $getCartForUser;
52+
$this->setShippingMethodOnCart = $setShippingMethodOnCart;
53+
}
54+
55+
/**
56+
* @inheritdoc
57+
*/
58+
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
59+
{
60+
$shippingMethods = $this->arrayManager->get('input/shipping_methods', $args);
61+
$maskedCartId = $this->arrayManager->get('input/cart_id', $args);
62+
63+
if (!$maskedCartId) {
64+
throw new GraphQlInputException(__('Required parameter "cart_id" is missing'));
65+
}
66+
if (!$shippingMethods) {
67+
throw new GraphQlInputException(__('Required parameter "shipping_methods" is missing'));
68+
}
69+
70+
$shippingMethod = reset($shippingMethods); // This point can be extended for multishipping
71+
72+
if (!$shippingMethod['cart_address_id']) {
73+
throw new GraphQlInputException(__('Required parameter "cart_address_id" is missing'));
74+
}
75+
if (!$shippingMethod['shipping_carrier_code']) {
76+
throw new GraphQlInputException(__('Required parameter "shipping_carrier_code" is missing'));
77+
}
78+
if (!$shippingMethod['shipping_method_code']) {
79+
throw new GraphQlInputException(__('Required parameter "shipping_method_code" is missing'));
80+
}
81+
82+
$userId = $context->getUserId();
83+
$cart = $this->getCartForUser->execute((string) $maskedCartId, $userId);
84+
85+
$this->setShippingMethodOnCart->execute(
86+
$cart,
87+
$shippingMethod['cart_address_id'],
88+
$shippingMethod['shipping_carrier_code'],
89+
$shippingMethod['shipping_method_code']
90+
);
91+
92+
return [
93+
'cart' => [
94+
'cart_id' => $maskedCartId,
95+
'model' => $cart
96+
]
97+
];
98+
}
99+
}

app/code/Magento/QuoteGraphQl/composer.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
"php": "~7.1.3||~7.2.0",
77
"magento/framework": "*",
88
"magento/module-quote": "*",
9+
"magento/module-checkout": "*",
910
"magento/module-catalog": "*",
1011
"magento/module-store": "*"
1112
},

0 commit comments

Comments
 (0)