Skip to content

Commit 7edefd2

Browse files
committed
MC-39896: Catalog price rules are not included in CartItemPrices in the API
- Adding customer group to the customer session - Adding api test
1 parent 6e0c28c commit 7edefd2

11 files changed

+519
-0
lines changed
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
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\CatalogRuleGraphQl\Plugin\Pricing\Price;
9+
10+
use Magento\CatalogRule\Model\ResourceModel\Rule;
11+
use Magento\CatalogRule\Pricing\Price\CatalogRulePrice;
12+
use Magento\Framework\Stdlib\DateTime\TimezoneInterface;
13+
14+
/**
15+
* Class UpdateCatalogRulePrice
16+
*
17+
* Plugin to update catalog rule price based on customer group id
18+
*/
19+
class UpdateCatalogRulePrice
20+
{
21+
/**
22+
* @var TimezoneInterface
23+
*/
24+
private $dateTime;
25+
26+
/**
27+
* @var Rule
28+
*/
29+
private $ruleResource;
30+
31+
/**
32+
* @param TimezoneInterface $dateTime
33+
* @param Rule $ruleResource
34+
*/
35+
public function __construct(
36+
TimezoneInterface $dateTime,
37+
Rule $ruleResource
38+
) {
39+
$this->dateTime = $dateTime;
40+
$this->ruleResource = $ruleResource;
41+
}
42+
43+
/**
44+
* Returns catalog rule value for logged in customer group
45+
*
46+
* @param CatalogRulePrice $catalogRulePrice
47+
* @param float|boolean $value
48+
* @return float|boolean
49+
*/
50+
public function afterGetValue(
51+
CatalogRulePrice $catalogRulePrice,
52+
$value
53+
) {
54+
$product = $catalogRulePrice->getProduct();
55+
if ($product && $product->getCustomerGroupId()) {
56+
$store = $product->getStore();
57+
$value = $this->ruleResource->getRulePrice(
58+
$this->dateTime->scopeDate($store->getId()),
59+
$store->getWebsiteId(),
60+
$product->getCustomerGroupId(),
61+
$product->getId()
62+
);
63+
$value = $value ? (float) $value : false;
64+
}
65+
66+
return $value;
67+
}
68+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?xml version="1.0"?>
2+
<!--
3+
/**
4+
* Copyright © Magento, Inc. All rights reserved.
5+
* See COPYING.txt for license details.
6+
*/
7+
-->
8+
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
9+
<type name="Magento\CatalogRule\Pricing\Price\CatalogRulePrice">
10+
<plugin name="update_catalog_rule_price_for_logged_in_customer_group" type="Magento\CatalogRuleGraphQl\Plugin\Pricing\Price\UpdateCatalogRulePrice"/>
11+
</type>
12+
</config>
Lines changed: 175 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
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\GraphQl\CatalogGraphQl;
9+
10+
use Magento\GraphQl\GetCustomerAuthenticationHeader;
11+
use Magento\TestFramework\Helper\Bootstrap;
12+
use Magento\TestFramework\ObjectManager;
13+
use Magento\TestFramework\TestCase\GraphQlAbstract;
14+
15+
/**
16+
* Test class to verify catalog price rule is applied for
17+
* tier prices for different customer groups.
18+
*/
19+
class PriceRangeTest extends GraphQlAbstract
20+
{
21+
/**
22+
* @var ObjectManager|null
23+
*/
24+
private $objectManager;
25+
26+
/**
27+
* @var GetCustomerAuthenticationHeader
28+
*/
29+
private $getCustomerAuthenticationHeader;
30+
31+
protected function setUp(): void
32+
{
33+
$this->objectManager = Bootstrap::getObjectManager();
34+
$this->getCustomerAuthenticationHeader = $this->objectManager->get(GetCustomerAuthenticationHeader::class);
35+
}
36+
37+
/**
38+
* Test for checking if catalog rule price has been applied for all customer group
39+
*
40+
* @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
41+
* @magentoApiDataFixture Magento/CatalogRule/_files/catalog_rule_25_customer_group_all.php
42+
*/
43+
public function testCheckIfCatalogRuleIsAppliedForTierPriceForAllGroups(): void
44+
{
45+
$productSku = 'simple';
46+
$query = $this->getProductSearchQuery($productSku);
47+
48+
$response = $this->graphQlQuery($query);
49+
50+
$this->assertNotEmpty($response['products']);
51+
$priceRange = $response['products']['items'][0]['price_range'];
52+
$this->assertEquals(10, $priceRange['minimum_price']['regular_price']['value']);
53+
$this->assertEquals(7.5, $priceRange['minimum_price']['final_price']['value']);
54+
$this->assertEquals(2.5, $priceRange['minimum_price']['discount']['amount_off']);
55+
$this->assertEquals(25, $priceRange['minimum_price']['discount']['percent_off']);
56+
$this->assertEquals(10, $priceRange['maximum_price']['regular_price']['value']);
57+
$this->assertEquals(7.5, $priceRange['maximum_price']['final_price']['value']);
58+
$this->assertEquals(2.5, $priceRange['maximum_price']['discount']['amount_off']);
59+
$this->assertEquals(25, $priceRange['maximum_price']['discount']['percent_off']);
60+
}
61+
62+
/**
63+
* Test for checking if catalog rule price has been applied for registered customer
64+
*
65+
* @magentoApiDataFixture Magento/Customer/_files/customer.php
66+
* @magentoApiDataFixture Magento/Catalog/_files/simple_product_with_tier_prices_for_logged_in_group.php
67+
* @magentoApiDataFixture Magento/CatalogRule/_files/catalog_rule_50_registered_customer_group.php
68+
*/
69+
public function testCheckIfCatalogRuleIsAppliedForTierPriceForRegisteredCustomer(): void
70+
{
71+
$productSku = 'simple';
72+
$query = $this->getProductSearchQuery($productSku);
73+
$response = $this->graphQlQuery(
74+
$query,
75+
[],
76+
'',
77+
$this->getCustomerAuthenticationHeader->execute('customer@example.com', 'password')
78+
);
79+
80+
$this->assertNotEmpty($response['products']);
81+
$priceRange = $response['products']['items'][0]['price_range'];
82+
$this->assertEquals(10, $priceRange['minimum_price']['regular_price']['value']);
83+
$this->assertEquals(5, $priceRange['minimum_price']['final_price']['value']);
84+
$this->assertEquals(5, $priceRange['minimum_price']['discount']['amount_off']);
85+
$this->assertEquals(50, $priceRange['minimum_price']['discount']['percent_off']);
86+
$this->assertEquals(10, $priceRange['maximum_price']['regular_price']['value']);
87+
$this->assertEquals(5, $priceRange['maximum_price']['final_price']['value']);
88+
$this->assertEquals(5, $priceRange['maximum_price']['discount']['amount_off']);
89+
$this->assertEquals(50, $priceRange['maximum_price']['discount']['percent_off']);
90+
}
91+
92+
/**
93+
* Test for checking if catalog rule price has been applied for guest
94+
*
95+
* @magentoApiDataFixture Magento/Catalog/_files/simple_product_with_tier_prices_for_not_logged_in_group.php
96+
* @magentoApiDataFixture Magento/CatalogRule/_files/catalog_rule_10_off_not_logged.php
97+
*/
98+
public function testCheckIfCatalogRuleIsAppliedForTierPriceForGuest(): void
99+
{
100+
$productSku = 'simple';
101+
$query = $this->getProductSearchQuery($productSku);
102+
$response = $this->graphQlQuery($query);
103+
104+
$this->assertNotEmpty($response['products']);
105+
$priceRange = $response['products']['items'][0]['price_range'];
106+
$this->assertEquals(10, $priceRange['minimum_price']['regular_price']['value']);
107+
$this->assertEquals(9, $priceRange['minimum_price']['final_price']['value']);
108+
$this->assertEquals(1, $priceRange['minimum_price']['discount']['amount_off']);
109+
$this->assertEquals(10, $priceRange['minimum_price']['discount']['percent_off']);
110+
$this->assertEquals(10, $priceRange['maximum_price']['regular_price']['value']);
111+
$this->assertEquals(9, $priceRange['maximum_price']['final_price']['value']);
112+
$this->assertEquals(1, $priceRange['maximum_price']['discount']['amount_off']);
113+
$this->assertEquals(10, $priceRange['maximum_price']['discount']['percent_off']);
114+
}
115+
116+
/**
117+
* Get a query which user filter for product sku and returns price_tiers
118+
*
119+
* @param string $productSku
120+
* @return string
121+
*/
122+
private function getProductSearchQuery(string $productSku): string
123+
{
124+
return <<<QUERY
125+
{
126+
products(filter: {sku: {eq: "{$productSku}"}}) {
127+
items {
128+
name
129+
sku
130+
price_range {
131+
minimum_price {
132+
regular_price {
133+
value
134+
currency
135+
}
136+
final_price {
137+
value
138+
currency
139+
}
140+
discount {
141+
amount_off
142+
percent_off
143+
}
144+
}
145+
maximum_price {
146+
regular_price {
147+
value
148+
currency
149+
}
150+
final_price {
151+
value
152+
currency
153+
}
154+
discount {
155+
amount_off
156+
percent_off
157+
}
158+
}
159+
}
160+
price_tiers{
161+
discount{
162+
amount_off
163+
percent_off
164+
}
165+
final_price{
166+
value
167+
}
168+
quantity
169+
}
170+
}
171+
}
172+
}
173+
QUERY;
174+
}
175+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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+
use Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory;
9+
use Magento\Catalog\Api\Data\ProductTierPriceExtensionFactory;
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Store\Api\WebsiteRepositoryInterface;
12+
use Magento\TestFramework\Helper\Bootstrap;
13+
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
14+
use Magento\Customer\Model\Group;
15+
16+
Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple.php');
17+
18+
$objectManager = Bootstrap::getObjectManager();
19+
$productRepository = $objectManager->create(ProductRepositoryInterface::class);
20+
$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class);
21+
$tpExtensionAttributesFactory = $objectManager->get(ProductTierPriceExtensionFactory::class);
22+
$product = $productRepository->get('simple', false, null, true);
23+
$adminWebsite = $objectManager->get(WebsiteRepositoryInterface::class)->get('admin');
24+
$tierPriceExtensionAttributes = $tpExtensionAttributesFactory->create()->setWebsiteId($adminWebsite->getId());
25+
$pricesForCustomerGroupsInput = [
26+
[
27+
'customer_group_id' => '1',
28+
'percentage_value'=> null,
29+
'qty'=> 1,
30+
'value'=> 20
31+
],
32+
[
33+
'customer_group_id' => '1',
34+
'percentage_value'=> null,
35+
'qty'=> 2,
36+
'value'=> 30
37+
]
38+
];
39+
$productTierPrices = [];
40+
foreach ($pricesForCustomerGroupsInput as $price) {
41+
$productTierPrices[] = $tierPriceFactory->create(
42+
[
43+
'data' => $price
44+
]
45+
)->setExtensionAttributes($tierPriceExtensionAttributes);
46+
}
47+
$product->setTierPrices($productTierPrices);
48+
$productRepository->save($product);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
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+
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
9+
10+
Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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+
use Magento\Catalog\Api\Data\ProductTierPriceInterfaceFactory;
9+
use Magento\Catalog\Api\Data\ProductTierPriceExtensionFactory;
10+
use Magento\Catalog\Api\ProductRepositoryInterface;
11+
use Magento\Store\Api\WebsiteRepositoryInterface;
12+
use Magento\TestFramework\Helper\Bootstrap;
13+
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
14+
use Magento\Customer\Model\Group;
15+
16+
Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple.php');
17+
18+
$objectManager = Bootstrap::getObjectManager();
19+
$productRepository = $objectManager->create(ProductRepositoryInterface::class);
20+
$tierPriceFactory = $objectManager->get(ProductTierPriceInterfaceFactory::class);
21+
$tpExtensionAttributesFactory = $objectManager->get(ProductTierPriceExtensionFactory::class);
22+
$product = $productRepository->get('simple', false, null, true);
23+
$adminWebsite = $objectManager->get(WebsiteRepositoryInterface::class)->get('admin');
24+
$tierPriceExtensionAttributes = $tpExtensionAttributesFactory->create()->setWebsiteId($adminWebsite->getId());
25+
$pricesForCustomerGroupsInput = [
26+
[
27+
'customer_group_id' => Group::NOT_LOGGED_IN_ID,
28+
'percentage_value'=> null,
29+
'qty'=> 1,
30+
'value'=> 50
31+
],
32+
[
33+
'customer_group_id' => Group::NOT_LOGGED_IN_ID,
34+
'percentage_value'=> null,
35+
'qty'=> 2,
36+
'value'=> 80
37+
]
38+
];
39+
$productTierPrices = [];
40+
foreach ($pricesForCustomerGroupsInput as $price) {
41+
$productTierPrices[] = $tierPriceFactory->create(
42+
[
43+
'data' => $price
44+
]
45+
)->setExtensionAttributes($tierPriceExtensionAttributes);
46+
}
47+
$product->setTierPrices($productTierPrices);
48+
$productRepository->save($product);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
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+
use Magento\TestFramework\Workaround\Override\Fixture\Resolver;
9+
10+
Resolver::getInstance()->requireDataFixture('Magento/Catalog/_files/product_simple_rollback.php');

0 commit comments

Comments
 (0)