Skip to content

Commit 5fef1a0

Browse files
[UPMERGE] 1.0 -> 2.0 (#162)
This PR has been generated automatically. For more details see [upmerge_pr.yaml](/Sylius/AdyenPlugin/blob/1.0/.github/workflows/upmerge_pr.yaml). **Remember!** The upmerge should always be merged with using `Merge pull request` button. In case of conflicts, please resolve them manually with usign the following commands: ``` git fetch upstream gh pr checkout <this-pr-number> git merge upstream/2.0 -m "Resolve conflicts between 1.0 and 2.0" ``` If you use other name for the upstream remote, please replace `upstream` with the name of your remote pointing to the `Sylius/AdyenPlugin` repository. Once the conflicts are resolved, please run `git merge --continue` and push the changes to this PR.
2 parents 435d514 + 25b50b4 commit 5fef1a0

File tree

6 files changed

+389
-4
lines changed

6 files changed

+389
-4
lines changed

config/services/validator.xml

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,17 @@
11
<?xml version="1.0" encoding="UTF-8" ?>
22

3-
<container xmlns="http://symfony.com/schema/dic/services" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4-
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd">
3+
<container
4+
xmlns="http://symfony.com/schema/dic/services"
5+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
6+
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"
7+
>
8+
<parameters>
9+
<parameter key="sylius_adyen.checkout.addressing.countries_requiring_province" type="collection">
10+
<parameter>CA</parameter>
11+
<parameter>US</parameter>
12+
</parameter>
13+
</parameters>
14+
515
<services>
616
<defaults public="true"/>
717

@@ -20,7 +30,11 @@
2030
id="sylius_adyen.validator.province_address_constraint_decorator"
2131
decorates="sylius.validator.valid_province_address"
2232
>
23-
<argument type="service" id=".inner"/>
33+
<argument type="service" id=".inner" />
34+
<argument>%sylius_adyen.checkout.addressing.countries_requiring_province%</argument>
35+
<argument type="service" id="sylius.context.channel" />
36+
<argument type="service" id="sylius_adyen.repository.query.adyen_payment_method"/>
37+
<argument type="service" id="sylius.context.cart" />
2438
</service>
2539

2640
</services>

src/Entity/CommodityCodeAwareTrait.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
trait CommodityCodeAwareTrait
1919
{
20+
/** @ORM\Column(name="commodity_code", type="string", length=12, nullable=true) */
2021
#[ORM\Column(name: 'commodity_code', type: 'string', length: 12, nullable: true)]
2122
protected ?string $commodityCode = null;
2223

src/StateMachine/Guard/OrderPaymentGuard.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use Sylius\AdyenPlugin\PaymentGraph;
1919
use Sylius\Component\Core\Model\OrderInterface;
2020
use Sylius\Component\Core\Model\PaymentInterface;
21+
use Sylius\Component\Core\OrderPaymentStates;
2122

2223
final class OrderPaymentGuard
2324
{
@@ -33,7 +34,7 @@ public function canBeCancelled(OrderInterface $order): bool
3334
null === $payment ||
3435
false === $this->adyenPaymentMethodChecker->isAdyenPayment($payment)
3536
) {
36-
return true;
37+
return $order->getPaymentState() !== OrderPaymentStates::STATE_PAID;
3738
}
3839

3940
if ($this->adyenPaymentMethodChecker->isCaptureMode($payment, PaymentCaptureMode::AUTOMATIC)) {

src/Validator/Constraint/ProvinceAddressConstraintValidatorDecorator.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,16 @@
1313

1414
namespace Sylius\AdyenPlugin\Validator\Constraint;
1515

16+
use Sylius\AdyenPlugin\Repository\Query\AdyenPaymentMethodQueryInterface;
1617
use Sylius\Bundle\AddressingBundle\Validator\Constraints\ProvinceAddressConstraint;
1718
use Sylius\Bundle\AddressingBundle\Validator\Constraints\ProvinceAddressConstraintValidator;
19+
use Sylius\Component\Channel\Context\ChannelContextInterface;
20+
use Sylius\Component\Channel\Context\ChannelNotFoundException;
21+
use Sylius\Component\Channel\Model\ChannelInterface;
1822
use Sylius\Component\Core\Model\AddressInterface;
23+
use Sylius\Component\Core\Model\OrderInterface;
24+
use Sylius\Component\Order\Context\CartContextInterface;
25+
use Sylius\Component\Order\Context\CartNotFoundException;
1926
use Symfony\Component\Validator\Constraint;
2027
use Symfony\Component\Validator\ConstraintValidator;
2128
use Webmozart\Assert\Assert;
@@ -30,6 +37,9 @@ public function __construct(
3037
private readonly ProvinceAddressConstraintValidator $decorated,
3138
/** @var array|string[] */
3239
private readonly array $provinceRequiredCountriesList = self::PROVINCE_REQUIRED_COUNTRIES_DEFAULT_LIST,
40+
private readonly ?ChannelContextInterface $channelContext = null,
41+
private readonly ?AdyenPaymentMethodQueryInterface $adyenPaymentMethodQuery = null,
42+
private readonly ?CartContextInterface $cartContext = null,
3343
) {
3444
}
3545

@@ -42,6 +52,10 @@ public function validate($value, Constraint $constraint): void
4252
$this->decorated->initialize($this->context);
4353
$this->decorated->validate($value, $constraint);
4454

55+
if (!$this->isAnyAdyenMethodAvailable()) {
56+
return;
57+
}
58+
4559
Assert::isInstanceOf($value, AddressInterface::class);
4660
Assert::isInstanceOf($constraint, ProvinceAddressConstraint::class);
4761

@@ -72,4 +86,46 @@ private function hasViolation(Constraint $constraint): bool
7286

7387
return false;
7488
}
89+
90+
private function isAnyAdyenMethodAvailable(): bool
91+
{
92+
if (
93+
null === $this->channelContext ||
94+
null === $this->adyenPaymentMethodQuery ||
95+
null === $this->cartContext
96+
) {
97+
return true;
98+
}
99+
100+
$channel = $this->resolveChannel();
101+
if (null === $channel) {
102+
return false;
103+
}
104+
105+
$paymentMethods = $this->adyenPaymentMethodQuery->findAllAdyenByChannel($channel);
106+
foreach ($paymentMethods as $key => $paymentMethod) {
107+
if (!$paymentMethod->isEnabled()) {
108+
unset($paymentMethods[$key]);
109+
}
110+
}
111+
112+
return 0 !== count($paymentMethods);
113+
}
114+
115+
private function resolveChannel(): ?ChannelInterface
116+
{
117+
try {
118+
return $this->channelContext->getChannel();
119+
} catch (ChannelNotFoundException) {
120+
try {
121+
/** @var OrderInterface $cart */
122+
$cart = $this->cartContext->getCart();
123+
124+
return $cart->getChannel();
125+
} catch (CartNotFoundException) {
126+
}
127+
}
128+
129+
return null;
130+
}
75131
}

tests/Unit/StateMachine/Guard/OrderPaymentGuardTest.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Sylius\AdyenPlugin\StateMachine\Guard\OrderPaymentGuard;
2222
use Sylius\Component\Core\Model\OrderInterface;
2323
use Sylius\Component\Core\Model\PaymentInterface;
24+
use Sylius\Component\Core\OrderPaymentStates;
2425

2526
final class OrderPaymentGuardTest extends TestCase
2627
{
@@ -81,6 +82,7 @@ public function testItAllowsCancellationForNonAdyenPayment(): void
8182
$payment = $this->createMock(PaymentInterface::class);
8283
$order = $this->createMock(OrderInterface::class);
8384
$order->method('getLastPayment')->willReturn($payment);
85+
$order->method('getPaymentState')->willReturn(OrderPaymentStates::STATE_AWAITING_PAYMENT);
8486

8587
$this->adyenPaymentMethodChecker->expects($this->once())
8688
->method('isAdyenPayment')
@@ -94,15 +96,26 @@ public function testItAllowsCancellationWhenPaymentIsNull(): void
9496
{
9597
$order = $this->createMock(OrderInterface::class);
9698
$order->method('getLastPayment')->willReturn(null);
99+
$order->method('getPaymentState')->willReturn(OrderPaymentStates::STATE_AWAITING_PAYMENT);
97100

98101
self::assertTrue($this->guard->canBeCancelled($order));
99102
}
100103

104+
public function testItDeniesCancellationWhenPaymentIsNullAndOrderIsPaid(): void
105+
{
106+
$order = $this->createMock(OrderInterface::class);
107+
$order->method('getLastPayment')->willReturn(null);
108+
$order->method('getPaymentState')->willReturn(OrderPaymentStates::STATE_PAID);
109+
110+
self::assertFalse($this->guard->canBeCancelled($order));
111+
}
112+
101113
public function testItAllowsCancellationWhenPaymentMethodIsNull(): void
102114
{
103115
$payment = $this->createMock(PaymentInterface::class);
104116
$order = $this->createMock(OrderInterface::class);
105117
$order->method('getLastPayment')->willReturn($payment);
118+
$order->method('getPaymentState')->willReturn(OrderPaymentStates::STATE_AWAITING_PAYMENT);
106119

107120
$this->adyenPaymentMethodChecker->expects($this->once())
108121
->method('isAdyenPayment')
@@ -112,6 +125,63 @@ public function testItAllowsCancellationWhenPaymentMethodIsNull(): void
112125
self::assertTrue($this->guard->canBeCancelled($order));
113126
}
114127

128+
public function testItDeniesCancellationForNonAdyenPaymentWhenOrderIsPaid(): void
129+
{
130+
$payment = $this->createMock(PaymentInterface::class);
131+
$order = $this->createMock(OrderInterface::class);
132+
$order->method('getLastPayment')->willReturn($payment);
133+
$order->method('getPaymentState')->willReturn(OrderPaymentStates::STATE_PAID);
134+
135+
$this->adyenPaymentMethodChecker->expects($this->once())
136+
->method('isAdyenPayment')
137+
->with($payment)
138+
->willReturn(false);
139+
140+
self::assertFalse($this->guard->canBeCancelled($order));
141+
}
142+
143+
public function testItDeniesCancellationForAdyenPaymentInManualCaptureModeWhenProcessing(): void
144+
{
145+
$payment = $this->createMock(PaymentInterface::class);
146+
$payment->method('getState')->willReturn(PaymentInterface::STATE_PROCESSING);
147+
148+
$order = $this->createMock(OrderInterface::class);
149+
$order->method('getLastPayment')->willReturn($payment);
150+
151+
$this->adyenPaymentMethodChecker->expects($this->once())
152+
->method('isAdyenPayment')
153+
->with($payment)
154+
->willReturn(true);
155+
156+
$this->adyenPaymentMethodChecker->expects($this->once())
157+
->method('isCaptureMode')
158+
->with($payment, PaymentCaptureMode::AUTOMATIC)
159+
->willReturn(false);
160+
161+
self::assertFalse($this->guard->canBeCancelled($order));
162+
}
163+
164+
public function testItDeniesCancellationForAdyenPaymentInManualCaptureModeWhenCompleted(): void
165+
{
166+
$payment = $this->createMock(PaymentInterface::class);
167+
$payment->method('getState')->willReturn(PaymentInterface::STATE_COMPLETED);
168+
169+
$order = $this->createMock(OrderInterface::class);
170+
$order->method('getLastPayment')->willReturn($payment);
171+
172+
$this->adyenPaymentMethodChecker->expects($this->once())
173+
->method('isAdyenPayment')
174+
->with($payment)
175+
->willReturn(true);
176+
177+
$this->adyenPaymentMethodChecker->expects($this->once())
178+
->method('isCaptureMode')
179+
->with($payment, PaymentCaptureMode::AUTOMATIC)
180+
->willReturn(false);
181+
182+
self::assertFalse($this->guard->canBeCancelled($order));
183+
}
184+
115185
public function testItAllowsRequestPaymentForNonAdyenPayment(): void
116186
{
117187
$payment = $this->createMock(PaymentInterface::class);

0 commit comments

Comments
 (0)