Skip to content

Commit 986cef0

Browse files
committed
Merge remote-tracking branch 'origin/BUG#AC-1084' into GL_Mainline_PR_03012022
2 parents d117a19 + 04420ea commit 986cef0

File tree

2 files changed

+181
-2
lines changed

2 files changed

+181
-2
lines changed

app/code/Magento/QuoteGraphQl/Model/Resolver/CartPrices.php

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@
77

88
namespace Magento\QuoteGraphQl\Model\Resolver;
99

10+
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\App\ObjectManager;
1012
use Magento\Framework\Exception\LocalizedException;
1113
use Magento\Framework\GraphQl\Config\Element\Field;
1214
use Magento\Framework\GraphQl\Query\ResolverInterface;
1315
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
1416
use Magento\Quote\Model\Quote;
1517
use Magento\Quote\Model\Quote\Address\Total;
1618
use Magento\QuoteGraphQl\Model\Cart\TotalsCollector;
19+
use Magento\Store\Model\ScopeInterface;
1720

1821
/**
1922
* @inheritdoc
@@ -25,13 +28,21 @@ class CartPrices implements ResolverInterface
2528
*/
2629
private $totalsCollector;
2730

31+
/**
32+
* @var ScopeConfigInterface
33+
*/
34+
private ScopeConfigInterface $scopeConfig;
35+
2836
/**
2937
* @param TotalsCollector $totalsCollector
38+
* @param ScopeConfigInterface|null $scopeConfig
3039
*/
3140
public function __construct(
32-
TotalsCollector $totalsCollector
41+
TotalsCollector $totalsCollector,
42+
ScopeConfigInterface $scopeConfig = null
3343
) {
3444
$this->totalsCollector = $totalsCollector;
45+
$this->scopeConfig = $scopeConfig ?? ObjectManager::getInstance()->get(ScopeConfigInterface::class);
3546
}
3647

3748
/**
@@ -59,7 +70,8 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
5970
'subtotal_including_tax' => ['value' => $cartTotals->getSubtotalInclTax(), 'currency' => $currency],
6071
'subtotal_excluding_tax' => ['value' => $cartTotals->getSubtotal(), 'currency' => $currency],
6172
'subtotal_with_discount_excluding_tax' => [
62-
'value' => $cartTotals->getSubtotalWithDiscount(), 'currency' => $currency
73+
'value' => $this->getSubtotalWithDiscountExcludingTax($cartTotals),
74+
'currency' => $currency
6375
],
6476
'applied_taxes' => $this->getAppliedTaxes($cartTotals, $currency),
6577
'discount' => $this->getDiscount($cartTotals, $currency),
@@ -109,4 +121,23 @@ private function getDiscount(Total $total, string $currency)
109121
'amount' => ['value' => $total->getDiscountAmount(), 'currency' => $currency]
110122
];
111123
}
124+
125+
/**
126+
* Get Subtotal with discount excluding tax.
127+
*
128+
* @param Total $cartTotals
129+
* @return float
130+
*/
131+
private function getSubtotalWithDiscountExcludingTax(Total $cartTotals): float
132+
{
133+
$discountIncludeTax = $this->scopeConfig->getValue(
134+
'tax/calculation/discount_tax',
135+
ScopeInterface::SCOPE_STORE
136+
) ?? 0;
137+
$discountExclTax = $discountIncludeTax ?
138+
$cartTotals->getDiscountAmount() + $cartTotals->getDiscountTaxCompensationAmount() :
139+
$cartTotals->getDiscountAmount();
140+
141+
return $cartTotals->getSubtotal() + $discountExclTax;
142+
}
112143
}
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
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\QuoteGraphQl\Test\Unit\Model\Resolver;
9+
10+
use Magento\Framework\App\Config\ScopeConfigInterface;
11+
use Magento\Framework\Exception\LocalizedException;
12+
use Magento\Framework\GraphQl\Config\Element\Field;
13+
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
14+
use Magento\GraphQl\Model\Query\Context;
15+
use Magento\Quote\Model\Quote;
16+
use Magento\Quote\Model\Quote\Address\Total;
17+
use Magento\QuoteGraphQl\Model\Cart\TotalsCollector;
18+
use Magento\QuoteGraphQl\Model\Resolver\CartPrices;
19+
use PHPUnit\Framework\TestCase;
20+
use PHPUnit\Framework\MockObject\MockObject;
21+
22+
/**
23+
* @see CartPrices
24+
*/
25+
class CartPricesTest extends TestCase
26+
{
27+
/**
28+
* @var CartPrices
29+
*/
30+
private CartPrices $cartPrices;
31+
32+
/**
33+
* @var TotalsCollector|MockObject
34+
*/
35+
private TotalsCollector $totalsCollectorMock;
36+
37+
/**
38+
* @var ScopeConfigInterface|MockObject
39+
*/
40+
private ScopeConfigInterface $scopeConfigMock;
41+
42+
/**
43+
* @var Field|MockObject
44+
*/
45+
private Field $fieldMock;
46+
47+
/**
48+
* @var ResolveInfo|MockObject
49+
*/
50+
private ResolveInfo $resolveInfoMock;
51+
52+
/**
53+
* @var Context|MockObject
54+
*/
55+
private Context $contextMock;
56+
57+
/**
58+
* @var Quote|MockObject
59+
*/
60+
private Quote $quoteMock;
61+
62+
/**
63+
* @var Total|MockObject
64+
*/
65+
private Total $totalMock;
66+
67+
/**
68+
* @var array
69+
*/
70+
private array $valueMock = [];
71+
72+
protected function setUp(): void
73+
{
74+
$this->totalsCollectorMock = $this->createMock(TotalsCollector::class);
75+
$this->scopeConfigMock = $this->createMock(ScopeConfigInterface::class);
76+
$this->fieldMock = $this->createMock(Field::class);
77+
$this->resolveInfoMock = $this->createMock(ResolveInfo::class);
78+
$this->contextMock = $this->createMock(Context::class);
79+
$this->quoteMock = $this->getMockBuilder(Quote::class)
80+
->disableOriginalConstructor()
81+
->addMethods(['getQuoteCurrencyCode'])
82+
->getMock();
83+
$this->totalMock = $this->getMockBuilder(Total::class)
84+
->disableOriginalConstructor()
85+
->addMethods(
86+
[
87+
'getSubtotal',
88+
'getSubtotalInclTax',
89+
'getGrandTotal',
90+
'getDiscountTaxCompensationAmount',
91+
'getDiscountAmount',
92+
'getDiscountDescription',
93+
'getAppliedTaxes'
94+
]
95+
)
96+
->getMock();
97+
$this->cartPrices = new CartPrices(
98+
$this->totalsCollectorMock,
99+
$this->scopeConfigMock
100+
);
101+
}
102+
103+
public function testResolveWithoutModelInValueParameter(): void
104+
{
105+
$this->expectException(LocalizedException::class);
106+
$this->expectExceptionMessage('"model" value should be specified');
107+
$this->cartPrices->resolve($this->fieldMock, $this->contextMock, $this->resolveInfoMock, $this->valueMock);
108+
}
109+
110+
public function testResolve(): void
111+
{
112+
$this->valueMock = ['model' => $this->quoteMock];
113+
$this->quoteMock
114+
->expects($this->once())
115+
->method('getQuoteCurrencyCode')
116+
->willReturn('USD');
117+
$this->totalMock
118+
->expects($this->once())
119+
->method('getGrandTotal');
120+
$this->totalMock
121+
->expects($this->exactly(2))
122+
->method('getSubtotal');
123+
$this->totalMock
124+
->expects($this->once())
125+
->method('getSubtotalInclTax');
126+
$this->totalMock
127+
->expects($this->once())
128+
->method('getDiscountDescription')
129+
->willReturn('Discount Description');
130+
$this->totalMock
131+
->expects($this->once())
132+
->method('getAppliedTaxes');
133+
$this->scopeConfigMock
134+
->expects($this->once())
135+
->method('getValue')
136+
->willReturn(1);
137+
$this->totalMock
138+
->expects($this->atLeast(2))
139+
->method('getDiscountAmount');
140+
$this->totalMock
141+
->expects($this->once())
142+
->method('getDiscountTaxCompensationAmount');
143+
$this->totalsCollectorMock
144+
->method('collectQuoteTotals')
145+
->willReturn($this->totalMock);
146+
$this->cartPrices->resolve($this->fieldMock, $this->contextMock, $this->resolveInfoMock, $this->valueMock);
147+
}
148+
}

0 commit comments

Comments
 (0)