Skip to content

Commit 13de3c8

Browse files
committed
ACP2E-1650:Create Shipment API
- addressed validation issues - adjusted unit tests
1 parent 528122e commit 13de3c8

File tree

4 files changed

+259
-235
lines changed

4 files changed

+259
-235
lines changed

app/code/Magento/Bundle/Model/Sales/Order/BundleOrderTypeValidator.php

Lines changed: 137 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,12 @@
99

1010
use Magento\Bundle\Model\Sales\Order\Shipment\BundleShipmentTypeValidator;
1111
use \Laminas\Validator\ValidatorInterface;
12+
use Magento\Catalog\Model\Product\Type;
13+
use Magento\Framework\Exception\NoSuchEntityException;
1214
use Magento\Framework\Phrase;
1315
use Magento\Framework\Webapi\Request;
16+
use Magento\Sales\Api\Data\ShipmentItemInterface;
17+
use Magento\Sales\Model\Order\Item;
1418
use Magento\Sales\Model\Order\Shipment;
1519

1620
/**
@@ -20,6 +24,10 @@ class BundleOrderTypeValidator extends BundleShipmentTypeValidator implements Va
2024
{
2125
private const SHIPMENT_API_ROUTE = 'v1/shipment';
2226

27+
public const SHIPMENT_TYPE_TOGETHER = '0';
28+
29+
public const SHIPMENT_TYPE_SEPARATELY = '1';
30+
2331
/**
2432
* @var array
2533
*/
@@ -52,14 +60,23 @@ public function isValid($value): bool
5260
return true;
5361
}
5462

55-
foreach ($value->getOrder()->getAllItems() as $orderItem) {
56-
foreach ($value->getItems() as $shipmentItem) {
57-
if ($orderItem->getItemId() == $shipmentItem->getOrderItemId()) {
58-
if ($validationMessages = $this->validate($orderItem)) {
59-
$this->renderValidationMessages($validationMessages);
60-
}
61-
}
63+
$result = $shippingInfo = [];
64+
foreach ($value->getItems() as $shipmentItem) {
65+
$shippingInfo[$shipmentItem->getOrderItemId()] = [
66+
'shipment_info' => $shipmentItem,
67+
'order_info' => $value->getOrder()->getItemById($shipmentItem->getOrderItemId())
68+
];
69+
}
70+
71+
foreach ($shippingInfo as $shippingItemInfo) {
72+
if ($shippingItemInfo['order_info']->getProductType() === Type::TYPE_BUNDLE) {
73+
$result[] = $this->checkBundleItem($shippingItemInfo, $shippingInfo);
74+
} elseif ($shippingItemInfo['order_info']->getParentItem() &&
75+
$shippingItemInfo['order_info']->getParentItem()->getProductType() === Type::TYPE_BUNDLE
76+
) {
77+
$result[] = $this->checkChildItem($shippingItemInfo['order_info'], $shippingInfo);
6278
}
79+
$this->renderValidationMessages($result);
6380
}
6481

6582
return empty($this->messages);
@@ -75,6 +92,118 @@ public function getMessages(): array
7592
return $this->messages;
7693
}
7794

95+
/**
96+
* @param Item $orderItem
97+
* @param array $shipmentInfo
98+
* @return Phrase|null
99+
* @throws NoSuchEntityException
100+
*/
101+
private function checkChildItem(Item $orderItem, array $shipmentInfo): ?Phrase
102+
{
103+
$result = null;
104+
if ($orderItem->getParentItem()->getProductType() === Type::TYPE_BUNDLE &&
105+
$orderItem->getParentItem()->getProduct()->getShipmentType() === self::SHIPMENT_TYPE_TOGETHER) {
106+
$result = __(
107+
'Cannot create shipment as bundle product "%1" has shipment type "%2". ' .
108+
'%3 should be shipped instead.',
109+
$orderItem->getParentItem()->getSku(),
110+
__('Together'),
111+
__('Bundle product itself'),
112+
);
113+
}
114+
115+
if ($orderItem->getParentItem()->getProductType() === Type::TYPE_BUNDLE &&
116+
$orderItem->getParentItem()->getProduct()->getShipmentType() === self::SHIPMENT_TYPE_SEPARATELY &&
117+
false === $this->hasParentInShipping($orderItem, $shipmentInfo)
118+
) {
119+
$result = __(
120+
'Cannot create shipment as bundle product %1 should be included as well.',
121+
$orderItem->getParentItem()->getSku()
122+
);
123+
}
124+
125+
return $result;
126+
}
127+
128+
/**
129+
* @param array $shippingItemInfo
130+
* @param array $shippingInfo
131+
* @return Phrase|null
132+
*/
133+
private function checkBundleItem(array $shippingItemInfo, array $shippingInfo): ?Phrase
134+
{
135+
$result = null;
136+
/** @var Item $orderItem */
137+
$orderItem = $shippingItemInfo['order_info'];
138+
/** @var ShipmentItemInterface $shipmentItem */
139+
$shipmentItem = $shippingItemInfo['shipment_info'];
140+
141+
if ($orderItem->getProduct()->getShipmentType() === self::SHIPMENT_TYPE_TOGETHER &&
142+
$this->hasChildrenInShipping($shipmentItem, $shippingInfo)
143+
) {
144+
$result = __(
145+
'Cannot create shipment as bundle product "%1" has shipment type "%2". ' .
146+
'%3 should be shipped instead.',
147+
$orderItem->getSku(),
148+
__('Together'),
149+
__('Bundle product itself'),
150+
);
151+
}
152+
if ($orderItem->getProduct()->getShipmentType() === self::SHIPMENT_TYPE_SEPARATELY &&
153+
false === $this->hasChildrenInShipping($shipmentItem, $shippingInfo)
154+
) {
155+
$result = __(
156+
'Cannot create shipment as bundle product "%1" has shipment type "%2". ' .
157+
'%3.',
158+
$orderItem->getSku(),
159+
__('Separately'),
160+
__('Shipment should also incorporate bundle options'),
161+
);
162+
}
163+
return $result;
164+
}
165+
166+
/**
167+
* Determines if a child shipment item has its corresponding parent in shipment
168+
*
169+
* @param Item $childItem
170+
* @param array $shipmentInfo
171+
* @return bool
172+
*/
173+
private function hasParentInShipping(Item $childItem, array $shipmentInfo): bool
174+
{
175+
/** @var Item $orderItem */
176+
foreach (array_column($shipmentInfo, 'order_info') as $orderItem) {
177+
if (!$orderItem->getParentItemId() &&
178+
$orderItem->getProductType() === Type::TYPE_BUNDLE &&
179+
$childItem->getParentItemId() == $orderItem->getItemId()
180+
) {
181+
return true;
182+
}
183+
}
184+
return false;
185+
}
186+
187+
/**
188+
* Determines if a bundle shipment item has at least one child in shipment
189+
*
190+
* @param ShipmentItemInterface $bundleItem
191+
* @param array $shippingInfo
192+
* @return bool
193+
*/
194+
private function hasChildrenInShipping(ShipmentItemInterface $bundleItem, array $shippingInfo): bool
195+
{
196+
/** @var Item $orderItem */
197+
foreach (array_column($shippingInfo, 'order_info') as $orderItem) {
198+
if ($orderItem->getParentItemId() &&
199+
$orderItem->getParentItemId() == $bundleItem->getOrderItemId()
200+
) {
201+
return true;
202+
}
203+
}
204+
return false;
205+
}
206+
78207
/**
79208
* Determines if the validation should be triggered or not
80209
*
@@ -98,5 +227,6 @@ private function renderValidationMessages(array $validationMessages): void
98227
$this->messages[] = $message->render();
99228
}
100229
}
230+
$this->messages = array_unique($this->messages);
101231
}
102232
}

0 commit comments

Comments
 (0)