Skip to content

Commit 1c74b3b

Browse files
author
Alexander Akimov
authored
Merge pull request #2216 from magento-plankton/forwardports1
[Plankton] Forwardports
2 parents 05ccc44 + 45b0de1 commit 1c74b3b

File tree

16 files changed

+727
-146
lines changed

16 files changed

+727
-146
lines changed

app/code/Magento/Sales/Model/Order/Shipment.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -262,8 +262,6 @@ public function register()
262262
if (!$item->getOrderItem()->isDummy(true)) {
263263
$totalQty += $item->getQty();
264264
}
265-
} else {
266-
$item->isDeleted(true);
267265
}
268266
}
269267

app/code/Magento/Sales/Model/Order/Shipment/OrderRegistrar.php

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,19 @@ class OrderRegistrar implements \Magento\Sales\Model\Order\Shipment\OrderRegistr
1717
*/
1818
public function register(OrderInterface $order, ShipmentInterface $shipment)
1919
{
20-
/** @var \Magento\Sales\Api\Data\ShipmentItemInterface|\Magento\Sales\Model\Order\Shipment\Item $item */
20+
$totalQty = 0;
21+
/** @var \Magento\Sales\Model\Order\Shipment\Item $item */
2122
foreach ($shipment->getItems() as $item) {
2223
if ($item->getQty() > 0) {
2324
$item->register();
25+
26+
if (!$item->getOrderItem()->isDummy(true)) {
27+
$totalQty += $item->getQty();
28+
}
2429
}
2530
}
31+
$shipment->setTotalQty($totalQty);
32+
2633
return $order;
2734
}
2835
}

app/code/Magento/Sales/Model/Order/ShipmentDocumentFactory.php

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Magento\Sales\Api\Data\OrderInterface;
1515
use Magento\Sales\Api\Data\ShipmentCommentCreationInterface;
1616
use Magento\Sales\Api\Data\ShipmentCreationArgumentsInterface;
17+
use Magento\Sales\Api\Data\OrderItemInterface;
1718

1819
/**
1920
* Class ShipmentDocumentFactory
@@ -77,13 +78,23 @@ public function create(
7778
array $packages = [],
7879
ShipmentCreationArgumentsInterface $arguments = null
7980
) {
80-
$shipmentItems = $this->itemsToArray($items);
81+
$shipmentItems = empty($items)
82+
? $this->getQuantitiesFromOrderItems($order->getItems())
83+
: $this->getQuantitiesFromShipmentItems($items);
84+
8185
/** @var Shipment $shipment */
8286
$shipment = $this->shipmentFactory->create(
8387
$order,
8488
$shipmentItems
8589
);
86-
$this->prepareTracks($shipment, $tracks);
90+
91+
foreach ($tracks as $track) {
92+
$hydrator = $this->hydratorPool->getHydrator(
93+
\Magento\Sales\Api\Data\ShipmentTrackCreationInterface::class
94+
);
95+
$shipment->addTrack($this->trackFactory->create(['data' => $hydrator->extract($track)]));
96+
}
97+
8798
if ($comment) {
8899
$shipment->addComment(
89100
$comment->getComment(),
@@ -101,30 +112,29 @@ public function create(
101112
}
102113

103114
/**
104-
* Adds tracks to the shipment.
115+
* Translate OrderItemInterface array to product id => product quantity array.
105116
*
106-
* @param ShipmentInterface $shipment
107-
* @param ShipmentTrackCreationInterface[] $tracks
108-
* @return ShipmentInterface
117+
* @param OrderItemInterface[] $items
118+
* @return int[]
109119
*/
110-
private function prepareTracks(\Magento\Sales\Api\Data\ShipmentInterface $shipment, array $tracks)
120+
private function getQuantitiesFromOrderItems(array $items)
111121
{
112-
foreach ($tracks as $track) {
113-
$hydrator = $this->hydratorPool->getHydrator(
114-
\Magento\Sales\Api\Data\ShipmentTrackCreationInterface::class
115-
);
116-
$shipment->addTrack($this->trackFactory->create(['data' => $hydrator->extract($track)]));
122+
$shipmentItems = [];
123+
foreach ($items as $item) {
124+
if (!$item->getIsVirtual() && (!$item->getParentItem() || $item->isShipSeparately())) {
125+
$shipmentItems[$item->getItemId()] = $item->getQtyOrdered();
126+
}
117127
}
118-
return $shipment;
128+
return $shipmentItems;
119129
}
120130

121131
/**
122-
* Convert items to array
132+
* Translate ShipmentItemCreationInterface array to product id => product quantity array.
123133
*
124134
* @param ShipmentItemCreationInterface[] $items
125-
* @return array
135+
* @return int[]
126136
*/
127-
private function itemsToArray(array $items = [])
137+
private function getQuantitiesFromShipmentItems(array $items)
128138
{
129139
$shipmentItems = [];
130140
foreach ($items as $item) {

app/code/Magento/Sales/Model/Order/ShipmentFactory.php

Lines changed: 64 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -96,14 +96,17 @@ protected function prepareItems(
9696
\Magento\Sales\Model\Order $order,
9797
array $items = []
9898
) {
99-
$totalQty = 0;
99+
$shipmentItems = [];
100100
foreach ($order->getAllItems() as $orderItem) {
101-
if (!$this->canShipItem($orderItem, $items)) {
101+
if ($this->validateItem($orderItem, $items) === false) {
102102
continue;
103103
}
104104

105105
/** @var \Magento\Sales\Model\Order\Shipment\Item $item */
106106
$item = $this->converter->itemToShipmentItem($orderItem);
107+
if ($orderItem->getIsVirtual() || ($orderItem->getParentItemId() && !$orderItem->isShipSeparately())) {
108+
$item->isDeleted(true);
109+
}
107110

108111
if ($orderItem->isDummy(true)) {
109112
$qty = 0;
@@ -121,8 +124,7 @@ protected function prepareItems(
121124
$qty = min($qty, $orderItem->getSimpleQtyToShip());
122125

123126
$item->setQty($this->castQty($orderItem, $qty));
124-
$shipment->addItem($item);
125-
127+
$shipmentItems[] = $item;
126128
continue;
127129
} else {
128130
$qty = 1;
@@ -141,10 +143,65 @@ protected function prepareItems(
141143
}
142144
}
143145

144-
$totalQty += $qty;
145-
146146
$item->setQty($this->castQty($orderItem, $qty));
147-
$shipment->addItem($item);
147+
$shipmentItems[] = $item;
148+
}
149+
return $this->setItemsToShipment($shipment, $shipmentItems);
150+
}
151+
152+
/**
153+
* Validate order item before shipment
154+
*
155+
* @param Item $orderItem
156+
* @param array $items
157+
* @return bool
158+
*/
159+
private function validateItem(\Magento\Sales\Model\Order\Item $orderItem, array $items)
160+
{
161+
if (!$this->canShipItem($orderItem, $items)) {
162+
return false;
163+
}
164+
165+
// Remove from shipment items without qty or with qty=0
166+
if (!$orderItem->isDummy(true)
167+
&& (!isset($items[$orderItem->getId()]) || $items[$orderItem->getId()] <= 0)
168+
) {
169+
return false;
170+
}
171+
return true;
172+
}
173+
174+
/**
175+
* Set prepared items to shipment document
176+
*
177+
* @param \Magento\Sales\Api\Data\ShipmentInterface $shipment
178+
* @param array $shipmentItems
179+
* @return \Magento\Sales\Api\Data\ShipmentInterface
180+
*/
181+
private function setItemsToShipment(\Magento\Sales\Api\Data\ShipmentInterface $shipment, $shipmentItems)
182+
{
183+
$totalQty = 0;
184+
185+
/**
186+
* Verify that composite products shipped separately has children, if not -> remove from collection
187+
*/
188+
/** @var \Magento\Sales\Model\Order\Shipment\Item $shipmentItem */
189+
foreach ($shipmentItems as $key => $shipmentItem) {
190+
if ($shipmentItem->getOrderItem()->getHasChildren()
191+
&& $shipmentItem->getOrderItem()->isShipSeparately()
192+
) {
193+
$containerId = $shipmentItem->getOrderItem()->getId();
194+
$childItems = array_filter($shipmentItems, function ($item) use ($containerId) {
195+
return $containerId == $item->getOrderItem()->getParentItemId();
196+
});
197+
198+
if (count($childItems) <= 0) {
199+
unset($shipmentItems[$key]);
200+
continue;
201+
}
202+
}
203+
$totalQty += $shipmentItem->getQty();
204+
$shipment->addItem($shipmentItem);
148205
}
149206
return $shipment->setTotalQty($totalQty);
150207
}

app/code/Magento/Sales/Test/Unit/Model/Order/Shipment/OrderRegistrarTest.php

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,23 +37,20 @@ protected function setUp()
3737
public function testRegister()
3838
{
3939
$item1 = $this->getShipmentItemMock();
40-
$item1->expects($this->once())
41-
->method('getQty')
42-
->willReturn(0);
43-
$item1->expects($this->never())
44-
->method('register');
40+
$item1->expects($this->once())->method('getQty')->willReturn(0);
41+
$item1->expects($this->never())->method('register');
42+
$item1->expects($this->never())->method('getOrderItem');
4543

4644
$item2 = $this->getShipmentItemMock();
47-
$item2->expects($this->once())
48-
->method('getQty')
49-
->willReturn(0.5);
50-
$item2->expects($this->once())
51-
->method('register');
45+
$item2->expects($this->atLeastOnce())->method('getQty')->willReturn(0.5);
46+
$item2->expects($this->once())->method('register');
47+
48+
$orderItemMock = $this->createMock(\Magento\Sales\Model\Order\Item::class);
49+
$orderItemMock->expects($this->once())->method('isDummy')->with(true)->willReturn(false);
50+
$item2->expects($this->once())->method('getOrderItem')->willReturn($orderItemMock);
5251

5352
$items = [$item1, $item2];
54-
$this->shipmentMock->expects($this->once())
55-
->method('getItems')
56-
->willReturn($items);
53+
$this->shipmentMock->expects($this->once())->method('getItems')->willReturn($items);
5754
$this->assertEquals(
5855
$this->orderMock,
5956
$this->model->register($this->orderMock, $this->shipmentMock)
@@ -67,7 +64,7 @@ private function getShipmentItemMock()
6764
{
6865
return $this->getMockBuilder(\Magento\Sales\Api\Data\ShipmentItemInterface::class)
6966
->disableOriginalConstructor()
70-
->setMethods(['register'])
67+
->setMethods(['register', 'getOrderItem'])
7168
->getMockForAbstractClass();
7269
}
7370
}

app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentDocumentFactoryTest.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
/**
2121
* Class ShipmentDocumentFactoryTest
22+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
2223
*/
2324
class ShipmentDocumentFactoryTest extends \PHPUnit\Framework\TestCase
2425
{
@@ -128,6 +129,8 @@ public function testCreate()
128129
$packages = [];
129130
$items = [1 => 10];
130131

132+
$this->itemMock->expects($this->once())->method('getOrderItemId')->willReturn(1);
133+
$this->itemMock->expects($this->once())->method('getQty')->willReturn(10);
131134
$this->itemMock->expects($this->once())
132135
->method('getOrderItemId')
133136
->willReturn(1);

app/code/Magento/Sales/Test/Unit/Model/Order/ShipmentFactoryTest.php

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,18 +71,31 @@ protected function setUp()
7171
*/
7272
public function testCreate($tracks)
7373
{
74-
$orderItem = $this->createPartialMock(\Magento\Sales\Model\Order\Item::class, ['getId', 'getQtyOrdered']);
74+
$orderItem = $this->createPartialMock(
75+
\Magento\Sales\Model\Order\Item::class,
76+
['getId', 'getQtyOrdered', 'getParentItemId', 'getIsVirtual']
77+
);
7578
$orderItem->expects($this->any())
7679
->method('getId')
7780
->willReturn(1);
7881
$orderItem->expects($this->any())
7982
->method('getQtyOrdered')
8083
->willReturn(5);
84+
$orderItem->expects($this->any())->method('getParentItemId')->willReturn(false);
85+
$orderItem->expects($this->any())->method('getIsVirtual')->willReturn(false);
8186

82-
$shipmentItem = $this->createPartialMock(\Magento\Sales\Model\Order\Shipment\Item::class, ['setQty']);
87+
$shipmentItem = $this->createPartialMock(
88+
\Magento\Sales\Model\Order\Shipment\Item::class,
89+
['setQty', 'getOrderItem', 'getQty']
90+
);
8391
$shipmentItem->expects($this->once())
8492
->method('setQty')
8593
->with(5);
94+
$shipmentItem->expects($this->once())
95+
->method('getQty')
96+
->willReturn(5);
97+
98+
$shipmentItem->expects($this->atLeastOnce())->method('getOrderItem')->willReturn($orderItem);
8699

87100
$order = $this->createPartialMock(\Magento\Sales\Model\Order::class, ['getAllItems']);
88101
$order->expects($this->any())

0 commit comments

Comments
 (0)