Skip to content

Commit 9942a74

Browse files
ENGCOM-8490: Allow customer to specify associated product qtys when adding grouped product to cart via RESTful API #27845
2 parents 7b2341e + b63124a commit 9942a74

File tree

6 files changed

+415
-14
lines changed

6 files changed

+415
-14
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
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\GroupedProduct\Api\Data;
9+
10+
use Magento\Framework\Api\ExtensibleDataInterface;
11+
12+
/**
13+
* Represents `product item id with qty` of a grouped product.
14+
*/
15+
interface GroupedOptionsInterface extends ExtensibleDataInterface
16+
{
17+
/**
18+
* Get associated product id
19+
*
20+
* @return int|null
21+
*/
22+
public function getId(): ?int;
23+
24+
/**
25+
* Get associated product qty
26+
*
27+
* @return int|null
28+
*/
29+
public function getQty(): ?int;
30+
31+
/**
32+
* Set extension attributes
33+
*
34+
* @param \Magento\GroupedProduct\Api\Data\GroupedOptionsExtensionInterface $extensionAttributes
35+
* @return void
36+
*/
37+
public function setExtensionAttributes(GroupedOptionsExtensionInterface $extensionAttributes): void;
38+
39+
/**
40+
* Get extension attributes
41+
*
42+
* @return \Magento\GroupedProduct\Api\Data\GroupedOptionsExtensionInterface|null
43+
*/
44+
public function getExtensionAttributes(): ?GroupedOptionsExtensionInterface;
45+
}
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
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\GroupedProduct\Model\Quote\Item;
9+
10+
use Magento\Framework\DataObject;
11+
use Magento\Framework\DataObject\Factory as ObjectFactory;
12+
use Magento\Framework\Exception\LocalizedException;
13+
use Magento\GroupedProduct\Api\Data\GroupedOptionsInterface;
14+
use Magento\GroupedProduct\Model\Product\Type\Grouped;
15+
use Magento\Quote\Api\Data as QuoteApi;
16+
use Magento\Quote\Api\Data\CartItemInterface;
17+
use Magento\Quote\Model\Quote\Item\CartItemProcessorInterface;
18+
19+
/**
20+
* Converts grouped_options to super_group for the grouped product.
21+
*/
22+
class CartItemProcessor implements CartItemProcessorInterface
23+
{
24+
private const SUPER_GROUP_CODE = 'super_group';
25+
26+
/**
27+
* @var ObjectFactory
28+
*/
29+
private $objectFactory;
30+
31+
/**
32+
* @var QuoteApi\ProductOptionExtensionFactory
33+
*/
34+
private $productOptionExtensionFactory;
35+
36+
/**
37+
* @var QuoteApi\ProductOptionInterfaceFactory
38+
*/
39+
private $productOptionFactory;
40+
41+
/**
42+
* @var array|null
43+
*/
44+
private $groupedOptions;
45+
46+
/**
47+
* @param ObjectFactory $objectFactory
48+
* @param QuoteApi\ProductOptionExtensionFactory $productOptionExtensionFactory
49+
* @param QuoteApi\ProductOptionInterfaceFactory $productOptionFactory
50+
*/
51+
public function __construct(
52+
ObjectFactory $objectFactory,
53+
QuoteApi\ProductOptionExtensionFactory $productOptionExtensionFactory,
54+
QuoteApi\ProductOptionInterfaceFactory $productOptionFactory
55+
) {
56+
$this->objectFactory = $objectFactory;
57+
$this->productOptionExtensionFactory = $productOptionExtensionFactory;
58+
$this->productOptionFactory = $productOptionFactory;
59+
}
60+
61+
/**
62+
* Converts the grouped_options request data into the same format as native frontend add-to-cart
63+
*
64+
* @param CartItemInterface $cartItem
65+
* @return DataObject|null
66+
*/
67+
public function convertToBuyRequest(CartItemInterface $cartItem): ?DataObject
68+
{
69+
if ($cartItem->getProductOption()
70+
&& $cartItem->getProductOption()->getExtensionAttributes()
71+
&& $cartItem->getProductOption()->getExtensionAttributes()->getGroupedOptions()
72+
) {
73+
$groupedOptions = $cartItem->getProductOption()->getExtensionAttributes()->getGroupedOptions();
74+
$this->groupedOptions = $groupedOptions;
75+
76+
return $this->objectFactory->create($this->getConvertedData($groupedOptions));
77+
}
78+
79+
return null;
80+
}
81+
82+
/**
83+
* Returns grouped_options converted to super_group data
84+
*
85+
* @param GroupedOptionsInterface[] $groupedOptions
86+
* @return array
87+
* @throws LocalizedException
88+
*/
89+
private function getConvertedData(array $groupedOptions): array
90+
{
91+
$requestData = [];
92+
foreach ($groupedOptions as $item) {
93+
/** @var GroupedOptionsInterface $item */
94+
if ($item->getQty() === null || $item->getId() === null) {
95+
throw new LocalizedException(__('Please specify id and qty for grouped options.'));
96+
}
97+
$requestData[self::SUPER_GROUP_CODE][$item->getId()] = $item->getQty();
98+
}
99+
100+
return $requestData;
101+
}
102+
103+
/**
104+
* Option processor
105+
*
106+
* @param CartItemInterface $cartItem
107+
* @return CartItemInterface
108+
*/
109+
public function processOptions(CartItemInterface $cartItem): CartItemInterface
110+
{
111+
if (empty($this->groupedOptions) || $cartItem->getProductType() !== Grouped::TYPE_CODE) {
112+
return $cartItem;
113+
}
114+
115+
$extension = $this->productOptionExtensionFactory->create()
116+
->setGroupedOptions($this->groupedOptions);
117+
if (!$cartItem->getProductOption()) {
118+
$cartItem->setProductOption($this->productOptionFactory->create());
119+
}
120+
$cartItem->getProductOption()->setExtensionAttributes($extension);
121+
122+
return $cartItem;
123+
}
124+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
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\GroupedProduct\Model\Quote\Item;
9+
10+
use Magento\GroupedProduct\Api\Data\GroupedOptionsInterface;
11+
use Magento\GroupedProduct\Api\Data\GroupedOptionsExtensionInterface;
12+
13+
/**
14+
* @inheritDoc
15+
*/
16+
class GroupedOptions implements GroupedOptionsInterface
17+
{
18+
/**
19+
* @var int|null
20+
*/
21+
private $qty;
22+
23+
/**
24+
* @var int|null
25+
*/
26+
private $id;
27+
28+
/**
29+
* @var GroupedOptionsExtensionInterface|null
30+
*/
31+
private $extensionAttributes;
32+
33+
/**
34+
* @param int|null $id
35+
* @param int|null $qty
36+
* @param GroupedOptionsExtensionInterface|null $extensionAttributes
37+
*/
38+
public function __construct(
39+
?int $id = null,
40+
?int $qty = null,
41+
?GroupedOptionsExtensionInterface $extensionAttributes = null
42+
) {
43+
$this->id = $id;
44+
$this->qty = $qty;
45+
$this->extensionAttributes = $extensionAttributes;
46+
}
47+
48+
/**
49+
* @inheritDoc
50+
*/
51+
public function getId(): ?int
52+
{
53+
return $this->id;
54+
}
55+
56+
/**
57+
* @inheritDoc
58+
*/
59+
public function getQty(): ?int
60+
{
61+
return $this->qty;
62+
}
63+
64+
/**
65+
* @inheritDoc
66+
*/
67+
public function setExtensionAttributes(GroupedOptionsExtensionInterface $extensionAttributes): void
68+
{
69+
$this->extensionAttributes = $extensionAttributes;
70+
}
71+
72+
/**
73+
* @inheritDoc
74+
*/
75+
public function getExtensionAttributes(): ?GroupedOptionsExtensionInterface
76+
{
77+
return $this->extensionAttributes;
78+
}
79+
}

app/code/Magento/GroupedProduct/etc/di.xml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
*/
77
-->
88
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9+
<preference for="Magento\GroupedProduct\Api\Data\GroupedOptionsInterface" type="Magento\GroupedProduct\Model\Quote\Item\GroupedOptions" />
10+
911
<type name="Magento\Quote\Model\Quote\Item\RelatedProducts">
1012
<arguments>
1113
<argument name="relatedProductTypes" xsi:type="array">
@@ -105,6 +107,13 @@
105107
</argument>
106108
</arguments>
107109
</type>
110+
<type name="Magento\Quote\Model\Quote\Item\Repository">
111+
<arguments>
112+
<argument name="cartItemProcessors" xsi:type="array">
113+
<item name="grouped" xsi:type="object">Magento\GroupedProduct\Model\Quote\Item\CartItemProcessor\Proxy</item>
114+
</argument>
115+
</arguments>
116+
</type>
108117
<type name="Magento\CatalogInventory\Observer\SaveInventoryDataObserver">
109118
<arguments>
110119
<argument name="parentItemProcessorPool" xsi:type="array">

app/code/Magento/GroupedProduct/etc/extension_attributes.xml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,8 @@
99
<extension_attributes for="Magento\Catalog\Api\Data\ProductLinkInterface">
1010
<attribute code="qty" type="float" />
1111
</extension_attributes>
12+
13+
<extension_attributes for="Magento\Quote\Api\Data\ProductOptionInterface">
14+
<attribute code="grouped_options" type="Magento\GroupedProduct\Api\Data\GroupedOptionsInterface[]" />
15+
</extension_attributes>
1216
</config>

0 commit comments

Comments
 (0)