Skip to content

#26121 - special price & tier price are coming in base currency #28890

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Jul 19, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\GraphQl\Query\Resolver\ValueFactory;
use Magento\Framework\Pricing\PriceCurrencyInterface;
use Magento\CatalogCustomerGraphQl\Model\Resolver\Product\Price\Tiers;
use Magento\CatalogCustomerGraphQl\Model\Resolver\Product\Price\TiersFactory;
use Magento\CatalogCustomerGraphQl\Model\Resolver\Customer\GetCustomerGroup;
Expand Down Expand Up @@ -60,25 +61,33 @@ class PriceTiers implements ResolverInterface
*/
private $priceProviderPool;

/**
* @var PriceCurrencyInterface
*/
private $priceCurrency;

/**
* @param ValueFactory $valueFactory
* @param TiersFactory $tiersFactory
* @param GetCustomerGroup $getCustomerGroup
* @param Discount $discount
* @param PriceProviderPool $priceProviderPool
* @param PriceCurrencyInterface $priceCurrency
*/
public function __construct(
ValueFactory $valueFactory,
TiersFactory $tiersFactory,
GetCustomerGroup $getCustomerGroup,
Discount $discount,
PriceProviderPool $priceProviderPool
PriceProviderPool $priceProviderPool,
PriceCurrencyInterface $priceCurrency
) {
$this->valueFactory = $valueFactory;
$this->tiersFactory = $tiersFactory;
$this->getCustomerGroup = $getCustomerGroup;
$this->discount = $discount;
$this->priceProviderPool = $priceProviderPool;
$this->priceCurrency = $priceCurrency;
}

/**
Expand Down Expand Up @@ -130,6 +139,7 @@ private function formatProductTierPrices(array $tierPrices, float $productPrice,
$tiers = [];

foreach ($tierPrices as $tierPrice) {
$tierPrice->setValue($this->priceCurrency->convertAndRound($tierPrice->getValue()));
$percentValue = $tierPrice->getExtensionAttributes()->getPercentageValue();
if ($percentValue && is_numeric($percentValue)) {
$discount = $this->discount->getDiscountByPercent($productPrice, (float)$percentValue);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\CatalogGraphQl\Model\Resolver\Product;

use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Pricing\Price\SpecialPrice as PricingSpecialPrice;

/**
* Resolver for Special Price
*/
class SpecialPrice implements ResolverInterface
{
/**
* @inheritdoc
*/
public function resolve(Field $field, $context, ResolveInfo $info, array $value = null, array $args = null)
{
/** @var ProductInterface $product */
$product = $value['model'];
/** @var PricingSpecialPrice $specialPrice */
$specialPrice = $product->getPriceInfo()->getPrice(PricingSpecialPrice::PRICE_CODE);

if ($specialPrice->getValue()) {
return $specialPrice->getValue();
}

return null;
}
}
2 changes: 1 addition & 1 deletion app/code/Magento/CatalogGraphQl/etc/schema.graphqls
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ interface ProductInterface @typeResolver(class: "Magento\\CatalogGraphQl\\Model\
sku: String @doc(description: "A number or code assigned to a product to identify the product, options, price, and manufacturer.")
description: ComplexTextValue @doc(description: "Detailed information about the product. The value can include simple HTML tags.") @resolver(class: "\\Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\ProductComplexTextAttribute")
short_description: ComplexTextValue @doc(description: "A short description of the product. Its use depends on the theme.") @resolver(class: "\\Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\ProductComplexTextAttribute")
special_price: Float @doc(description: "The discounted price of the product.")
special_price: Float @doc(description: "The discounted price of the product.") @resolver(class: "Magento\\CatalogGraphQl\\Model\\Resolver\\Product\\SpecialPrice")
special_from_date: String @doc(description: "The beginning date that a product has a special price.")
special_to_date: String @doc(description: "The end date that a product has a special price.")
attribute_set_id: Int @doc(description: "The attribute set assigned to the product.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\GraphQl\CatalogCustomer;

use Magento\GraphQl\GetCustomerAuthenticationHeader;
use Magento\TestFramework\TestCase\GraphQlAbstract;
use Magento\Store\Api\StoreRepositoryInterface;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\ObjectManager;

class PriceTiersTest extends GraphQlAbstract
{
/**
* @var ObjectManager
*/
private $objectManager;

/**
* @var GetCustomerAuthenticationHeader
*/
private $getCustomerAuthenticationHeader;

protected function setUp(): void
{
$this->objectManager = Bootstrap::getObjectManager();
$this->getCustomerAuthenticationHeader = $this->objectManager->get(GetCustomerAuthenticationHeader::class);
}

/**
* @magentoApiDataFixture Magento/Catalog/_files/product_simple.php
*/
public function testAllGroups()
{
$productSku = 'simple';
$query = $this->getProductSearchQuery($productSku);

$response = $this->graphQlQuery($query);

$itemTiers = $response['products']['items'][0]['price_tiers'];
$this->assertCount(5, $itemTiers);
$this->assertEquals(8, $this->getValueForQuantity(2, $itemTiers));
$this->assertEquals(5, $this->getValueForQuantity(3, $itemTiers));
$this->assertEquals(6, $this->getValueForQuantity(3.2, $itemTiers));
}

/**
* @magentoApiDataFixture Magento/Customer/_files/customer.php
* @magentoApiDataFixture Magento/Catalog/_files/simple_product_with_tier_prices_for_multiple_groups.php
*/
public function testLoggedInCustomer()
{
$productSku = 'simple';
$query = $this->getProductSearchQuery($productSku);
$response = $this->graphQlQuery(
$query,
[],
'',
$this->getCustomerAuthenticationHeader->execute('[email protected]', 'password')
);

$itemTiers = $response['products']['items'][0]['price_tiers'];
$this->assertCount(3, $itemTiers);
$this->assertEquals(9.25, $this->getValueForQuantity(2, $itemTiers));
$this->assertEquals(8.25, $this->getValueForQuantity(3, $itemTiers));
$this->assertEquals(7.25, $this->getValueForQuantity(5, $itemTiers));
}

/**
* @magentoApiDataFixture Magento/Store/_files/second_store_with_second_currency.php
* @magentoApiDataFixture Magento/Customer/_files/customer.php
* @magentoApiDataFixture Magento/Catalog/_files/simple_product_with_tier_prices_for_multiple_groups.php
*/
public function testSecondStoreViewWithCurrencyRate()
{
$storeViewCode = 'fixture_second_store';
$storeRepository = $this->objectManager->get(StoreRepositoryInterface::class);
$rate = $storeRepository->get($storeViewCode)->getCurrentCurrencyRate();
$productSku = 'simple';
$query = $this->getProductSearchQuery($productSku);
$headers = array_merge(
$this->getCustomerAuthenticationHeader->execute('[email protected]', 'password'),
$this->getHeaderStore($storeViewCode)
);

$response = $this->graphQlQuery(
$query,
[],
'',
$headers
);

$itemTiers = $response['products']['items'][0]['price_tiers'];
$this->assertCount(3, $itemTiers);
$this->assertEquals(round(9.25 * $rate, 2), $this->getValueForQuantity(2, $itemTiers));
$this->assertEquals(round(8.25 * $rate, 2), $this->getValueForQuantity(3, $itemTiers));
$this->assertEquals(round(7.25 * $rate, 2), $this->getValueForQuantity(5, $itemTiers));
}

/**
* Get the tier price value for the given product quantity
*
* @param float $quantity
* @param array $tiers
* @return float
*/
private function getValueForQuantity(float $quantity, array $tiers): float
{
$filteredResult = array_values(array_filter($tiers, function ($tier) use ($quantity) {
if ((float)$tier['quantity'] == $quantity) {
return $tier;
}
}));

return (float)$filteredResult[0]['final_price']['value'];
}

/**
* Get a query which user filter for product sku and returns price_tiers
*
* @param string $productSku
* @return string
*/
private function getProductSearchQuery(string $productSku): string
{
return <<<QUERY
{
products(filter: {sku: {eq: "{$productSku}"}}) {
items {
price_tiers {
final_price {
currency
value
}
discount {
amount_off
percent_off
}
quantity
}
}
}
}
QUERY;
}

/**
* Get array that would be used in request header
*
* @param string $storeViewCode
* @return array
*/
private function getHeaderStore(string $storeViewCode): array
{
return ['Store' => $storeViewCode];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

namespace Magento\GraphQl\CatalogCustomer;

use Magento\TestFramework\TestCase\GraphQlAbstract;
use Magento\Store\Api\StoreRepositoryInterface;
use Magento\TestFramework\Helper\Bootstrap;
use Magento\TestFramework\ObjectManager;

class SpecialPriceTest extends GraphQlAbstract
{
/**
* @var ObjectManager
*/
private $objectManager;

protected function setUp(): void
{
$this->objectManager = Bootstrap::getObjectManager();
}

/**
* @magentoApiDataFixture Magento/Catalog/_files/product_special_price.php
*/
public function testSpecialPrice()
{
$productSku = 'simple';
$query = $this->getProductSearchQuery($productSku);

$response = $this->graphQlQuery($query);

$specialPrice = (float)$response['products']['items'][0]['special_price'];
$this->assertEquals(5.99, $specialPrice);
}

/**
* @magentoApiDataFixture Magento/Store/_files/second_store_with_second_currency.php
* @magentoApiDataFixture Magento/Catalog/_files/product_special_price.php
*/
public function testSpecialPriceWithCurrencyRate()
{
$storeViewCode = 'fixture_second_store';
$storeRepository = $this->objectManager->get(StoreRepositoryInterface::class);
$rate = $storeRepository->get($storeViewCode)->getCurrentCurrencyRate();
$productSku = 'simple';
$query = $this->getProductSearchQuery($productSku);
$headers = $this->getHeaderStore($storeViewCode);

$response = $this->graphQlQuery(
$query,
[],
'',
$headers
);

$specialPrice = (float)$response['products']['items'][0]['special_price'];
$this->assertEquals(round(5.99 * $rate, 2), $specialPrice);
}

/**
* Get a query which user filter for product sku and returns special_price
*
* @param string $productSku
* @return string
*/
private function getProductSearchQuery(string $productSku): string
{
return <<<QUERY
{
products(filter: {sku: {eq: "{$productSku}"}}) {
items {
special_price
}
}
}
QUERY;
}

/**
* Get array that would be used in request header
*
* @param string $storeViewCode
* @return array
*/
private function getHeaderStore(string $storeViewCode): array
{
return ['Store' => $storeViewCode];
}
}
Loading