Skip to content

Commit c249db5

Browse files
authored
LYNX-626 Mutation setShippingAddressesOnCart throws error when using pickup_location_code
1 parent 7399ea7 commit c249db5

File tree

3 files changed

+275
-10
lines changed

3 files changed

+275
-10
lines changed

InventoryInStorePickupQuoteGraphQl/Model/Cart/GetShippingAddress/AdaptGetShippingAddressPlugin.php

Lines changed: 69 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
<?php
22
/**
3-
* Copyright © Magento, Inc. All rights reserved.
4-
* See COPYING.txt for license details.
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
55
*/
66
declare(strict_types=1);
77

88
namespace Magento\InventoryInStorePickupQuoteGraphQl\Model\Cart\GetShippingAddress;
99

10+
use Magento\Framework\Exception\LocalizedException;
11+
use Magento\Framework\Exception\NoSuchEntityException;
12+
use Magento\Framework\GraphQl\Exception\GraphQlInputException;
1013
use Magento\GraphQl\Model\Query\ContextInterface;
14+
use Magento\Inventory\Model\SourceRepository;
1115
use Magento\Quote\Api\Data\AddressExtensionFactory;
1216
use Magento\Quote\Model\Quote\Address;
1317
use Magento\QuoteGraphQl\Model\Cart\GetShippingAddress;
@@ -18,17 +22,47 @@
1822
class AdaptGetShippingAddressPlugin
1923
{
2024
/**
21-
* @var AddressExtensionFactory
22-
*/
23-
private $addressExtensionFactory;
24-
25-
/**
25+
* AdaptGetShippingAddressPlugin Constructor
26+
*
2627
* @param AddressExtensionFactory $addressExtensionFactory
28+
* @param SourceRepository $sourceRepository
2729
*/
2830
public function __construct(
29-
AddressExtensionFactory $addressExtensionFactory
31+
private readonly AddressExtensionFactory $addressExtensionFactory,
32+
private readonly SourceRepository $sourceRepository
3033
) {
31-
$this->addressExtensionFactory = $addressExtensionFactory;
34+
}
35+
36+
/**
37+
* Set shipping address in quote from pickup_location_code
38+
*
39+
* @param GetShippingAddress $subject
40+
* @param ContextInterface $context
41+
* @param array $shippingAddressInput
42+
* @return array
43+
* @throws GraphQlInputException
44+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
45+
*/
46+
public function beforeExecute(
47+
GetShippingAddress $subject,
48+
ContextInterface $context,
49+
array $shippingAddressInput
50+
): array {
51+
try {
52+
if (!empty($shippingAddressInput['pickup_location_code']) &&
53+
empty($shippingAddressInput['customer_address_id']) &&
54+
empty($shippingAddressInput['address'])
55+
) {
56+
$address = $this->getStoreAddress($shippingAddressInput['pickup_location_code']);
57+
if ($address) {
58+
$shippingAddressInput['address'] = $address;
59+
}
60+
}
61+
} catch (LocalizedException $e) {
62+
throw new GraphQlInputException(__($e->getMessage()));
63+
}
64+
65+
return [$context, $shippingAddressInput];
3266
}
3367

3468
/**
@@ -74,4 +108,30 @@ private function assignPickupLocation(Address $address, array $shippingAddressIn
74108

75109
$extension->setPickupLocationCode($pickupLocationCode);
76110
}
111+
112+
/**
113+
* Get store address
114+
*
115+
* @param string $pickupLocationCode
116+
* @return array
117+
* @throws NoSuchEntityException
118+
*/
119+
private function getStoreAddress(string $pickupLocationCode): array
120+
{
121+
$storeAddress = $this->sourceRepository->get($pickupLocationCode);
122+
if ($storeAddress->getEnabled() && $storeAddress->getIsPickupLocationActive()) {
123+
return [
124+
'firstname' => $storeAddress->getFrontendName(),
125+
'lastname' => 'Store',
126+
'street' => $storeAddress->getStreet(),
127+
'city' => $storeAddress->getCity(),
128+
'region' => $storeAddress->getRegionId(),
129+
'postcode' => $storeAddress->getPostcode(),
130+
'country_code' => $storeAddress->getCountryId(),
131+
'telephone' => $storeAddress->getPhone()
132+
];
133+
}
134+
135+
return [];
136+
}
77137
}

InventoryInStorePickupQuoteGraphQl/composer.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
"magento/framework": "*",
77
"magento/module-quote-graph-ql": "*",
88
"magento/module-quote": "*",
9-
"magento/module-graph-ql": "*"
9+
"magento/module-graph-ql": "*",
10+
"magento/module-inventory": "*"
1011
},
1112
"type": "magento2-module",
1213
"license": [
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\GraphQl\InventoryInStorePickupQuote;
9+
10+
use Magento\Catalog\Test\Fixture\Product as ProductFixture;
11+
use Magento\Framework\Exception\CouldNotSaveException;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Framework\Validation\ValidationException;
15+
use Magento\InventoryApi\Api\SourceRepositoryInterface;
16+
use Magento\InventoryApi\Test\Fixture\SourceItems as SourceItemsFixture;
17+
use Magento\InventoryApi\Test\Fixture\Stock as StockFixture;
18+
use Magento\InventoryApi\Test\Fixture\StockSourceLinks as StockSourceLinksFixture;
19+
use Magento\InventoryInStorePickupApi\Model\GetPickupLocationInterface;
20+
use Magento\InventorySalesApi\Api\Data\SalesChannelInterface;
21+
use Magento\InventorySalesApi\Test\Fixture\StockSalesChannels as StockSalesChannelsFixture;
22+
use Magento\Quote\Test\Fixture\AddProductToCart as AddProductToCartFixture;
23+
use Magento\InventoryApi\Test\Fixture\Source as SourceFixture;
24+
use Magento\Quote\Test\Fixture\GuestCart as GuestCartFixture;
25+
use Magento\Quote\Test\Fixture\QuoteIdMask as QuoteMaskFixture;
26+
use Magento\Store\Model\StoreManagerInterface;
27+
use Magento\TestFramework\Fixture\AppIsolation;
28+
use Magento\TestFramework\Fixture\DataFixture;
29+
use Magento\TestFramework\Fixture\DataFixtureStorage;
30+
use Magento\TestFramework\Fixture\DataFixtureStorageManager;
31+
use Magento\TestFramework\Fixture\DbIsolation;
32+
use Magento\TestFramework\Helper\Bootstrap;
33+
use Magento\TestFramework\TestCase\GraphQlAbstract;
34+
35+
/**
36+
* Test coverage of extension of Quote Graph Ql.
37+
* Test possibility to pass Pickup Location Code to Shipping Address.
38+
*/
39+
class PickupLocationForShippingTest extends GraphQlAbstract
40+
{
41+
/**
42+
* @var GetPickupLocationInterface
43+
*/
44+
private $getPickupLocation;
45+
46+
/**
47+
* @var StoreManagerInterface
48+
*/
49+
private $storeManager;
50+
51+
/**
52+
* @var DataFixtureStorage
53+
*/
54+
private $fixtures;
55+
56+
/**
57+
* @var SourceRepositoryInterface
58+
*/
59+
private $sourceRepository;
60+
61+
public function setUp(): void
62+
{
63+
$this->getPickupLocation = Bootstrap::getObjectManager()->get(GetPickupLocationInterface::class);
64+
$this->storeManager = Bootstrap::getObjectManager()->get(StoreManagerInterface::class)->getStore();
65+
$this->sourceRepository = Bootstrap::getObjectManager()->get(SourceRepositoryInterface::class);
66+
$this->fixtures = Bootstrap::getObjectManager()->get(DataFixtureStorageManager::class)->getStorage();
67+
}
68+
69+
/**
70+
* @throws NoSuchEntityException
71+
* @throws ValidationException
72+
* @throws CouldNotSaveException
73+
* @throws LocalizedException
74+
*/
75+
#[
76+
DbIsolation(false),
77+
AppIsolation(true),
78+
DataFixture(
79+
SourceFixture::class,
80+
[
81+
'latitude'=>38.7634,
82+
'longitude'=>-95.84,
83+
'postcode' => '66413',
84+
'city' => 'Burlingame',
85+
'region' => 'California',
86+
'region_id' => 12,
87+
'street' => 'Bloomquist Dr 100',
88+
'contact_name' => 'Test Store',
89+
'phone' => '9876543210',
90+
'enabled' => 1
91+
],
92+
as: 'src1'
93+
),
94+
DataFixture(StockFixture::class, as: 'stk2'),
95+
DataFixture(
96+
StockSourceLinksFixture::class,
97+
[
98+
['stock_id' => '$stk2.stock_id$', 'source_code' => '$src1.source_code$'],
99+
]
100+
),
101+
DataFixture(StockSalesChannelsFixture::class, ['stock_id' => '$stk2.stock_id$', 'sales_channels' => ['base']]),
102+
DataFixture(ProductFixture::class, as: 'p1'),
103+
DataFixture(
104+
SourceItemsFixture::class,
105+
[
106+
['sku' => '$p1.sku$', 'source_code' => '$src1.source_code$', 'quantity' => 1],
107+
]
108+
),
109+
DataFixture(GuestCartFixture::class, as: 'cart'),
110+
DataFixture(AddProductToCartFixture::class, ['cart_id' => '$cart.id$', 'product_id' => '$p1.id$']),
111+
DataFixture(QuoteMaskFixture::class, ['cart_id' => '$cart.id$'], 'quoteIdMask'),
112+
]
113+
public function testSetPickupLocationForShippingAddress()
114+
{
115+
$source = $this->fixtures->get('src1');
116+
$source->getExtensionAttributes()->setIsPickupLocationActive(1);
117+
$this->sourceRepository->save($source);
118+
$pickupLocationCode = $source->getSourceCode();
119+
120+
$response = $this->graphQlMutation($this->getSetShippingAddressOnCartMutation(
121+
$this->fixtures->get('quoteIdMask')->getMaskedId(),
122+
$pickupLocationCode
123+
));
124+
125+
$this->assertNewShippingAddressFields(
126+
current($response['setShippingAddressesOnCart']['cart']['shipping_addresses']),
127+
$pickupLocationCode
128+
);
129+
}
130+
131+
/**
132+
* Get setShippingAddressOnCart mutation with pickupLocationCode
133+
*
134+
* @param string $cartId
135+
* @param string $pickupLocationCode
136+
* @return string
137+
*/
138+
private function getSetShippingAddressOnCartMutation(string $cartId, string $pickupLocationCode): string
139+
{
140+
return <<<MUTATION
141+
mutation {
142+
setShippingAddressesOnCart(
143+
input: {
144+
cart_id: "{$cartId}"
145+
shipping_addresses: [
146+
{
147+
pickup_location_code: "{$pickupLocationCode}"
148+
}
149+
]
150+
}
151+
) {
152+
cart {
153+
shipping_addresses {
154+
firstname
155+
street
156+
city
157+
postcode
158+
telephone
159+
country {
160+
code
161+
label
162+
},
163+
pickup_location_code,
164+
__typename
165+
}
166+
}
167+
}
168+
}
169+
MUTATION;
170+
}
171+
172+
/**
173+
* @param array $shippingAddressResponse
174+
* @param string $pickupLocationCode
175+
*
176+
* @throws LocalizedException
177+
* @throws NoSuchEntityException
178+
*/
179+
private function assertNewShippingAddressFields(array $shippingAddressResponse, string $pickupLocationCode)
180+
{
181+
$pickupLocation = $this->getPickupLocation->execute(
182+
$pickupLocationCode,
183+
SalesChannelInterface::TYPE_WEBSITE,
184+
$this->storeManager->getWebsite()->getCode()
185+
);
186+
$assertionMap = [
187+
['response_field' => 'firstname', 'expected_value' => $pickupLocation->getName()],
188+
['response_field' => 'street', 'expected_value' => [0 => $pickupLocation->getStreet()]],
189+
['response_field' => 'city', 'expected_value' => $pickupLocation->getCity()],
190+
['response_field' => 'postcode', 'expected_value' => $pickupLocation->getPostcode()],
191+
['response_field' => 'telephone', 'expected_value' => '9876543210'],
192+
[
193+
'response_field' => 'country',
194+
'expected_value' => [
195+
'code' => $pickupLocation->getCountryId(),
196+
'label' => $pickupLocation->getCountryId()
197+
]
198+
],
199+
['response_field' => 'pickup_location_code', 'expected_value' => $pickupLocation->getPickupLocationCode()],
200+
['response_field' => '__typename', 'expected_value' => 'ShippingCartAddress']
201+
];
202+
$this->assertResponseFields($shippingAddressResponse, $assertionMap);
203+
}
204+
}

0 commit comments

Comments
 (0)