Skip to content

Commit 2866fd8

Browse files
authored
Merge branch '2.4-develop' into PB-500
2 parents 8f9bfe1 + e8c31f5 commit 2866fd8

File tree

299 files changed

+26317
-20626
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

299 files changed

+26317
-20626
lines changed

app/code/Magento/AdminNotification/view/adminhtml/web/system/notification.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ define([
6969
}
7070
});
7171

72-
$(document).ready(function () {
72+
$(function () {
7373
$('#system_messages .message-system-short .error').on('click', function () {
7474
$('#message-system-all').systemMessageDialog('openModal', 1);
7575
});

app/code/Magento/AdvancedSearch/view/adminhtml/web/js/testconnection.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ define([
4444
fieldToCheck = this.options.fieldToCheck || 'success';
4545

4646
element.removeClass('success').addClass('fail');
47-
$.each($.parseJSON(this.options.fieldMapping), function (key, el) {
47+
$.each(JSON.parse(this.options.fieldMapping), function (key, el) {
4848
params[key] = $('#' + el).val();
4949
});
5050
$.ajax({

app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/AbstractRenderer.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,9 @@ protected function _getValue(DataObject $row)
9797
}
9898
return '';
9999
}
100-
return $row->getData($this->getColumn()->getIndex());
100+
return $this->getColumn()->getIndex() !== null
101+
? $row->getData($this->getColumn()->getIndex())
102+
: null;
101103
}
102104

103105
/**

app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Currency.php

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ protected function _getCurrencyCode($row)
102102
if ($code = $this->getColumn()->getCurrencyCode()) {
103103
return $code;
104104
}
105-
if ($code = $row->getData($this->getColumn()->getCurrency())) {
105+
$currency = $this->getColumn()->getCurrency();
106+
107+
if ($currency !== null && $code = $row->getData($currency)) {
106108
return $code;
107109
}
108110

@@ -118,11 +120,14 @@ protected function _getCurrencyCode($row)
118120
protected function _getRate($row)
119121
{
120122
if ($rate = $this->getColumn()->getRate()) {
121-
return (float)$rate;
123+
return (float) $rate;
122124
}
123-
if ($rate = $row->getData($this->getColumn()->getRateField())) {
124-
return (float)$rate;
125+
$rateField = $this->getColumn()->getRateField();
126+
127+
if ($rateField !== null && $rate = $row->getData($rateField)) {
128+
return (float) $rate;
125129
}
130+
126131
return $this->_defaultBaseCurrency->getRate($this->_getCurrencyCode($row));
127132
}
128133

app/code/Magento/Backend/Block/Widget/Grid/Column/Renderer/Price.php

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public function render(\Magento\Framework\DataObject $row)
6060
return $data;
6161
}
6262

63-
$data = (float)$data * $this->_getRate($row);
63+
$data = (float) $data * $this->_getRate($row);
6464
$data = sprintf("%f", $data);
6565
$data = $this->_localeCurrency->getCurrency($currencyCode)->toCurrency($data);
6666
return $data;
@@ -79,7 +79,9 @@ protected function _getCurrencyCode($row)
7979
if ($code = $this->getColumn()->getCurrencyCode()) {
8080
return $code;
8181
}
82-
if ($code = $row->getData($this->getColumn()->getCurrency())) {
82+
$currency = $this->getColumn()->getCurrency();
83+
84+
if ($currency !== null && $code = $row->getData($currency)) {
8385
return $code;
8486
}
8587
return false;
@@ -94,10 +96,12 @@ protected function _getCurrencyCode($row)
9496
protected function _getRate($row)
9597
{
9698
if ($rate = $this->getColumn()->getRate()) {
97-
return (float)$rate;
99+
return (float) $rate;
98100
}
99-
if ($rate = $row->getData($this->getColumn()->getRateField())) {
100-
return (float)$rate;
101+
$rateField = $this->getColumn()->getRateField();
102+
103+
if ($rateField !== null && $rate = $row->getData($rateField)) {
104+
return (float) $rate;
101105
}
102106
return 1;
103107
}

app/code/Magento/Backend/view/adminhtml/templates/widget/form/renderer/fieldset.phtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ if ($isField) {
4040
data-role="<?= $block->escapeHtmlAttr($id) ?>-wrapper">
4141
<div class="fieldset-wrapper-title admin__fieldset-wrapper-title">
4242
<strong <?= /* @noEscape */ $isCollapsable ?
43-
'class="admin__collapsible-title" data-toggle="collapse" data-target="#' . $id . '-content"' :
43+
'class="admin__collapsible-title" data-bs-toggle="collapse" data-bs-target="#' . $id . '-content"' :
4444
'class="title"'; ?>>
4545
<span><?= $block->escapeHtml($element->getLegend()) ?></span>
4646
</strong>
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
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\Bundle\Model\Inventory;
9+
10+
use Magento\Bundle\Model\Product\Type;
11+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
12+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
13+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
14+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
15+
16+
/***
17+
* Update stock status of bundle products based on children products stock status
18+
*/
19+
class ChangeParentStockStatus
20+
{
21+
/**
22+
* @var Type
23+
*/
24+
private $bundleType;
25+
26+
/**
27+
* @var StockItemCriteriaInterfaceFactory
28+
*/
29+
private $criteriaInterfaceFactory;
30+
31+
/**
32+
* @var StockItemRepositoryInterface
33+
*/
34+
private $stockItemRepository;
35+
36+
/**
37+
* @var StockConfigurationInterface
38+
*/
39+
private $stockConfiguration;
40+
41+
/**
42+
* @param StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory
43+
* @param StockItemRepositoryInterface $stockItemRepository
44+
* @param StockConfigurationInterface $stockConfiguration
45+
* @param Type $bundleType
46+
*/
47+
public function __construct(
48+
StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory,
49+
StockItemRepositoryInterface $stockItemRepository,
50+
StockConfigurationInterface $stockConfiguration,
51+
Type $bundleType
52+
) {
53+
$this->bundleType = $bundleType;
54+
$this->criteriaInterfaceFactory = $criteriaInterfaceFactory;
55+
$this->stockItemRepository = $stockItemRepository;
56+
$this->stockConfiguration = $stockConfiguration;
57+
}
58+
59+
/**
60+
* Update stock status of bundle products based on children products stock status
61+
*
62+
* @param array $childrenIds
63+
* @return void
64+
*/
65+
public function execute(array $childrenIds): void
66+
{
67+
$parentIds = $this->bundleType->getParentIdsByChild($childrenIds);
68+
foreach (array_unique($parentIds) as $productId) {
69+
$this->processStockForParent((int)$productId);
70+
}
71+
}
72+
73+
/**
74+
* Update stock status of bundle product based on children products stock status
75+
*
76+
* @param int $productId
77+
* @return void
78+
*/
79+
private function processStockForParent(int $productId): void
80+
{
81+
$stockItems = $this->getStockItems([$productId]);
82+
$parentStockItem = $stockItems[$productId] ?? null;
83+
if ($parentStockItem) {
84+
$childrenIsInStock = $this->isChildrenInStock($productId);
85+
if ($this->isNeedToUpdateParent($parentStockItem, $childrenIsInStock)) {
86+
$parentStockItem->setIsInStock($childrenIsInStock);
87+
$parentStockItem->setStockStatusChangedAuto(1);
88+
$this->stockItemRepository->save($parentStockItem);
89+
}
90+
}
91+
}
92+
93+
/**
94+
* Returns stock status of bundle product based on children stock status
95+
*
96+
* Returns TRUE if any of the following conditions is true:
97+
* - At least one product is in-stock in each required option
98+
* - Any product is in-stock (if all options are optional)
99+
*
100+
* @param int $productId
101+
* @return bool
102+
*/
103+
private function isChildrenInStock(int $productId) : bool
104+
{
105+
$childrenIsInStock = false;
106+
$childrenIds = $this->bundleType->getChildrenIds($productId, true);
107+
$stockItems = $this->getStockItems(array_merge(...array_values($childrenIds)));
108+
foreach ($childrenIds as $childrenIdsPerOption) {
109+
$childrenIsInStock = false;
110+
foreach ($childrenIdsPerOption as $id) {
111+
$stockItem = $stockItems[$id] ?? null;
112+
if ($stockItem && $stockItem->getIsInStock()) {
113+
$childrenIsInStock = true;
114+
break;
115+
}
116+
}
117+
if (!$childrenIsInStock) {
118+
break;
119+
}
120+
}
121+
122+
return $childrenIsInStock;
123+
}
124+
125+
/**
126+
* Check if parent item should be updated
127+
*
128+
* @param StockItemInterface $parentStockItem
129+
* @param bool $childrenIsInStock
130+
* @return bool
131+
*/
132+
private function isNeedToUpdateParent(
133+
StockItemInterface $parentStockItem,
134+
bool $childrenIsInStock
135+
): bool {
136+
return $parentStockItem->getIsInStock() !== $childrenIsInStock &&
137+
($childrenIsInStock === false || $parentStockItem->getStockStatusChangedAuto());
138+
}
139+
140+
/**
141+
* Get stock items for provided product IDs
142+
*
143+
* @param array $productIds
144+
* @return StockItemInterface[]
145+
*/
146+
private function getStockItems(array $productIds): array
147+
{
148+
$criteria = $this->criteriaInterfaceFactory->create();
149+
$criteria->setScopeFilter($this->stockConfiguration->getDefaultScopeId());
150+
$criteria->setProductsFilter(array_unique($productIds));
151+
$stockItemCollection = $this->stockItemRepository->getList($criteria);
152+
153+
$stockItems = [];
154+
foreach ($stockItemCollection->getItems() as $stockItem) {
155+
$stockItems[$stockItem->getProductId()] = $stockItem;
156+
}
157+
158+
return $stockItems;
159+
}
160+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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\Bundle\Model\Inventory;
9+
10+
use Magento\Catalog\Api\Data\ProductInterface as Product;
11+
use Magento\CatalogInventory\Observer\ParentItemProcessorInterface;
12+
13+
/**
14+
* Bundle product stock item processor
15+
*/
16+
class ParentItemProcessor implements ParentItemProcessorInterface
17+
{
18+
/**
19+
* @var ChangeParentStockStatus
20+
*/
21+
private $changeParentStockStatus;
22+
23+
/**
24+
* @param ChangeParentStockStatus $changeParentStockStatus
25+
*/
26+
public function __construct(
27+
ChangeParentStockStatus $changeParentStockStatus
28+
) {
29+
$this->changeParentStockStatus = $changeParentStockStatus;
30+
}
31+
32+
/**
33+
* @inheritdoc
34+
*/
35+
public function process(Product $product)
36+
{
37+
$this->changeParentStockStatus->execute([$product->getId()]);
38+
}
39+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
9+
<actionGroups xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
10+
xsi:noNamespaceSchemaLocation="urn:magento:mftf:Test/etc/actionGroupSchema.xsd">
11+
<actionGroup name="AdminAssertSpecialPriceAttributeValueOnProductGridPageActionGroup">
12+
<annotations>
13+
<description>Assert special price attribute value from the catalog product grid page</description>
14+
</annotations>
15+
<arguments>
16+
<argument name="specialPriceColumn" type="string" defaultValue="Special Price"/>
17+
<argument name="expectedValue" type="string" defaultValue=""/>
18+
</arguments>
19+
<!-- Check the special price column are present in catalog product grid -->
20+
<seeElement selector="{{AdminProductGridSection.columnHeader(specialPriceColumn)}}" stepKey="seeSpecialPriceColumn"/>
21+
<!-- Grab the special price value from the catalog product grid -->
22+
<grabTextFrom selector="{{AdminProductGridSection.productGridCell('1', specialPriceColumn)}}" stepKey="getSpecialPrice"/>
23+
<assertStringContainsString stepKey="assertSpecialPricePercentageSymbol">
24+
<expectedResult type="string">{{expectedValue}}</expectedResult>
25+
<actualResult type="variable">$getSpecialPrice</actualResult>
26+
</assertStringContainsString>
27+
</actionGroup>
28+
</actionGroups>

0 commit comments

Comments
 (0)