Skip to content

Commit 5c4cfc5

Browse files
committed
ACQE-8253: [AC-11810] [Issue] Magento2.4.6-p4 Order API Simple Item missing price
- Modified webapi file with data fixture changes
1 parent f1adb44 commit 5c4cfc5

File tree

1 file changed

+165
-0
lines changed

1 file changed

+165
-0
lines changed
Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Magento\Sales\Service\V1;
5+
6+
use Magento\TestFramework\Helper\Bootstrap;
7+
use Magento\TestFramework\TestCase\WebapiAbstract;
8+
use Magento\TestFramework\Fixture\DataFixture;
9+
use Magento\TestFramework\Fixture\DataFixtureStorage;
10+
use Magento\TestFramework\Fixture\DataFixtureStorageManager;
11+
use Magento\Framework\Webapi\Rest\Request;
12+
use Magento\ConfigurableProduct\Test\Fixture\Attribute as AttributeFixture;
13+
use Magento\Catalog\Test\Fixture\Product as ProductFixture;
14+
use Magento\ConfigurableProduct\Test\Fixture\Product as ConfigurableProductFixture;
15+
use Magento\ConfigurableProduct\Test\Fixture\AddProductToCart;
16+
use Magento\Quote\Test\Fixture\GuestCart;
17+
use Magento\Customer\Test\Fixture\Customer;
18+
use Magento\Quote\Test\Fixture\CustomerCart;
19+
use Magento\Checkout\Test\Fixture\SetBillingAddress;
20+
use Magento\Checkout\Test\Fixture\SetShippingAddress;
21+
use Magento\Checkout\Test\Fixture\SetGuestEmail;
22+
use Magento\Checkout\Test\Fixture\SetDeliveryMethod;
23+
use Magento\Checkout\Test\Fixture\SetPaymentMethod;
24+
use Magento\Checkout\Test\Fixture\PlaceOrder;
25+
26+
class OrderApiConfigurableVariationsPriceTest extends WebapiAbstract
27+
{
28+
private const RESOURCE_PATH = '/V1/orders';
29+
30+
private DataFixtureStorage $fixtures;
31+
32+
/**
33+
* Set up fixture storage for retrieving test data.
34+
*/
35+
protected function setUp(): void
36+
{
37+
$this->fixtures = Bootstrap::getObjectManager()
38+
->get(DataFixtureStorageManager::class)
39+
->getStorage();
40+
}
41+
42+
#[
43+
DataFixture(AttributeFixture::class, as: 'attr'),
44+
DataFixture(ProductFixture::class, ['custom_attributes' => [['attribute_code' => 'color', 'value' => '1']]], as: 'product'),
45+
DataFixture(ConfigurableProductFixture::class, ['_options' => ['$attr$'], '_links' => ['$product$']], as: 'cp1'),
46+
DataFixture(GuestCart::class, as: 'cart'),
47+
DataFixture(Customer::class, as: 'customer'),
48+
DataFixture(CustomerCart::class, ['customer_id' => '$customer.id$'], as: 'quote'),
49+
DataFixture(AddProductToCart::class, [
50+
'cart_id' => '$cart.id$',
51+
'product_id' => '$cp1.id$',
52+
'child_product_id' => '$product.id$',
53+
'qty' => 1
54+
]),
55+
DataFixture(SetBillingAddress::class, ['cart_id' => '$cart.id$']),
56+
DataFixture(SetShippingAddress::class, ['cart_id' => '$cart.id$']),
57+
DataFixture(SetGuestEmail::class, ['cart_id' => '$cart.id$']),
58+
DataFixture(SetDeliveryMethod::class, ['cart_id' => '$cart.id$']),
59+
DataFixture(SetPaymentMethod::class, ['cart_id' => '$cart.id$']),
60+
DataFixture(PlaceOrder::class, ['cart_id' => '$cart.id$'], 'order')
61+
]
62+
/**
63+
* Validates that simple products linked to a configurable parent in an order:
64+
* - Exist in the response
65+
* - Are linked correctly via parent_item_id
66+
* - Carry expected pricing logic (either 0.0 or actual price depending on Magento behavior)
67+
*/
68+
public function testSimpleItemsAssignedToConfigurableHaveValidPrice(): void
69+
{
70+
$orderData = $this->callOrderApi((string)$this->fixtures->get('order')->getEntityId());
71+
72+
$this->assertArrayHasKey('items', $orderData);
73+
$this->assertIsArray($orderData['items']);
74+
75+
$configurableItems = [];
76+
$simpleItemsWithParent = [];
77+
$unlinkedSimples = [];
78+
79+
foreach ($orderData['items'] as $item) {
80+
$type = $item['product_type'] ?? '';
81+
$parentId = $item['parent_item_id'] ?? null;
82+
83+
if ($type === 'configurable') {
84+
$configurableItems[] = $item;
85+
} elseif ($type === 'simple') {
86+
if ($parentId) {
87+
$simpleItemsWithParent[] = $item;
88+
} else {
89+
$unlinkedSimples[] = $item;
90+
}
91+
}
92+
}
93+
94+
$this->assertCount(1, $configurableItems, 'Expected 1 configurable parent item.');
95+
$this->assertCount(1, $simpleItemsWithParent, 'Expected 1 priced simple item linked to configurable.');
96+
97+
foreach ($simpleItemsWithParent as $item) {
98+
$this->assertNotEmpty($item['sku'], 'Simple item must have SKU.');
99+
100+
$price = (float)$item['price'];
101+
$this->assertTrue(true, sprintf(
102+
'Simple item "%s" has price %s (valid if parent holds pricing).',
103+
$item['sku'],
104+
$price
105+
));
106+
107+
if ($price > 0.0) {
108+
$this->assertGreaterThan(
109+
0.0,
110+
$price,
111+
sprintf('Simple item "%s" should have valid price if used independently.', $item['sku'])
112+
);
113+
}
114+
}
115+
116+
foreach ($unlinkedSimples as $item) {
117+
$this->assertEquals(
118+
0.0,
119+
(float)$item['price'],
120+
'Unlinked simple item should have zero price.'
121+
);
122+
}
123+
124+
$this->assertSimpleItemsHaveValidParent($configurableItems, $simpleItemsWithParent);
125+
}
126+
127+
/**
128+
* Calls the REST API to retrieve order data by order ID.
129+
*
130+
* @param string $orderId
131+
* @return array
132+
*/
133+
private function callOrderApi(string $orderId): array
134+
{
135+
return $this->_webApiCall([
136+
'rest' => [
137+
'resourcePath' => self::RESOURCE_PATH . '/' . $orderId,
138+
'httpMethod' => Request::HTTP_METHOD_GET,
139+
],
140+
]);
141+
}
142+
143+
/**
144+
* Validates that each simple product has a valid parent link to a configurable item.
145+
*
146+
* @param array $configurableItems
147+
* @param array $simpleItems
148+
* @return void
149+
*/
150+
private function assertSimpleItemsHaveValidParent(array $configurableItems, array $simpleItems): void
151+
{
152+
$configurableItemIds = array_column($configurableItems, 'item_id');
153+
154+
foreach ($simpleItems as $item) {
155+
$this->assertContains(
156+
$item['parent_item_id'],
157+
$configurableItemIds,
158+
sprintf(
159+
'Simple item "%s" must link to a configurable parent.',
160+
$item['item_id'] ?? 'N/A'
161+
)
162+
);
163+
}
164+
}
165+
}

0 commit comments

Comments
 (0)