Skip to content

Commit 419fbf3

Browse files
authored
Merge pull request #4842 from magento-honey-badgers/MC-18403
[honey] MC-18403: Pricing :: Product pricing schema
2 parents d27a28c + 8d69fde commit 419fbf3

File tree

28 files changed

+2464
-93
lines changed

28 files changed

+2464
-93
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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\BundleGraphQl\Model\Resolver\Product\Price;
9+
10+
use Magento\Bundle\Pricing\Price\FinalPrice;
11+
use Magento\Catalog\Pricing\Price\BasePrice;
12+
use Magento\Bundle\Model\Product\Price;
13+
use Magento\Catalog\Pricing\Price\RegularPrice;
14+
use Magento\CatalogGraphQl\Model\Resolver\Product\Price\ProviderInterface;
15+
use Magento\Framework\Pricing\Amount\AmountInterface;
16+
use Magento\Framework\Pricing\SaleableInterface;
17+
18+
/**
19+
* Provides pricing information for Bundle products
20+
*/
21+
class Provider implements ProviderInterface
22+
{
23+
/**
24+
* @inheritdoc
25+
*/
26+
public function getMinimalFinalPrice(SaleableInterface $product): AmountInterface
27+
{
28+
return $product->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getMinimalPrice();
29+
}
30+
31+
/**
32+
* @inheritdoc
33+
*/
34+
public function getMinimalRegularPrice(SaleableInterface $product): AmountInterface
35+
{
36+
return $product->getPriceInfo()->getPrice(RegularPrice::PRICE_CODE)->getMinimalPrice();
37+
}
38+
39+
/**
40+
* @inheritdoc
41+
*/
42+
public function getMaximalFinalPrice(SaleableInterface $product): AmountInterface
43+
{
44+
return $product->getPriceInfo()->getPrice(FinalPrice::PRICE_CODE)->getMaximalPrice();
45+
}
46+
47+
/**
48+
* @inheritdoc
49+
*/
50+
public function getMaximalRegularPrice(SaleableInterface $product): AmountInterface
51+
{
52+
return $product->getPriceInfo()->getPrice(RegularPrice::PRICE_CODE)->getMaximalPrice();
53+
}
54+
55+
/**
56+
* @inheritdoc
57+
*/
58+
public function getRegularPrice(SaleableInterface $product): AmountInterface
59+
{
60+
if ($product->getPriceType() == Price::PRICE_TYPE_FIXED) {
61+
return $product->getPriceInfo()->getPrice(BasePrice::PRICE_CODE)->getAmount();
62+
}
63+
return $product->getPriceInfo()->getPrice(RegularPrice::PRICE_CODE)->getAmount();
64+
}
65+
}

app/code/Magento/BundleGraphQl/etc/graphql/di.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,22 @@
4040
</argument>
4141
</arguments>
4242
</type>
43+
44+
45+
<type name="Magento\CatalogGraphQl\Model\Resolver\Product\Price\ProviderPool">
46+
<arguments>
47+
<argument name="providers" xsi:type="array">
48+
<item name="bundle" xsi:type="object">Magento\BundleGraphQl\Model\Resolver\Product\Price\Provider</item>
49+
</argument>
50+
</arguments>
51+
</type>
52+
<type name="Magento\CatalogGraphQl\Model\Resolver\Products\DataProvider\Product\CollectionProcessor\AttributeProcessor">
53+
<arguments>
54+
<argument name="fieldToAttributeMap" xsi:type="array">
55+
<item name="price_range" xsi:type="array">
56+
<item name="price_type" xsi:type="string">price_type</item>
57+
</item>
58+
</argument>
59+
</arguments>
60+
</type>
4361
</config>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
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\CatalogCustomerGraphQl\Model\Resolver\Customer;
9+
10+
use Magento\Customer\Api\GroupManagementInterface;
11+
use Magento\Customer\Api\CustomerRepositoryInterface;
12+
use Magento\Customer\Model\GroupManagement;
13+
use Magento\Framework\Exception\NoSuchEntityException;
14+
use Magento\Framework\GraphQl\Exception\GraphQlNoSuchEntityException;
15+
16+
/**
17+
* Get customer group
18+
*/
19+
class GetCustomerGroup
20+
{
21+
/**
22+
* @var GroupManagementInterface
23+
*/
24+
private $groupManagement;
25+
26+
/**
27+
* @var CustomerRepositoryInterface
28+
*/
29+
private $customerRepository;
30+
31+
/**
32+
* @param GroupManagementInterface $groupManagement
33+
* @param CustomerRepositoryInterface $customerRepository
34+
*/
35+
public function __construct(
36+
GroupManagementInterface $groupManagement,
37+
CustomerRepositoryInterface $customerRepository
38+
) {
39+
$this->groupManagement = $groupManagement;
40+
$this->customerRepository = $customerRepository;
41+
}
42+
43+
/**
44+
* Get customer group by id
45+
*
46+
* @param int|null $customerId
47+
* @return int
48+
* @throws GraphQlNoSuchEntityException
49+
*/
50+
public function execute(?int $customerId): int
51+
{
52+
if (!$customerId) {
53+
$customerGroupId = GroupManagement::NOT_LOGGED_IN_ID;
54+
} else {
55+
try {
56+
$customer = $this->customerRepository->getById($customerId);
57+
} catch (NoSuchEntityException $e) {
58+
throw new GraphQlNoSuchEntityException(
59+
__('Customer with id "%customer_id" does not exist.', ['customer_id' => $customerId]),
60+
$e
61+
);
62+
}
63+
$customerGroupId = $customer->getGroupId();
64+
}
65+
return (int)$customerGroupId;
66+
}
67+
}
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
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\CatalogCustomerGraphQl\Model\Resolver;
9+
10+
use Magento\Framework\GraphQl\Config\Element\Field;
11+
use Magento\Framework\GraphQl\Query\ResolverInterface;
12+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
13+
use Magento\Framework\Exception\LocalizedException;
14+
use Magento\Framework\GraphQl\Query\Resolver\ValueFactory;
15+
use Magento\CatalogCustomerGraphQl\Model\Resolver\Product\Price\Tiers;
16+
use Magento\CatalogCustomerGraphQl\Model\Resolver\Product\Price\TiersFactory;
17+
use Magento\CatalogCustomerGraphQl\Model\Resolver\Customer\GetCustomerGroup;
18+
use Magento\Store\Api\Data\StoreInterface;
19+
use Magento\CatalogGraphQl\Model\Resolver\Product\Price\Discount;
20+
use Magento\CatalogGraphQl\Model\Resolver\Product\Price\ProviderPool as PriceProviderPool;
21+
use Magento\Catalog\Api\Data\ProductTierPriceInterface;
22+
23+
/**
24+
* Resolver for price_tiers
25+
*/
26+
class PriceTiers implements ResolverInterface
27+
{
28+
/**
29+
* @var TiersFactory
30+
*/
31+
private $tiersFactory;
32+
33+
/**
34+
* @var ValueFactory
35+
*/
36+
private $valueFactory;
37+
38+
/**
39+
* @var GetCustomerGroup
40+
*/
41+
private $getCustomerGroup;
42+
43+
/**
44+
* @var int
45+
*/
46+
private $customerGroupId;
47+
48+
/**
49+
* @var Tiers
50+
*/
51+
private $tiers;
52+
53+
/**
54+
* @var Discount
55+
*/
56+
private $discount;
57+
58+
/**
59+
* @var PriceProviderPool
60+
*/
61+
private $priceProviderPool;
62+
63+
/**
64+
* @param ValueFactory $valueFactory
65+
* @param TiersFactory $tiersFactory
66+
* @param GetCustomerGroup $getCustomerGroup
67+
* @param Discount $discount
68+
* @param PriceProviderPool $priceProviderPool
69+
*/
70+
public function __construct(
71+
ValueFactory $valueFactory,
72+
TiersFactory $tiersFactory,
73+
GetCustomerGroup $getCustomerGroup,
74+
Discount $discount,
75+
PriceProviderPool $priceProviderPool
76+
) {
77+
$this->valueFactory = $valueFactory;
78+
$this->tiersFactory = $tiersFactory;
79+
$this->getCustomerGroup = $getCustomerGroup;
80+
$this->discount = $discount;
81+
$this->priceProviderPool = $priceProviderPool;
82+
}
83+
84+
/**
85+
* @inheritdoc
86+
*/
87+
public function resolve(
88+
Field $field,
89+
$context,
90+
ResolveInfo $info,
91+
array $value = null,
92+
array $args = null
93+
) {
94+
if (!isset($value['model'])) {
95+
throw new LocalizedException(__('"model" value should be specified'));
96+
}
97+
98+
if (empty($this->tiers)) {
99+
$this->customerGroupId = $this->getCustomerGroup->execute($context->getUserId());
100+
$this->tiers = $this->tiersFactory->create(['customerGroupId' => $this->customerGroupId]);
101+
}
102+
103+
$product = $value['model'];
104+
$productId = $product->getId();
105+
$this->tiers->addProductFilter($productId);
106+
107+
return $this->valueFactory->create(
108+
function () use ($productId, $context) {
109+
/** @var StoreInterface $store */
110+
$store = $context->getExtensionAttributes()->getStore();
111+
112+
$productPrice = $this->tiers->getProductRegularPrice($productId) ?? 0.0;
113+
$tierPrices = $this->tiers->getProductTierPrices($productId) ?? [];
114+
115+
return $this->formatProductTierPrices($tierPrices, $productPrice, $store);
116+
}
117+
);
118+
}
119+
120+
/**
121+
* Format tier prices for output
122+
*
123+
* @param ProductTierPriceInterface[] $tierPrices
124+
* @param float $productPrice
125+
* @param StoreInterface $store
126+
* @return array
127+
*/
128+
private function formatProductTierPrices(array $tierPrices, float $productPrice, StoreInterface $store): array
129+
{
130+
$tiers = [];
131+
132+
foreach ($tierPrices as $tierPrice) {
133+
$percentValue = $tierPrice->getExtensionAttributes()->getPercentageValue();
134+
if ($percentValue && is_numeric($percentValue)) {
135+
$discount = $this->discount->getDiscountByPercent($productPrice, (float)$percentValue);
136+
} else {
137+
$discount = $this->discount->getDiscountByDifference($productPrice, (float)$tierPrice->getValue());
138+
}
139+
140+
$tiers[] = [
141+
"discount" => $discount,
142+
"quantity" => $tierPrice->getQty(),
143+
"final_price" => [
144+
"value" => $tierPrice->getValue(),
145+
"currency" => $store->getCurrentCurrencyCode()
146+
]
147+
];
148+
}
149+
return $tiers;
150+
}
151+
}

0 commit comments

Comments
 (0)