Skip to content

Commit a0370f7

Browse files
authored
LYNX-913: [AC-2.4.9] Getting historical orders with out of stock products (#368)
1 parent 2a89d3b commit a0370f7

File tree

2 files changed

+160
-9
lines changed

2 files changed

+160
-9
lines changed

app/code/Magento/SalesGraphQl/Model/Resolver/ProductResolver.php

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77

88
namespace Magento\SalesGraphQl\Model\Resolver;
99

10-
use Magento\Catalog\Model\Product;
1110
use Magento\CatalogGraphQl\Model\ProductDataProvider;
11+
use Magento\Framework\Exception\LocalizedException;
1212
use Magento\Framework\GraphQl\Config\Element\Field;
1313
use Magento\Framework\GraphQl\Query\ResolverInterface;
1414
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
15-
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
15+
use Magento\Sales\Api\Data\OrderItemInterface;
1616

1717
/**
1818
* Fetches the Product data according to the GraphQL schema
@@ -39,14 +39,10 @@ public function resolve(
3939
?array $value = null,
4040
?array $args = null
4141
) {
42-
if (!isset($value['associatedProduct'])) {
43-
throw new GraphQlNoSuchEntityException(
44-
__("This product is currently out of stock or not available.")
45-
);
42+
if (!(($value['model'] ?? null) instanceof OrderItemInterface)) {
43+
throw new LocalizedException(__('"model" value should be specified'));
4644
}
47-
/** @var Product $product */
48-
$product = $value['associatedProduct'];
4945

50-
return $this->productDataProvider->getProductDataById((int)$product->getId());
46+
return $this->productDataProvider->getProductDataById((int)$value['model']->getProductId());
5147
}
5248
}
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
<?php
2+
/**
3+
* Copyright 2025 Adobe
4+
* All Rights Reserved.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\GraphQl\Sales;
9+
10+
use Exception;
11+
use Magento\Catalog\Api\Data\ProductInterface;
12+
use Magento\Catalog\Test\Fixture\Product as ProductFixture;
13+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
14+
use Magento\CatalogInventory\Api\StockRegistryInterface;
15+
use Magento\Checkout\Test\Fixture\PlaceOrder as PlaceOrderFixture;
16+
use Magento\Checkout\Test\Fixture\SetBillingAddress as SetBillingAddressFixture;
17+
use Magento\Checkout\Test\Fixture\SetDeliveryMethod as SetDeliveryMethodFixture;
18+
use Magento\Checkout\Test\Fixture\SetPaymentMethod as SetPaymentMethodFixture;
19+
use Magento\Checkout\Test\Fixture\SetShippingAddress as SetShippingAddressFixture;
20+
use Magento\Customer\Test\Fixture\Customer as CustomerFixture;
21+
use Magento\Integration\Api\CustomerTokenServiceInterface;
22+
use Magento\Quote\Test\Fixture\AddProductToCart as AddProductToCartFixture;
23+
use Magento\Quote\Test\Fixture\CustomerCart as CustomerCartFixture;
24+
use Magento\TestFramework\Fixture\DataFixture;
25+
use Magento\TestFramework\Fixture\DataFixtureStorage;
26+
use Magento\TestFramework\Fixture\DataFixtureStorageManager;
27+
use Magento\TestFramework\Helper\Bootstrap;
28+
use Magento\TestFramework\TestCase\GraphQlAbstract;
29+
30+
class CustomerOrderItemProductTest extends GraphQlAbstract
31+
{
32+
/**
33+
* @var CustomerTokenServiceInterface
34+
*/
35+
private $customerTokenService;
36+
37+
/**
38+
* @var DataFixtureStorage
39+
*/
40+
private $fixtures;
41+
42+
/**
43+
* @var StockRegistryInterface
44+
*/
45+
private $stockRegistry;
46+
47+
protected function setUp(): void
48+
{
49+
$this->customerTokenService = Bootstrap::getObjectManager()->get(CustomerTokenServiceInterface::class);
50+
$this->fixtures = Bootstrap::getObjectManager()->get(DataFixtureStorageManager::class)->getStorage();
51+
$this->stockRegistry = Bootstrap::getObjectManager()->get(StockRegistryInterface::class);
52+
}
53+
54+
#[
55+
DataFixture(ProductFixture::class, as: 'product'),
56+
DataFixture(CustomerFixture::class, as: 'customer'),
57+
DataFixture(
58+
CustomerCartFixture::class,
59+
['customer_id' => '$customer.id$', 'reserved_order_id' => 'test_order_with_simple_product'],
60+
as: 'cart'
61+
),
62+
DataFixture(AddProductToCartFixture::class, ['cart_id' => '$cart.id$', 'product_id' => '$product.id$']),
63+
DataFixture(SetBillingAddressFixture::class, ['cart_id' => '$cart.id$']),
64+
DataFixture(SetShippingAddressFixture::class, ['cart_id' => '$cart.id$']),
65+
DataFixture(SetDeliveryMethodFixture::class, ['cart_id' => '$cart.id$']),
66+
DataFixture(SetPaymentMethodFixture::class, ['cart_id' => '$cart.id$']),
67+
DataFixture(PlaceOrderFixture::class, ['cart_id' => '$cart.id$'], 'order')
68+
]
69+
public function testOrderItemProductWhenOutOfStock(): void
70+
{
71+
$this->updateProductStock();
72+
73+
$this->assertEquals(
74+
[
75+
'customer' => [
76+
'orders' => [
77+
'items' => [
78+
[
79+
'number' => $this->fixtures->get('order')->getIncrementId(),
80+
'items' => [
81+
[
82+
'product' => [
83+
'sku' => $this->fixtures->get('product')->getSku(),
84+
'stock_status' => 'OUT_OF_STOCK'
85+
]
86+
]
87+
]
88+
]
89+
]
90+
]
91+
]
92+
],
93+
$this->graphQlQuery(
94+
$this->getCustomerOrdersQuery(),
95+
[],
96+
'',
97+
$this->getCustomerAuthHeaders($this->fixtures->get('customer')->getEmail())
98+
)
99+
);
100+
}
101+
102+
/**
103+
* Update product stock to out of stock
104+
*
105+
* @throws Exception
106+
*/
107+
private function updateProductStock(): void
108+
{
109+
/** @var ProductInterface $product */
110+
$product = $this->fixtures->get('product');
111+
$stockItem = $this->stockRegistry->getStockItem($product->getId());
112+
$stockItem->setData(StockItemInterface::IS_IN_STOCK, false);
113+
$stockItem->setData(StockItemInterface::QTY, 0);
114+
$stockItem->setData(StockItemInterface::MANAGE_STOCK, true);
115+
$stockItem->save();
116+
}
117+
118+
/**
119+
* Returns the GraphQL query to fetch customer orders.
120+
*
121+
* @return string
122+
*/
123+
private function getCustomerOrdersQuery(): string
124+
{
125+
return <<<QUERY
126+
query {
127+
customer {
128+
orders {
129+
items {
130+
number
131+
items {
132+
product {
133+
sku
134+
stock_status
135+
}
136+
}
137+
}
138+
}
139+
}
140+
}
141+
QUERY;
142+
}
143+
144+
/**
145+
* Returns the header with customer token for GQL Mutation
146+
*
147+
* @param string $email
148+
* @return array
149+
*/
150+
private function getCustomerAuthHeaders(string $email): array
151+
{
152+
$customerToken = $this->customerTokenService->createCustomerAccessToken($email, 'password');
153+
return ['Authorization' => 'Bearer ' . $customerToken];
154+
}
155+
}

0 commit comments

Comments
 (0)