Skip to content

Commit 5b7b239

Browse files
committed
Provide available shipping rates for addresses
1 parent 8dfe26a commit 5b7b239

File tree

4 files changed

+140
-6
lines changed

4 files changed

+140
-6
lines changed

app/code/Magento/QuoteGraphQl/Model/Cart/Address/AddressDataProvider.php

Lines changed: 51 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
use Magento\Framework\Api\ExtensibleDataObjectConverter;
1111
use Magento\Quote\Api\Data\AddressInterface;
1212
use Magento\Quote\Api\Data\CartInterface;
13+
use Magento\Quote\Api\Data\ShippingMethodInterface;
1314
use Magento\Quote\Model\Quote\Address as QuoteAddress;
15+
use Magento\Quote\Model\Cart\ShippingMethodConverter;
1416

1517
/**
1618
* Class AddressDataProvider
@@ -24,24 +26,33 @@ class AddressDataProvider
2426
*/
2527
private $dataObjectConverter;
2628

29+
/**
30+
* @var ShippingMethodConverter
31+
*/
32+
private $shippingMethodConverter;
33+
2734
/**
2835
* AddressDataProvider constructor.
2936
*
3037
* @param ExtensibleDataObjectConverter $dataObjectConverter
38+
* @param ShippingMethodConverter $shippingMethodConverter
3139
*/
3240
public function __construct(
33-
ExtensibleDataObjectConverter $dataObjectConverter
41+
ExtensibleDataObjectConverter $dataObjectConverter,
42+
ShippingMethodConverter $shippingMethodConverter
3443
) {
3544
$this->dataObjectConverter = $dataObjectConverter;
45+
$this->shippingMethodConverter = $shippingMethodConverter;
3646
}
3747

3848
/**
3949
* Collect and return information about shipping and billing addresses
4050
*
4151
* @param CartInterface $cart
52+
* @param bool $includeShippingMethods
4253
* @return array
4354
*/
44-
public function getCartAddresses(CartInterface $cart): array
55+
public function getCartAddresses(CartInterface $cart, $includeShippingMethods = false): array
4556
{
4657
$addressData = [];
4758
$shippingAddress = $cart->getShippingAddress();
@@ -50,6 +61,12 @@ public function getCartAddresses(CartInterface $cart): array
5061
if ($shippingAddress) {
5162
$shippingData = $this->dataObjectConverter->toFlatArray($shippingAddress, [], AddressInterface::class);
5263
$shippingData['address_type'] = 'SHIPPING';
64+
if ($includeShippingMethods) {
65+
$shippingData['available_shipping_methods'] = $this->extractAvailableShippingRateData(
66+
$cart,
67+
$shippingAddress
68+
);
69+
}
5370
$addressData[] = array_merge($shippingData, $this->extractAddressData($shippingAddress));
5471
}
5572

@@ -84,11 +101,42 @@ private function extractAddressData(QuoteAddress $address): array
84101
'code' => $address->getShippingMethod(),
85102
'label' => $address->getShippingDescription(),
86103
'free_shipping' => $address->getFreeShipping(),
104+
'amount' => $address->getShippingAmount(),
105+
'base_amount' => $address->getBaseShippingAmount(),
106+
'amount_incl_tax' => $address->getShippingInclTax(),
107+
'base_amount_incl_tax' => $address->getBaseShippingInclTax(),
87108
],
88109
'items_weight' => $address->getWeight(),
89-
'customer_notes' => $address->getCustomerNotes()
110+
'customer_notes' => $address->getCustomerNotes(),
111+
'quote_id' => $address->getQuoteId(),
90112
];
91113

92114
return $addressData;
93115
}
116+
117+
private function extractAvailableShippingRateData(CartInterface $cart, QuoteAddress $address): array
118+
{
119+
$output = [];
120+
121+
// Allow shipping rates by setting country id for new addresses
122+
if (!$address->getCountryId() && $address->getCountryCode()) {
123+
$address->setCountryId($address->getCountryCode());
124+
}
125+
126+
$address->setCollectShippingRates(true);
127+
$address->collectShippingRates();
128+
129+
$shippingRates = $address->getGroupedAllShippingRates();
130+
foreach ($shippingRates as $carrierRates) {
131+
foreach ($carrierRates as $rate) {
132+
$output[] = $this->dataObjectConverter->toFlatArray(
133+
$this->shippingMethodConverter->modelToDataObject($rate, $cart->getQuoteCurrencyCode()),
134+
[],
135+
ShippingMethodInterface::class
136+
);
137+
}
138+
}
139+
140+
return $output;
141+
}
94142
}

app/code/Magento/QuoteGraphQl/Model/Resolver/CartAddresses.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
4343

4444
$cart = $value['model'];
4545

46-
return $this->addressDataProvider->getCartAddresses($cart);
46+
return $this->addressDataProvider->getCartAddresses($cart, $this->includeShippingMethods($info));
47+
}
48+
49+
private function includeShippingMethods(ResolveInfo $info): bool
50+
{
51+
return $info->getFieldSelection()['available_shipping_methods'] ?? false;
4752
}
4853
}

app/code/Magento/QuoteGraphQl/etc/schema.graphqls

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ type CartAddress {
112112
telephone: String
113113
address_type: AdressTypeEnum
114114
selected_shipping_method: CheckoutShippingMethod
115-
available_shipping_methods: [CheckoutShippingMethod]
115+
available_shipping_methods: [CheckoutAvailableShippingMethod]
116116
items_weight: Float
117117
customer_notes: String
118118
cart_items: [CartItemQuantity]
@@ -138,7 +138,23 @@ type CheckoutShippingMethod {
138138
label: String
139139
free_shipping: Boolean!
140140
error_message: String
141-
# TODO: Add more complex structure for shipping rates
141+
amount: Float!
142+
base_amount: Float!
143+
amount_incl_tax: Float!
144+
base_amount_incl_tax: Float!
145+
}
146+
147+
type CheckoutAvailableShippingMethod {
148+
carrier_code: String!
149+
carrier_title: String!
150+
method_code: String!
151+
method_title: String!
152+
error_message: String
153+
amount: Float!
154+
base_amount: Float!
155+
price_excl_tax: Float!
156+
price_incl_tax: Float!
157+
available: Boolean!
142158
}
143159

144160
enum AdressTypeEnum {

dev/tests/api-functional/testsuite/Magento/GraphQl/Quote/SetShippingAddressOnCartTest.php

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,18 @@ public function testSetNewGuestShippingAddressOnCart()
8787
city
8888
postcode
8989
telephone
90+
available_shipping_methods {
91+
amount
92+
available
93+
base_amount
94+
carrier_code
95+
carrier_title
96+
error_message
97+
method_code
98+
method_title
99+
price_excl_tax
100+
price_incl_tax
101+
}
90102
}
91103
}
92104
}
@@ -99,6 +111,7 @@ public function testSetNewGuestShippingAddressOnCart()
99111
self::assertArrayHasKey('addresses', $cartResponse);
100112
$shippingAddressResponse = current($cartResponse['addresses']);
101113
$this->assertNewShippingAddressFields($shippingAddressResponse);
114+
$this->assertAvailableShippingRates($shippingAddressResponse);
102115
}
103116

104117
/**
@@ -340,6 +353,18 @@ public function testSetNewRegisteredCustomerShippingAddressOnCart()
340353
city
341354
postcode
342355
telephone
356+
available_shipping_methods {
357+
amount
358+
available
359+
base_amount
360+
carrier_code
361+
carrier_title
362+
error_message
363+
method_code
364+
method_title
365+
price_excl_tax
366+
price_incl_tax
367+
}
343368
}
344369
}
345370
}
@@ -352,6 +377,7 @@ public function testSetNewRegisteredCustomerShippingAddressOnCart()
352377
self::assertArrayHasKey('addresses', $cartResponse);
353378
$shippingAddressResponse = current($cartResponse['addresses']);
354379
$this->assertNewShippingAddressFields($shippingAddressResponse);
380+
$this->assertAvailableShippingRates($shippingAddressResponse);
355381
}
356382

357383
/**
@@ -398,6 +424,18 @@ public function testSetSavedRegisteredCustomerShippingAddressOnCart()
398424
city
399425
postcode
400426
telephone
427+
available_shipping_methods {
428+
amount
429+
available
430+
base_amount
431+
carrier_code
432+
carrier_title
433+
error_message
434+
method_code
435+
method_title
436+
price_excl_tax
437+
price_incl_tax
438+
}
401439
}
402440
}
403441
}
@@ -410,6 +448,7 @@ public function testSetSavedRegisteredCustomerShippingAddressOnCart()
410448
self::assertArrayHasKey('addresses', $cartResponse);
411449
$shippingAddressResponse = current($cartResponse['addresses']);
412450
$this->assertSavedShippingAddressFields($shippingAddressResponse);
451+
$this->assertAvailableShippingRates($shippingAddressResponse);
413452
}
414453

415454
/**
@@ -452,6 +491,32 @@ private function assertSavedShippingAddressFields(array $shippingAddressResponse
452491
$this->assertResponseFields($shippingAddressResponse, $assertionMap);
453492
}
454493

494+
/**
495+
* Verify the expected shipping method is available
496+
*
497+
* @param array $shippingAddressResponse
498+
*/
499+
private function assertAvailableShippingRates(array $shippingAddressResponse): void
500+
{
501+
$this->assertArrayHasKey('available_shipping_methods', $shippingAddressResponse);
502+
$rate = current($shippingAddressResponse['available_shipping_methods']);
503+
504+
$assertionMap = [
505+
['response_field' => 'amount', 'expected_value' => 5],
506+
['response_field' => 'available', 'expected_value' => true],
507+
['response_field' => 'base_amount', 'expected_value' => 5],
508+
['response_field' => 'carrier_code', 'expected_value' => 'flatrate'],
509+
['response_field' => 'carrier_title', 'expected_value' => 'Flat Rate'],
510+
['response_field' => 'error_message', 'expected_value' => ''],
511+
['response_field' => 'method_code', 'expected_value' => 'flatrate'],
512+
['response_field' => 'method_title', 'expected_value' => 'Fixed'],
513+
['response_field' => 'price_incl_tax', 'expected_value' => 5],
514+
['response_field' => 'price_excl_tax', 'expected_value' => 5],
515+
];
516+
517+
$this->assertResponseFields($rate, $assertionMap);
518+
}
519+
455520
/**
456521
* @param string $username
457522
* @return array

0 commit comments

Comments
 (0)