Skip to content

Commit 0a3b703

Browse files
authored
Merge pull request #10263 from adobe-commerce-tier-4/PR_2025_12_03_chittima
[Support Tier-4 chittima] 12-03-2025 Regular delivery of bugfixes and improvements
2 parents 265cbda + c41a42b commit 0a3b703

File tree

15 files changed

+810
-100
lines changed

15 files changed

+810
-100
lines changed

app/code/Magento/Bundle/Block/Catalog/Product/View/Type/Bundle.php

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Magento\Framework\Json\EncoderInterface;
2121
use Magento\Framework\Locale\FormatInterface;
2222
use Magento\Framework\ObjectManager\ResetAfterRequestInterface;
23+
use Magento\Framework\Pricing\PriceCurrencyInterface;
2324
use Magento\Framework\Stdlib\ArrayUtils;
2425

2526
/**
@@ -71,6 +72,11 @@ class Bundle extends AbstractView implements ResetAfterRequestInterface
7172
*/
7273
private $optionsPosition = [];
7374

75+
/**
76+
* @var PriceCurrencyInterface
77+
*/
78+
private $priceCurrency;
79+
7480
/**
7581
* @param Context $context
7682
* @param ArrayUtils $arrayUtils
@@ -80,6 +86,7 @@ class Bundle extends AbstractView implements ResetAfterRequestInterface
8086
* @param FormatInterface $localeFormat
8187
* @param array $data
8288
* @param CollectionProcessor|null $catalogRuleProcessor
89+
* @param PriceCurrencyInterface|null $priceCurrency
8390
*/
8491
public function __construct(
8592
Context $context,
@@ -89,7 +96,8 @@ public function __construct(
8996
EncoderInterface $jsonEncoder,
9097
FormatInterface $localeFormat,
9198
array $data = [],
92-
?CollectionProcessor $catalogRuleProcessor = null
99+
?CollectionProcessor $catalogRuleProcessor = null,
100+
?PriceCurrencyInterface $priceCurrency = null
93101
) {
94102
$this->catalogProduct = $catalogProduct;
95103
$this->productPriceFactory = $productPrice;
@@ -102,6 +110,8 @@ public function __construct(
102110
);
103111
$this->catalogRuleProcessor = $catalogRuleProcessor ?? ObjectManager::getInstance()
104112
->get(CollectionProcessor::class);
113+
$this->priceCurrency = $priceCurrency ?? ObjectManager::getInstance()
114+
->get(PriceCurrencyInterface::class);
105115
}
106116

107117
/**
@@ -251,13 +261,13 @@ private function getSelectionItemData(Product $product, Product $selection)
251261
'optionId' => $selection->getId(),
252262
'prices' => [
253263
'oldPrice' => [
254-
'amount' => $oldPrice,
264+
'amount' => $this->priceCurrency->roundPrice($oldPrice),
255265
],
256266
'basePrice' => [
257-
'amount' => $basePrice,
267+
'amount' => $this->priceCurrency->roundPrice($basePrice),
258268
],
259269
'finalPrice' => [
260-
'amount' => $finalPrice,
270+
'amount' => $this->priceCurrency->roundPrice($finalPrice),
261271
],
262272
],
263273
'priceType' => $selection->getSelectionPriceType(),

app/code/Magento/Bundle/Pricing/Adjustment/Calculator.php

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -323,27 +323,15 @@ protected function calculateDynamicBundleAmount($basePriceValue, $bundleProduct,
323323
}
324324
}
325325

326-
/** @var Store $store */
327-
$store = $bundleProduct->getStore();
328-
$roundingMethod = $this->taxHelper->getCalculationAlgorithm($store);
329326
foreach ($amountList as $amountInfo) {
330327
/** @var AmountInterface $itemAmount */
331328
$itemAmount = $amountInfo['amount'];
332329
$qty = $amountInfo['quantity'];
333-
334-
if ($roundingMethod != TaxCalculationInterface::CALC_TOTAL_BASE) {
335-
//We need to round the individual selection first
336-
$fullAmount += ($this->priceCurrency->round($itemAmount->getValue()) * $qty);
337-
foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) {
338-
$adjustment = $this->priceCurrency->round($adjustment) * $qty;
339-
$adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment;
340-
}
341-
} else {
342-
$fullAmount += ($itemAmount->getValue() * $qty);
343-
foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) {
344-
$adjustment = $adjustment * $qty;
345-
$adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment;
346-
}
330+
//We need to round the individual selection first
331+
$fullAmount += ($this->priceCurrency->round($itemAmount->getValue()) * $qty);
332+
foreach ($itemAmount->getAdjustmentAmounts() as $code => $adjustment) {
333+
$adjustment = $this->priceCurrency->round($adjustment) * $qty;
334+
$adjustments[$code] = isset($adjustments[$code]) ? $adjustments[$code] + $adjustment : $adjustment;
347335
}
348336
}
349337
if (is_array($exclude) == false) {

app/code/Magento/Bundle/Test/Unit/Block/Catalog/Product/View/Type/BundleTest.php

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,13 @@
2121
use Magento\Bundle\Pricing\Price\BundleOptionPrice;
2222
use Magento\Bundle\Pricing\Price\TierPrice;
2323
use Magento\Catalog\Helper\Product;
24-
use Magento\Catalog\Pricing\Price\BasePrice;
2524
use Magento\Catalog\Pricing\Price\FinalPrice;
2625
use Magento\Catalog\Pricing\Price\RegularPrice;
2726
use Magento\CatalogRule\Model\ResourceModel\Product\CollectionProcessor;
2827
use Magento\Framework\DataObject;
2928
use Magento\Framework\Escaper;
3029
use Magento\Framework\Event\ManagerInterface;
3130
use Magento\Framework\Json\Encoder;
32-
use Magento\Framework\Pricing\Amount\AmountInterface;
3331
use Magento\Framework\Pricing\PriceInfo\Base;
3432
use Magento\Framework\Registry;
3533
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
@@ -77,6 +75,11 @@ class BundleTest extends TestCase
7775
*/
7876
private $escaperMock;
7977

78+
/**
79+
* @var \Magento\Directory\Model\PriceCurrency|MockObject
80+
*/
81+
private $priceCurrency;
82+
8083
/**
8184
* @inheritDoc
8285
*/
@@ -93,6 +96,8 @@ protected function setUp(): void
9396
$this->jsonEncoder = $this->createMock(Encoder::class);
9497
$this->catalogProduct = $this->createMock(Product::class);
9598
$this->escaperMock = $this->createMock(Escaper::class);
99+
$this->priceCurrency = $this->createMock(\Magento\Directory\Model\PriceCurrency::class);
100+
96101
/** @var BundleBlock $bundleBlock */
97102
$this->bundleBlock = $objectHelper->getObject(
98103
BundleBlock::class,
@@ -102,7 +107,8 @@ protected function setUp(): void
102107
'jsonEncoder' => $this->jsonEncoder,
103108
'productPrice' => $this->bundleProductPriceFactory,
104109
'catalogProduct' => $this->catalogProduct,
105-
'escaper' => $this->escaperMock
110+
'escaper' => $this->escaperMock,
111+
'priceCurrency' => $this->priceCurrency
106112
]
107113
);
108114

@@ -252,6 +258,11 @@ public function testGetJsonConfigFixedPriceBundle(): void
252258
)
253259
]
254260
);
261+
262+
$this->priceCurrency->expects($this->exactly(3))
263+
->method('roundPrice')
264+
->willReturn($basePriceValue);
265+
255266
$bundleOptionPriceMock = $this->getBundleOptionPriceMock(
256267
$baseAmount,
257268
$baseAmount,

app/code/Magento/Catalog/Model/Product/Price/Validation/TierPriceValidator.php

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
use Magento\Catalog\Helper\Data;
2121
use Magento\Store\Model\ScopeInterface;
2222
use Magento\Framework\Exception\NoSuchEntityException;
23+
use Magento\Store\Model\StoreManagerInterface;
2324

2425
/**
2526
* Validate Tier Price and check duplication
@@ -88,6 +89,11 @@ class TierPriceValidator implements ResetAfterRequestInterface
8889
*/
8990
private $scopeConfig;
9091

92+
/**
93+
* @var StoreManagerInterface
94+
*/
95+
private StoreManagerInterface $storeManager;
96+
9197
/**
9298
* TierPriceValidator constructor.
9399
*
@@ -99,6 +105,7 @@ class TierPriceValidator implements ResetAfterRequestInterface
99105
* @param array $allowedProductTypes [optional]
100106
* @param ResourceConnection|null $resourceConnection
101107
* @param ScopeConfigInterface|null $scopeConfig
108+
* @param StoreManagerInterface|null $storeManager
102109
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
103110
*/
104111
public function __construct(
@@ -109,7 +116,8 @@ public function __construct(
109116
ProductRepositoryInterface $productRepository,
110117
array $allowedProductTypes = [],
111118
?ResourceConnection $resourceConnection = null,
112-
?ScopeConfigInterface $scopeConfig = null
119+
?ScopeConfigInterface $scopeConfig = null,
120+
?StoreManagerInterface $storeManager = null
113121
) {
114122
$this->productIdLocator = $productIdLocator;
115123
$this->websiteRepository = $websiteRepository;
@@ -119,6 +127,7 @@ public function __construct(
119127
$this->allowedProductTypes = $allowedProductTypes;
120128
$this->resourceConnection = $resourceConnection ?: ObjectManager::getInstance()->get(ResourceConnection::class);
121129
$this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class);
130+
$this->storeManager = $storeManager ?: ObjectManager::getInstance()->get(StoreManagerInterface::class);
122131
}
123132

124133
/**
@@ -354,12 +363,12 @@ private function checkWebsite(TierPriceInterface $price, $key, Result $validatio
354363
{
355364
try {
356365
$this->websiteRepository->getById($price->getWebsiteId());
357-
$isWebsiteScope = $this->scopeConfig
358-
->isSetFlag(
359-
Data::XML_PATH_PRICE_SCOPE,
360-
ScopeInterface::SCOPE_STORE,
361-
ScopeConfigInterface::SCOPE_TYPE_DEFAULT
362-
);
366+
$defaultStoreView = $this->storeManager->getDefaultStoreView();
367+
$isWebsiteScope = $this->scopeConfig->isSetFlag(
368+
Data::XML_PATH_PRICE_SCOPE,
369+
ScopeInterface::SCOPE_STORE,
370+
$defaultStoreView->getCode()
371+
);
363372
if (!$isWebsiteScope && (int) $this->allWebsitesValue !== $price->getWebsiteId()) {
364373
throw NoSuchEntityException::singleField('website_id', $price->getWebsiteId());
365374
}

app/code/Magento/Catalog/Test/Unit/Model/Product/Price/Validation/TierPriceValidatorTest.php

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@
1919
use Magento\Framework\DB\Select;
2020
use Magento\Framework\Exception\NoSuchEntityException;
2121
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
22+
use Magento\Store\Api\Data\StoreInterface;
2223
use Magento\Store\Api\Data\WebsiteInterface;
2324
use Magento\Store\Api\WebsiteRepositoryInterface;
25+
use Magento\Store\Model\StoreManagerInterface;
2426
use PHPUnit\Framework\MockObject\MockObject;
2527
use PHPUnit\Framework\TestCase;
2628

@@ -76,6 +78,11 @@ class TierPriceValidatorTest extends TestCase
7678
*/
7779
private $adapterInterface;
7880

81+
/**
82+
* @var StoreManagerInterface|MockObject
83+
*/
84+
private StoreManagerInterface $storeManager;
85+
7986
/**
8087
* {@inheritdoc}
8188
*/
@@ -107,6 +114,7 @@ protected function setUp(): void
107114
$this->adapterInterface = $this->getMockBuilder(AdapterInterface::class)
108115
->disableOriginalConstructor()
109116
->getMockForAbstractClass();
117+
$this->storeManager = $this->createMock(StoreManagerInterface::class);
110118

111119
$objectManagerHelper = new ObjectManager($this);
112120
$this->tierPriceValidator = $objectManagerHelper->getObject(
@@ -117,7 +125,8 @@ protected function setUp(): void
117125
'validationResult' => $this->validationResult,
118126
'invalidSkuProcessor' => $this->invalidSkuProcessor,
119127
'productRepository' => $this->productRepository,
120-
'resourceConnection' => $this->resourceConnectionMock
128+
'resourceConnection' => $this->resourceConnectionMock,
129+
'storeManager' => $this->storeManager
121130
]
122131
);
123132
}
@@ -237,8 +246,12 @@ public function testValidateSkus()
237246
public function testRetrieveValidationResult(array $returned)
238247
{
239248
$sku = 'ASDF234234';
249+
$defaultStoreViewCode = 'default';
240250
$prices = [$this->tierPrice];
241251
$existingPrices = [$this->tierPrice];
252+
$defaultStoreView = $this->createMock(StoreInterface::class);
253+
$defaultStoreView->expects($this->once())->method('getCode')->willReturn($defaultStoreViewCode);
254+
$this->storeManager->expects($this->once())->method('getDefaultStoreView')->willReturn($defaultStoreView);
242255
$this->prepareRetrieveValidationResultMethod($sku, $returned);
243256
$website = $this->getMockBuilder(WebsiteInterface::class)
244257
->disableOriginalConstructor()

0 commit comments

Comments
 (0)