Skip to content

Commit f6a1af4

Browse files
committed
Merge remote-tracking branch 'origin/MC-29449' into 2.4-develop-pr4
2 parents 9400c1e + edfc05b commit f6a1af4

File tree

7 files changed

+373
-19
lines changed

7 files changed

+373
-19
lines changed

app/code/Magento/CatalogRule/Observer/ProcessAdminFinalPriceObserver.php

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77

88
namespace Magento\CatalogRule\Observer;
99

10-
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
11-
use Magento\Framework\Registry;
1210
use Magento\Framework\Event\ObserverInterface;
11+
use Magento\Framework\Registry;
12+
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
13+
use Magento\Store\Model\StoreManagerInterface;
1314

1415
/**
1516
* Observer for applying catalog rules on product for admin area
@@ -23,6 +24,11 @@ class ProcessAdminFinalPriceObserver implements ObserverInterface
2324
*/
2425
protected $coreRegistry;
2526

27+
/**
28+
* @var StoreManagerInterface
29+
*/
30+
protected $storeManager;
31+
2632
/**
2733
* @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface
2834
*/
@@ -41,17 +47,20 @@ class ProcessAdminFinalPriceObserver implements ObserverInterface
4147
/**
4248
* @param RulePricesStorage $rulePricesStorage
4349
* @param Registry $coreRegistry
50+
* @param StoreManagerInterface $storeManager
4451
* @param \Magento\CatalogRule\Model\ResourceModel\RuleFactory $resourceRuleFactory
4552
* @param TimezoneInterface $localeDate
4653
*/
4754
public function __construct(
4855
RulePricesStorage $rulePricesStorage,
4956
Registry $coreRegistry,
57+
StoreManagerInterface $storeManager,
5058
\Magento\CatalogRule\Model\ResourceModel\RuleFactory $resourceRuleFactory,
5159
TimezoneInterface $localeDate
5260
) {
5361
$this->rulePricesStorage = $rulePricesStorage;
5462
$this->coreRegistry = $coreRegistry;
63+
$this->storeManager = $storeManager;
5564
$this->resourceRuleFactory = $resourceRuleFactory;
5665
$this->localeDate = $localeDate;
5766
}
@@ -61,6 +70,7 @@ public function __construct(
6170
*
6271
* @param \Magento\Framework\Event\Observer $observer
6372
* @return $this
73+
* @throws \Magento\Framework\Exception\NoSuchEntityException
6474
*/
6575
public function execute(\Magento\Framework\Event\Observer $observer)
6676
{
@@ -74,13 +84,17 @@ public function execute(\Magento\Framework\Event\Observer $observer)
7484
$wId = $ruleData->getWebsiteId();
7585
$gId = $ruleData->getCustomerGroupId();
7686
$pId = $product->getId();
77-
7887
$key = "{$date->format('Y-m-d H:i:s')}|{$wId}|{$gId}|{$pId}";
7988
} elseif ($product->getWebsiteId() !== null && $product->getCustomerGroupId() !== null) {
8089
$wId = $product->getWebsiteId();
8190
$gId = $product->getCustomerGroupId();
8291
$pId = $product->getId();
8392
$key = "{$date->format('Y-m-d H:i:s')}|{$wId}|{$gId}|{$pId}";
93+
} elseif ($product->getWebsiteId() === null && $product->getCustomerGroupId() !== null) {
94+
$wId = $this->storeManager->getStore($storeId)->getWebsiteId();
95+
$gId = $product->getCustomerGroupId();
96+
$pId = $product->getId();
97+
$key = "{$date->format('Y-m-d H:i:s')}|{$wId}|{$gId}|{$pId}";
8498
}
8599

86100
if ($key) {
Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\CatalogRule\Test\Unit\Observer;
7+
8+
use Magento\Catalog\Model\Product;
9+
use Magento\CatalogRule\Model\ResourceModel\RuleFactory;
10+
use Magento\CatalogRule\Observer\ProcessAdminFinalPriceObserver;
11+
use Magento\CatalogRule\Observer\RulePricesStorage;
12+
use Magento\Framework\Event;
13+
use Magento\Framework\Event\Observer;
14+
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
15+
use Magento\Framework\TestFramework\Unit\Helper\ObjectManager;
16+
use Magento\Store\Model\Store;
17+
use Magento\Store\Model\StoreManagerInterface;
18+
use Magento\Ui\Component\Form\Element\DataType\Date;
19+
use PHPUnit\Framework\TestCase;
20+
21+
/**
22+
* Class ProcessAdminFinalPriceObserverTest
23+
*
24+
* Test class for Observer for applying catalog rules on product for admin area
25+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
26+
*/
27+
class ProcessAdminFinalPriceObserverTest extends TestCase
28+
{
29+
/**
30+
* @var ProcessAdminFinalPriceObserver
31+
*/
32+
private $observer;
33+
34+
/**
35+
* Store Manager mock
36+
*
37+
* @var StoreManagerInterface
38+
*/
39+
private $storeManagerMock;
40+
41+
/**
42+
* Locale Date mock
43+
*
44+
* @var TimezoneInterface
45+
*/
46+
private $localeDateMock;
47+
48+
/**
49+
* Resource Rule Factory mock
50+
*
51+
* @var RuleFactory
52+
*/
53+
private $resourceRuleFactoryMock;
54+
55+
/**
56+
* Rule Prices Storage mock
57+
*
58+
* @var RulePricesStorage
59+
*/
60+
private $rulePricesStorageMock;
61+
62+
/**
63+
* @var Event|\PHPUnit_Framework_MockObject_MockObject
64+
*/
65+
private $eventMock;
66+
67+
/**
68+
* @var Observer|\PHPUnit\Framework\MockObject\MockObject
69+
*/
70+
private $observerMock;
71+
72+
protected function setUp()
73+
{
74+
$this->observerMock = $this
75+
->getMockBuilder(Observer::class)
76+
->disableOriginalConstructor()
77+
->getMock();
78+
$this->eventMock = $this
79+
->getMockBuilder(Event::class)
80+
->setMethods(['getProduct'])
81+
->disableOriginalConstructor()
82+
->getMock();
83+
$this->rulePricesStorageMock = $this->getMockBuilder(RulePricesStorage::class)
84+
->setMethods(['getWebsiteId', 'getRulePrice', 'getCustomerGroupId', 'setRulePrice'])
85+
->disableOriginalConstructor()
86+
->getMock();
87+
$this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class)
88+
->setMethods(['getStore'])
89+
->disableOriginalConstructor()
90+
->getMockForAbstractClass();
91+
$this->resourceRuleFactoryMock = $this->getMockBuilder(RuleFactory::class)
92+
->setMethods(['create'])
93+
->disableOriginalConstructor()
94+
->getMock();
95+
$this->localeDateMock = $this->getMockBuilder(TimezoneInterface::class)
96+
->setMethods(['scopeDate'])
97+
->disableOriginalConstructor()
98+
->getMockForAbstractClass();
99+
$objectManagerHelper = new ObjectManager($this);
100+
$this->observer = $objectManagerHelper->getObject(
101+
ProcessAdminFinalPriceObserver::class,
102+
[
103+
'rulePricesStorage' => $this->rulePricesStorageMock,
104+
'storeManager' => $this->storeManagerMock,
105+
'resourceRuleFactory' => $this->resourceRuleFactoryMock,
106+
'localeDate' => $this->localeDateMock
107+
]
108+
);
109+
}
110+
111+
public function testExecute()
112+
{
113+
$finalPrice = 20.00;
114+
$rulePrice = 10.00;
115+
$storeId = 2;
116+
$wId = 1;
117+
$gId = 4;
118+
$pId = 20;
119+
$localeDateFormat = 'Y-m-d H:i:s';
120+
$date = '2019-12-02 08:00:00';
121+
$storeMock = $this->createMock(Store::class);
122+
$this->observerMock
123+
->expects($this->atLeastOnce())
124+
->method('getEvent')
125+
->willReturn($this->eventMock);
126+
127+
$productMock = $this->getMockBuilder(Product::class)
128+
->setMethods(
129+
[
130+
'getStoreId',
131+
'getWebsiteId',
132+
'getId',
133+
'getData',
134+
'getCustomerGroupId',
135+
'setFinalPrice'
136+
]
137+
)
138+
->disableOriginalConstructor()
139+
->getMock();
140+
$dateMock = $this->getMockBuilder(Date::class)
141+
->setMethods(['format'])
142+
->disableOriginalConstructor()
143+
->getMock();
144+
145+
$this->localeDateMock->expects($this->once())
146+
->method('scopeDate')
147+
->with($storeId)
148+
->willReturn($dateMock);
149+
$dateMock->expects($this->once())
150+
->method('format')
151+
->with($localeDateFormat)
152+
->willReturn($date);
153+
$storeMock->expects($this->once())
154+
->method('getWebsiteId')
155+
->willReturn($wId);
156+
$this->storeManagerMock->expects($this->once())
157+
->method('getStore')
158+
->with($storeId)
159+
->willReturn($storeMock);
160+
$productMock->expects($this->once())
161+
->method('getStoreId')
162+
->willReturn($storeId);
163+
$productMock->expects($this->any())
164+
->method('getCustomerGroupId')
165+
->willReturn($gId);
166+
$productMock->expects($this->once())
167+
->method('getId')
168+
->willReturn($pId);
169+
$productMock->expects($this->once())
170+
->method('getData')
171+
->with('final_price')
172+
->willReturn($finalPrice);
173+
$this->rulePricesStorageMock->expects($this->any())
174+
->method('getCustomerGroupId')
175+
->willReturn($gId);
176+
$this->resourceRuleFactoryMock->expects($this->once())
177+
->method('create')
178+
->willReturn($this->rulePricesStorageMock);
179+
$this->rulePricesStorageMock->expects($this->any())
180+
->method('getRulePrice')
181+
->willReturn($rulePrice);
182+
$this->rulePricesStorageMock->expects($this->once())
183+
->method('setRulePrice')
184+
->willReturnSelf();
185+
$this->eventMock
186+
->expects($this->atLeastOnce())
187+
->method('getProduct')
188+
->willReturn($productMock);
189+
$this->assertEquals($this->observer, $this->observer->execute($this->observerMock));
190+
}
191+
}

dev/tests/integration/testsuite/Magento/CatalogRule/Model/Indexer/Product/PriceTest.php

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,13 @@
55
*/
66
namespace Magento\CatalogRule\Model\Indexer\Product;
77

8-
use Magento\TestFramework\Helper\Bootstrap;
9-
use Magento\CatalogRule\Model\ResourceModel\Rule;
10-
use Magento\Catalog\Model\ResourceModel\Product\Collection;
118
use Magento\Catalog\Api\ProductRepositoryInterface;
9+
use Magento\Catalog\Model\ProductRepository;
10+
use Magento\Catalog\Model\ResourceModel\Product\Collection;
11+
use Magento\CatalogRule\Model\ResourceModel\Rule;
1212
use Magento\Framework\Api\SearchCriteriaInterface;
1313
use Magento\Framework\Api\SortOrder;
14+
use Magento\TestFramework\Helper\Bootstrap;
1415

1516
class PriceTest extends \PHPUnit\Framework\TestCase
1617
{
@@ -56,6 +57,46 @@ public function testPriceApplying()
5657
$this->assertEquals($simpleProduct->getFinalPrice(), $confProduct->getMinimalPrice());
5758
}
5859

60+
/**
61+
* @magentoDataFixtureBeforeTransaction Magento/CatalogRule/_files/simple_products.php
62+
* @magentoDataFixtureBeforeTransaction Magento/CatalogRule/_files/catalog_rule_50_percent_off.php
63+
* @magentoDbIsolation enabled
64+
* @magentoAppIsolation enabled
65+
*/
66+
public function testPriceForSecondStore()
67+
{
68+
$customerGroupId = 1;
69+
$websiteId = 2;
70+
/** @var ProductRepository $productRepository */
71+
$productRepository = Bootstrap::getObjectManager()->create(
72+
ProductRepository::class
73+
);
74+
$simpleProduct = $productRepository->get('simple3');
75+
$simpleProduct->setPriceCalculation(true);
76+
$this->assertEquals('simple3', $simpleProduct->getSku());
77+
$this->assertFalse(
78+
$this->resourceRule->getRulePrice(
79+
new \DateTime(),
80+
$websiteId,
81+
$customerGroupId,
82+
$simpleProduct->getId()
83+
)
84+
);
85+
$indexerBuilder = Bootstrap::getObjectManager()->get(
86+
\Magento\CatalogRule\Model\Indexer\IndexBuilder::class
87+
);
88+
$indexerBuilder->reindexById($simpleProduct->getId());
89+
$this->assertEquals(
90+
$this->resourceRule->getRulePrice(
91+
new \DateTime(),
92+
$websiteId,
93+
$customerGroupId,
94+
$simpleProduct->getId()
95+
),
96+
25
97+
);
98+
}
99+
59100
/**
60101
* @magentoDataFixtureBeforeTransaction Magento/CatalogRule/_files/simple_products.php
61102
* @magentoDataFixtureBeforeTransaction Magento/CatalogRule/_files/rule_by_attribute.php
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
use Magento\TestFramework\Helper\Bootstrap;
8+
9+
/**
10+
* Creates simple Catalog Rule with the following data:
11+
* active, applied to all products, without time limits, with 50% off for all customers
12+
*/
13+
/** @var \Magento\CatalogRule\Model\Rule $rule */
14+
$catalogRule = Bootstrap::getObjectManager()->get(\Magento\CatalogRule\Model\RuleFactory::class)->create();
15+
$catalogRule->loadPost(
16+
[
17+
'name' => 'Test Catalog Rule 50% off',
18+
'is_active' => '1',
19+
'stop_rules_processing' => 0,
20+
'website_ids' => [2],
21+
'customer_group_ids' => [0, 1],
22+
'discount_amount' => 50,
23+
'simple_action' => 'by_percent',
24+
'from_date' => '',
25+
'to_date' => '',
26+
'sort_order' => 0,
27+
'sub_is_enable' => 0,
28+
'sub_discount_amount' => 0,
29+
'conditions' => [],
30+
]
31+
);
32+
$catalogRule->save();
33+
/** @var \Magento\CatalogRule\Model\Indexer\IndexBuilder $indexBuilder */
34+
$indexBuilder = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()
35+
->get(\Magento\CatalogRule\Model\Indexer\IndexBuilder::class);
36+
$indexBuilder->reindexFull();
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
$objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
8+
9+
/** @var \Magento\CatalogRule\Model\ResourceModel\Rule $catalogRuleResource */
10+
$catalogRuleResource = $objectManager->create(\Magento\CatalogRule\Model\ResourceModel\Rule::class);
11+
12+
//Retrieve second rule by name
13+
$select = $catalogRuleResource->getConnection()->select();
14+
$select->from($catalogRuleResource->getMainTable(), 'rule_id');
15+
$select->where('name = ?', 'Test Catalog Rule 50% off');
16+
$ruleId = $catalogRuleResource->getConnection()->fetchOne($select);
17+
18+
try {
19+
/** @var \Magento\CatalogRule\Api\CatalogRuleRepositoryInterface $ruleRepository */
20+
$ruleRepository = $objectManager->create(\Magento\CatalogRule\Api\CatalogRuleRepositoryInterface::class);
21+
$ruleRepository->deleteById($ruleId);
22+
} catch (\Exception $ex) {
23+
//Nothing to remove
24+
}
25+
26+
/** @var \Magento\CatalogRule\Model\Indexer\IndexBuilder $indexBuilder */
27+
$indexBuilder = $objectManager->get(\Magento\CatalogRule\Model\Indexer\IndexBuilder::class);
28+
$indexBuilder->reindexFull();

0 commit comments

Comments
 (0)