Skip to content

Commit df73677

Browse files
Merge pull request #1668 from magento-plankton/MAGETWO-80191
[Plankton] Fixes - MAGETWO-80191: [2.2.x] - Fixes #10255: base_shipping_discount_tax_compensation_amnt was empty from order onwards #10435 - MAGETWO-80203 [2.2.x]: - FIX for issue 9930 - Asymmetric Transaction Error with ElasticSearch #10610 - MAGETWO-62981: Cannot save category position after drag&drop (second attempt) - MAGETWO-82339: Duplicate Shipment getting created
2 parents 0483421 + 0b2196e commit df73677

File tree

17 files changed

+614
-56
lines changed

17 files changed

+614
-56
lines changed

app/code/Magento/Catalog/Model/Product/Gallery/Processor.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ public function addImage(
192192
$mediaGalleryData['images'][] = [
193193
'file' => $fileName,
194194
'position' => $position,
195+
'media_type' => 'image',
195196
'label' => '',
196197
'disabled' => (int)$exclude,
197198
];

app/code/Magento/Catalog/view/adminhtml/templates/catalog/category/tree.phtml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
}
6060
};
6161

62+
var treeRoot = '#tree-div';
63+
6264
/**
6365
* Fix ext compatibility with prototype 1.6
6466
*/
@@ -491,7 +493,7 @@
491493
if (data.error) {
492494
reRenderTree();
493495
} else {
494-
$(obj.tree.container.dom).trigger('categoryMove.tree');
496+
$(treeRoot).trigger('categoryMove.tree');
495497
}
496498
$('.page-main-actions').next('.messages').remove();
497499
$('.page-main-actions').next('#messages').remove();

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: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ private function getQuantitiesFromOrderItems(array $items)
121121
{
122122
$shipmentItems = [];
123123
foreach ($items as $item) {
124-
if (!$item->getIsVirtual() && !$item->getParentItem()) {
124+
if (!$item->getIsVirtual() && (!$item->getParentItem() || $item->isShipSeparately())) {
125125
$shipmentItems[$item->getItemId()] = $item->getQtyOrdered();
126126
}
127127
}

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

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -96,15 +96,15 @@ 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()) {
107+
if ($orderItem->getIsVirtual() || ($orderItem->getParentItemId() && !$orderItem->isShipSeparately())) {
108108
$item->isDeleted(true);
109109
}
110110

@@ -124,8 +124,7 @@ protected function prepareItems(
124124
$qty = min($qty, $orderItem->getSimpleQtyToShip());
125125

126126
$item->setQty($this->castQty($orderItem, $qty));
127-
$shipment->addItem($item);
128-
127+
$shipmentItems[] = $item;
129128
continue;
130129
} else {
131130
$qty = 1;
@@ -144,10 +143,65 @@ protected function prepareItems(
144143
}
145144
}
146145

147-
$totalQty += $qty;
148-
149146
$item->setQty($this->castQty($orderItem, $qty));
150-
$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);
151205
}
152206
return $shipment->setTotalQty($totalQty);
153207
}

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/ShipmentFactoryTest.php

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,18 @@ public function testCreate($tracks)
8484
$orderItem->expects($this->any())->method('getParentItemId')->willReturn(false);
8585
$orderItem->expects($this->any())->method('getIsVirtual')->willReturn(false);
8686

87-
$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+
);
8891
$shipmentItem->expects($this->once())
8992
->method('setQty')
9093
->with(5);
94+
$shipmentItem->expects($this->once())
95+
->method('getQty')
96+
->willReturn(5);
97+
98+
$shipmentItem->expects($this->atLeastOnce())->method('getOrderItem')->willReturn($orderItem);
9199

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

app/code/Magento/Sales/etc/fieldset.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,7 +279,7 @@
279279
<aspect name="to_order" />
280280
</field>
281281
<field name="base_shipping_discount_tax_compensation_amount">
282-
<aspect name="to_order" />
282+
<aspect name="to_order" targetField="base_shipping_discount_tax_compensation_amnt"/>
283283
</field>
284284
<field name="prefix">
285285
<aspect name="to_order_address" />

app/code/Magento/Shipping/view/adminhtml/templates/create/items.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
</tr>
2828
</thead>
2929
<?php $_items = $block->getShipment()->getAllItems() ?>
30-
<?php $_i = 0; foreach ($_items as $_item): $_i++ ?>
30+
<?php $_i = 0; foreach ($_items as $_item): if ($_item->getOrderItem()->getParentItem()): continue; endif; $_i++ ?>
3131
<tbody class="<?= /* @escapeNotVerified */ $_i%2 ? 'odd' : 'even' ?>">
3232
<?= $block->getItemHtml($_item) ?>
3333
<?= $block->getItemExtraInfoHtml($_item->getOrderItem()) ?>

app/code/Magento/Shipping/view/adminhtml/templates/view/items.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
</tr>
1717
</thead>
1818
<?php $_items = $block->getShipment()->getAllItems() ?>
19-
<?php $_i = 0; foreach ($_items as $_item): $_i++ ?>
19+
<?php $_i = 0; foreach ($_items as $_item): if ($_item->getOrderItem()->getParentItem()): continue; endif; $_i++ ?>
2020
<tbody class="<?= /* @escapeNotVerified */ $_i%2 ? 'odd' : 'even' ?>">
2121
<?= $block->getItemHtml($_item) ?>
2222
<?= $block->getItemExtraInfoHtml($_item->getOrderItem()) ?>

dev/tests/api-functional/testsuite/Magento/Sales/Service/V1/ShipOrderTest.php

Lines changed: 83 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,11 @@ public function testConfigurableShipOrder()
4343
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
4444
->loadByIncrementId('100000001');
4545

46-
$serviceInfo = [
47-
'rest' => [
48-
'resourcePath' => '/V1/order/' . $existingOrder->getId() . '/ship',
49-
'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
50-
],
51-
'soap' => [
52-
'service' => self::SERVICE_READ_NAME,
53-
'serviceVersion' => self::SERVICE_VERSION,
54-
'operation' => self::SERVICE_READ_NAME . 'execute',
55-
],
56-
];
57-
5846
$requestData = [
5947
'orderId' => $existingOrder->getId(),
6048
];
6149

62-
$shipmentId = (int)$this->_webApiCall($serviceInfo, $requestData);
50+
$shipmentId = (int)$this->_webApiCall($this->getServiceInfo($existingOrder), $requestData);
6351
$this->assertNotEmpty($shipmentId);
6452

6553
try {
@@ -98,18 +86,6 @@ public function testShipOrder()
9886
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
9987
->loadByIncrementId('100000001');
10088

101-
$serviceInfo = [
102-
'rest' => [
103-
'resourcePath' => '/V1/order/' . $existingOrder->getId() . '/ship',
104-
'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
105-
],
106-
'soap' => [
107-
'service' => self::SERVICE_READ_NAME,
108-
'serviceVersion' => self::SERVICE_VERSION,
109-
'operation' => self::SERVICE_READ_NAME . 'execute',
110-
],
111-
];
112-
11389
$requestData = [
11490
'orderId' => $existingOrder->getId(),
11591
'items' => [],
@@ -134,7 +110,7 @@ public function testShipOrder()
134110
];
135111
}
136112

137-
$result = $this->_webApiCall($serviceInfo, $requestData);
113+
$result = $this->_webApiCall($this->getServiceInfo($existingOrder), $requestData);
138114

139115
$this->assertNotEmpty($result);
140116

@@ -154,4 +130,85 @@ public function testShipOrder()
154130
'Failed asserting that Order status was changed'
155131
);
156132
}
133+
134+
/**
135+
* @magentoApiDataFixture Magento/Bundle/_files/order_with_bundle_shipped_separately.php
136+
*/
137+
public function testPartialShipOrderWithBundleShippedSeparately()
138+
{
139+
/** @var \Magento\Sales\Model\Order $existingOrder */
140+
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
141+
->loadByIncrementId('100000001');
142+
143+
$requestData = [
144+
'orderId' => $existingOrder->getId(),
145+
'items' => [],
146+
'comment' => [
147+
'comment' => 'Test Comment',
148+
'is_visible_on_front' => 1,
149+
],
150+
'tracks' => [
151+
[
152+
'track_number' => 'TEST_TRACK_0001',
153+
'title' => 'Simple shipment track',
154+
'carrier_code' => 'UPS'
155+
]
156+
]
157+
];
158+
159+
$shippedItemId = null;
160+
foreach ($existingOrder->getAllItems() as $item) {
161+
if ($item->getProductType() == 'simple') {
162+
$requestData['items'][] = [
163+
'order_item_id' => $item->getItemId(),
164+
'qty' => $item->getQtyOrdered(),
165+
];
166+
$shippedItemId = $item->getItemId();
167+
break;
168+
}
169+
}
170+
171+
$shipmentId = $this->_webApiCall($this->getServiceInfo($existingOrder), $requestData);
172+
$this->assertNotEmpty($shipmentId);
173+
174+
try {
175+
$shipment = $this->shipmentRepository->get($shipmentId);
176+
} catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
177+
$this->fail('Failed asserting that Shipment was created');
178+
}
179+
180+
$this->assertEquals(1, $shipment->getTotalQty());
181+
182+
/** @var \Magento\Sales\Model\Order $existingOrder */
183+
$existingOrder = $this->objectManager->create(\Magento\Sales\Model\Order::class)
184+
->loadByIncrementId('100000001');
185+
186+
foreach ($existingOrder->getAllItems() as $item) {
187+
if ($item->getItemId() == $shippedItemId) {
188+
$this->assertEquals(1, $item->getQtyShipped());
189+
continue;
190+
}
191+
$this->assertEquals(0, $item->getQtyShipped());
192+
}
193+
}
194+
195+
/**
196+
* @param \Magento\Sales\Model\Order $order
197+
* @return array
198+
*/
199+
private function getServiceInfo(\Magento\Sales\Model\Order $order)
200+
{
201+
$serviceInfo = [
202+
'rest' => [
203+
'resourcePath' => '/V1/order/' . $order->getId() . '/ship',
204+
'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_POST,
205+
],
206+
'soap' => [
207+
'service' => self::SERVICE_READ_NAME,
208+
'serviceVersion' => self::SERVICE_VERSION,
209+
'operation' => self::SERVICE_READ_NAME . 'execute',
210+
],
211+
];
212+
return $serviceInfo;
213+
}
157214
}

dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Category/Tree.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ public function isCategoryVisible(Category $category)
169169
*/
170170
public function assignCategory($parentCategoryName, $childCategoryName)
171171
{
172-
$this->_rootElement->find(sprintf($this->categoryInTree, $childCategoryName), Locator::SELECTOR_XPATH)->click();
172+
$this->_rootElement->find(sprintf($this->categoryInTree, $childCategoryName), Locator::SELECTOR_XPATH)->hover();
173173
$this->getTemplateBlock()->waitLoader();
174174
$targetElement = $this->_rootElement->find(
175175
sprintf($this->categoryInTree, $parentCategoryName),

0 commit comments

Comments
 (0)