Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
dfc2a18
#40209 - Conditional TotalCollect Trigger for mutation and Virtual Carts
Oct 11, 2025
170d7bc
Merge branch '2.4-develop' into Fix-QuoteGraphQl-CartPrices-Performance
senthilengg Oct 11, 2025
82f2786
#40209 - Fixing Implicit Null of ScopeConfig
Oct 11, 2025
43760cc
#40209 - Fixing Static Tests
Oct 11, 2025
3fd68ba
#40209 - Removing Extenstion Attribute after Shipping getData()
Oct 13, 2025
a7ca4ed
Merge branch '2.4-develop' into Fix-QuoteGraphQl-CartPrices-Performance
senthilengg Oct 13, 2025
64c6b34
Merge branch '2.4-develop' into Fix-QuoteGraphQl-CartPrices-Performance
senthilengg Oct 15, 2025
1cbabde
Merge branch '2.4-develop' into Fix-QuoteGraphQl-CartPrices-Performance
senthilengg Oct 17, 2025
5474f24
Merge branch '2.4-develop' into Fix-QuoteGraphQl-CartPrices-Performance
senthilengg Oct 21, 2025
2c13e99
Fix copyright comment formatting in CartPrices.php
senthilengg Oct 21, 2025
723bb3d
Fix copyright notice formatting in CartPricesTest.php
senthilengg Oct 21, 2025
11b684c
Merge branch '2.4-develop' into Fix-QuoteGraphQl-CartPrices-Performance
senthilengg Oct 24, 2025
62f16f9
Merge branch '2.4-develop' into Fix-QuoteGraphQl-CartPrices-Performance
engcom-Hotel Oct 27, 2025
4b41a49
Merge branch '2.4-develop' into Fix-QuoteGraphQl-CartPrices-Performance
senthilengg Oct 29, 2025
602829c
#40209 - Fixing discount lable null and WebAPI Test Failures
Oct 29, 2025
0495e41
#40209 - Adding Discounts to graphql response retriving from extensio…
Oct 30, 2025
f4ee24a
#40209 - Made new params in constructor as optional and updated unit …
Oct 30, 2025
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
142 changes: 119 additions & 23 deletions app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php
/**
* Copyright 2019 Adobe
* Copyright 2025 Adobe
* All Rights Reserved.
*/
declare(strict_types=1);
Expand All @@ -13,13 +13,21 @@
use Magento\Framework\GraphQl\Config\Element\Field;
use Magento\Framework\GraphQl\Query\ResolverInterface;
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
use Magento\Framework\Api\DataObjectHelper;
use Magento\Framework\Api\ExtensibleDataInterface;
use Magento\Quote\Api\Data\TotalsInterface as QuoteTotalsInterface;
use Magento\Quote\Api\Data\TotalsInterfaceFactory;
use Magento\Quote\Api\Data\TotalsExtensionInterfaceFactory;
use Magento\Quote\Model\Quote;
use Magento\Quote\Model\Quote\Address\Total;
use Magento\Quote\Model\Cart\Totals as CartTotals;
use Magento\QuoteGraphQl\Model\Cart\TotalsCollector;
use Magento\Store\Model\ScopeInterface;

/**
* @inheritdoc
*
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
*/
class CartPrices implements ResolverInterface
{
Expand All @@ -28,21 +36,53 @@ class CartPrices implements ResolverInterface
*/
private $totalsCollector;

/**
* @var string
*/
private const QUERY_TYPE = 'query';

/**
* @var ScopeConfigInterface
*/
private ScopeConfigInterface $scopeConfig;

/**
* @var TotalsInterfaceFactory
*/
private TotalsInterfaceFactory $totalsFactory;

/**
* @var DataObjectHelper
*/
private DataObjectHelper $dataObjectHelper;

/**
* @var TotalsExtensionInterfaceFactory
*/
private TotalsExtensionInterfaceFactory $totalsExtension;

/**
* @param TotalsCollector $totalsCollector
* @param ScopeConfigInterface|null $scopeConfig
* @param TotalsInterfaceFactory|null $totalsFactory
* @param DataObjectHelper|null $dataObjectHelper
* @param TotalsExtensionInterfaceFactory|null $totalsExtensionFactory
*/
public function __construct(
TotalsCollector $totalsCollector,
?ScopeConfigInterface $scopeConfig = null
?ScopeConfigInterface $scopeConfig = null,
?TotalsInterfaceFactory $totalsFactory = null,
?DataObjectHelper $dataObjectHelper = null,
?TotalsExtensionInterfaceFactory $totalsExtensionFactory = null
) {
$this->totalsCollector = $totalsCollector;
$this->scopeConfig = $scopeConfig ?? ObjectManager::getInstance()->get(ScopeConfigInterface::class);
$this->totalsFactory = $totalsFactory ??
ObjectManager::getInstance()->get(TotalsInterfaceFactory::class);
$this->dataObjectHelper = $dataObjectHelper ??
ObjectManager::getInstance()->get(DataObjectHelper::class);
$this->totalsExtension = $totalsExtensionFactory ??
ObjectManager::getInstance()->get(TotalsExtensionInterfaceFactory::class);
}

/**
Expand All @@ -56,16 +96,45 @@ public function resolve(Field $field, $context, ResolveInfo $info, ?array $value

/** @var Quote $quote */
$quote = $value['model'];
/**
* To calculate a right discount value
* before calculate totals
* need to reset Cart Fixed Rules in the quote
*/
$quote->setCartFixedRules([]);
$cartTotals = $this->totalsCollector->collectQuoteTotals($quote);
$currency = $quote->getQuoteCurrencyCode();

$appliedTaxes = $this->getAppliedTaxes($cartTotals, $currency);
if (!$quote->isVirtual() && $info->operation->operation == self::QUERY_TYPE) {
$addressTotalsData = $quote->getShippingAddress()->getData();
$extensionAttributes = $quote->getShippingAddress()->getExtensionAttributes()->__toArray();
unset($addressTotalsData[ExtensibleDataInterface::EXTENSION_ATTRIBUTES_KEY]);
$cartTotals = $this->totalsFactory->create();
$this->dataObjectHelper->populateWithArray(
$cartTotals,
$addressTotalsData,
QuoteTotalsInterface::class
);

if ($extensionAttributes) {
$newExtensionAttributes = $this->totalsExtension->create();
$this->dataObjectHelper->populateWithArray(
$newExtensionAttributes,
$extensionAttributes,
\Magento\Quote\Api\Data\TotalsExtensionInterface::class
);
$cartTotals->setExtensionAttributes($newExtensionAttributes);
}

if (isset($addressTotalsData['discount_description'])) {
$cartTotals->setDiscountDescription($addressTotalsData['discount_description']);
}

$appliedTaxes = $this->getAppliedTaxes($quote->getShippingAddress(), $currency);
} else {
/**
* To calculate a right discount value
* before calculate totals
* need to reset Cart Fixed Rules in the quote
*/
$quote->setCartFixedRules([]);
$cartTotals = $this->totalsCollector->collectQuoteTotals($quote);
$appliedTaxes = $this->getAppliedTaxes($cartTotals, $currency);
}

$grandTotal = $cartTotals->getGrandTotal();

$totalAppliedTaxes = 0;
Expand All @@ -92,14 +161,19 @@ public function resolve(Field $field, $context, ResolveInfo $info, ?array $value
/**
* Returns taxes applied to the current quote
*
* @param Total $total
* @param \Magento\Quote\Model\Quote\Address|Total $addressOrTotals
* @param string $currency
* @return array
* @throws \InvalidArgumentException
*/
private function getAppliedTaxes(Total $total, string $currency): array
private function getAppliedTaxes($addressOrTotals, string $currency): array
{
if (!$addressOrTotals instanceof Total && !$addressOrTotals instanceof \Magento\Quote\Model\Quote\Address) {
throw new \InvalidArgumentException('Unsupported totals type: ' . get_class($addressOrTotals));
}

$appliedTaxesData = [];
$appliedTaxes = $total->getAppliedTaxes();
$appliedTaxes = $addressOrTotals->getAppliedTaxes();

if (empty($appliedTaxes)) {
return $appliedTaxesData;
Expand Down Expand Up @@ -133,37 +207,59 @@ private function getAppliedTaxes(Total $total, string $currency): array
/**
* Returns information about an applied discount
*
* @param Total $total
* @param Total|CartTotals $totals
* @param string $currency
* @return array|null
* @throws \InvalidArgumentException
*/
private function getDiscount(Total $total, string $currency)
private function getDiscount($totals, string $currency)
{
if ($total->getDiscountAmount() === 0) {
$this->validateTotalsInstance($totals);

if ($totals->getDiscountAmount() == 0) {
return null;
}
return [
'label' => $total->getDiscountDescription() !== null ? explode(', ', $total->getDiscountDescription()) : [],
'amount' => ['value' => $total->getDiscountAmount(), 'currency' => $currency]
'label' => $totals->getDiscountDescription() !== null ?
explode(', ', $totals->getDiscountDescription()) : [],
'amount' => ['value' => $totals->getDiscountAmount(), 'currency' => $currency]
];
}

/**
* Get Subtotal with discount excluding tax.
*
* @param Total $cartTotals
* @param Total|CartTotals $totals
* @return float
* @throws \InvalidArgumentException
*/
private function getSubtotalWithDiscountExcludingTax(Total $cartTotals): float
private function getSubtotalWithDiscountExcludingTax($totals): float
{
$this->validateTotalsInstance($totals);

$discountIncludeTax = $this->scopeConfig->getValue(
'tax/calculation/discount_tax',
ScopeInterface::SCOPE_STORE
) ?? 0;
$discountExclTax = $discountIncludeTax ?
$cartTotals->getDiscountAmount() + $cartTotals->getDiscountTaxCompensationAmount() :
$cartTotals->getDiscountAmount();
$totals->getDiscountAmount() + $totals->getDiscountTaxCompensationAmount() :
$totals->getDiscountAmount();

return $cartTotals->getSubtotal() + $discountExclTax;
return $totals->getSubtotal() + $discountExclTax;
}

/**
* Validates the provided totals instance to ensure it is of a supported type.
*
* @param Total|CartTotals $totals
* @return void
* @throws \InvalidArgumentException If the provided totals instance is of an unsupported type.
*/
private function validateTotalsInstance($totals)
{

if (!$totals instanceof Total && !$totals instanceof CartTotals) {
throw new \InvalidArgumentException('Unsupported totals type: ' . get_class($totals));
}
}
}
Loading