diff --git a/spec/Event/RefundPaymentGeneratedSpec.php b/spec/Event/RefundPaymentGeneratedSpec.php index 4d3437a5..14aab649 100644 --- a/spec/Event/RefundPaymentGeneratedSpec.php +++ b/spec/Event/RefundPaymentGeneratedSpec.php @@ -10,12 +10,13 @@ final class RefundPaymentGeneratedSpec extends ObjectBehavior { function it_represents_an_immutable_fact_that_refund_payment_has_been_generated(): void { - $this->beConstructedWith(1, '000222', 10000, 'GBP', 2); + $this->beConstructedWith(1, '000222', 10000, 'GBP', 2, 3); $this->id()->shouldReturn(1); $this->orderNumber()->shouldReturn('000222'); $this->amount()->shouldReturn(10000); $this->currencyCode()->shouldReturn('GBP'); $this->paymentMethodId()->shouldReturn(2); + $this->paymentId()->shouldReturn(3); } } diff --git a/spec/ProcessManager/RefundPaymentProcessManagerSpec.php b/spec/ProcessManager/RefundPaymentProcessManagerSpec.php index bc8edd6d..d06ac3df 100644 --- a/spec/ProcessManager/RefundPaymentProcessManagerSpec.php +++ b/spec/ProcessManager/RefundPaymentProcessManagerSpec.php @@ -13,18 +13,21 @@ use Sylius\RefundPlugin\Event\UnitsRefunded; use Sylius\RefundPlugin\Factory\RefundPaymentFactoryInterface; use Sylius\RefundPlugin\Model\OrderItemUnitRefund; +use Sylius\RefundPlugin\Provider\RelatedPaymentIdProviderInterface; use Sylius\RefundPlugin\StateResolver\OrderFullyRefundedStateResolverInterface; final class RefundPaymentProcessManagerSpec extends ObjectBehavior { function let( OrderFullyRefundedStateResolverInterface $orderFullyRefundedStateResolver, + RelatedPaymentIdProviderInterface $relatedPaymentIdProvider, RefundPaymentFactoryInterface $refundPaymentFactory, EntityManagerInterface $entityManager, EventBus $eventBus ): void { $this->beConstructedWith( $orderFullyRefundedStateResolver, + $relatedPaymentIdProvider, $refundPaymentFactory, $entityManager, $eventBus @@ -33,6 +36,7 @@ function let( function it_reacts_on_units_refunded_event_and_creates_refund_payment( OrderFullyRefundedStateResolverInterface $orderFullyRefundedStateResolver, + RelatedPaymentIdProviderInterface $relatedPaymentIdProvider, RefundPaymentFactoryInterface $refundPaymentFactory, EntityManagerInterface $entityManager, RefundPaymentInterface $refundPayment, @@ -55,13 +59,16 @@ function it_reacts_on_units_refunded_event_and_creates_refund_payment( $refundPayment->getOrderNumber()->willReturn('000222'); $refundPayment->getAmount()->willReturn(1000); + $relatedPaymentIdProvider->getForRefundPayment($refundPayment)->willReturn(3); + $eventBus->dispatch(Argument::that(function (RefundPaymentGenerated $event): bool { return $event->id() === 10 && $event->orderNumber() === '000222' && $event->amount() === 1000 && $event->currencyCode() === 'USD' && - $event->paymentMethodId() === 1 + $event->paymentMethodId() === 1 && + $event->paymentId() === 3 ; }))->shouldBeCalled(); diff --git a/spec/Provider/DefaultRelatedPaymentIdProviderSpec.php b/spec/Provider/DefaultRelatedPaymentIdProviderSpec.php new file mode 100644 index 00000000..6f81b78e --- /dev/null +++ b/spec/Provider/DefaultRelatedPaymentIdProviderSpec.php @@ -0,0 +1,73 @@ +beConstructedWith($orderRepository); + } + + function it_implements_related_payment_id_provider_interface(): void + { + $this->shouldImplement(RelatedPaymentIdProviderInterface::class); + } + + function it_provides_id_of_last_completed_payment_from_refund_payment_order( + OrderRepositoryInterface $orderRepository, + RefundPaymentInterface $refundPayment, + OrderInterface $order, + PaymentInterface $payment + ): void { + $refundPayment->getOrderNumber()->willReturn('000333'); + + $orderRepository->findOneByNumber('000333')->willReturn($order); + + $order->getLastPayment(PaymentInterface::STATE_COMPLETED)->willReturn($payment); + + $payment->getId()->willReturn(4); + + $this->getForRefundPayment($refundPayment)->shouldReturn(4); + } + + function it_throws_exception_if_there_is_no_order_with_given_number( + OrderRepositoryInterface $orderRepository, + RefundPaymentInterface $refundPayment + ): void { + $refundPayment->getOrderNumber()->willReturn('000666'); + $orderRepository->findOneByNumber('000666')->willReturn(null); + + $this + ->shouldThrow(OrderNotFound::withNumber('000666')) + ->during('getForRefundPayment', [$refundPayment]) + ; + } + + function it_throws_exception_if_order_has_no_completed_payments( + OrderRepositoryInterface $orderRepository, + RefundPaymentInterface $refundPayment, + OrderInterface $order + ): void { + $refundPayment->getOrderNumber()->willReturn('000666'); + $orderRepository->findOneByNumber('000666')->willReturn($order); + + $order->getLastPayment(PaymentInterface::STATE_COMPLETED)->willReturn(null); + + $this + ->shouldThrow(CompletedPaymentNotFound::withNumber('000666')) + ->during('getForRefundPayment', [$refundPayment]) + ; + } +} diff --git a/src/Event/RefundPaymentGenerated.php b/src/Event/RefundPaymentGenerated.php index 48b44ac6..ffe57f14 100644 --- a/src/Event/RefundPaymentGenerated.php +++ b/src/Event/RefundPaymentGenerated.php @@ -21,13 +21,23 @@ final class RefundPaymentGenerated /** @var int */ private $paymentMethodId; - public function __construct(int $id, string $orderNumber, int $amount, string $currencyCode, int $paymentMethodId) - { + /** @var int */ + private $paymentId; + + public function __construct( + int $id, + string $orderNumber, + int $amount, + string $currencyCode, + int $paymentMethodId, + int $paymentId + ) { $this->id = $id; $this->orderNumber = $orderNumber; $this->amount = $amount; $this->currencyCode = $currencyCode; $this->paymentMethodId = $paymentMethodId; + $this->paymentId = $paymentId; } public function id(): int @@ -54,4 +64,9 @@ public function paymentMethodId(): int { return $this->paymentMethodId; } + + public function paymentId(): int + { + return $this->paymentId; + } } diff --git a/src/Exception/CompletedPaymentNotFound.php b/src/Exception/CompletedPaymentNotFound.php new file mode 100644 index 00000000..c8119edf --- /dev/null +++ b/src/Exception/CompletedPaymentNotFound.php @@ -0,0 +1,13 @@ +orderFullyRefundedStateResolver = $orderFullyRefundedStateResolver; + $this->relatedPaymentIdProvider = $relatedPaymentIdProvider; $this->refundPaymentFactory = $refundPaymentFactory; $this->entityManager = $entityManager; $this->eventBus = $eventBus; @@ -56,7 +62,8 @@ public function __invoke(UnitsRefunded $event): void $event->orderNumber(), $event->amount(), $event->currencyCode(), - $event->paymentMethodId() + $event->paymentMethodId(), + $this->relatedPaymentIdProvider->getForRefundPayment($refundPayment) )); $this->orderFullyRefundedStateResolver->resolve($event->orderNumber()); diff --git a/src/Provider/DefaultRelatedPaymentIdProvider.php b/src/Provider/DefaultRelatedPaymentIdProvider.php new file mode 100644 index 00000000..0e910019 --- /dev/null +++ b/src/Provider/DefaultRelatedPaymentIdProvider.php @@ -0,0 +1,42 @@ +orderRepository = $orderRepository; + } + + public function getForRefundPayment(RefundPaymentInterface $refundPayment): int + { + $orderNumber = $refundPayment->getOrderNumber(); + /** @var OrderInterface|null $order */ + $order = $this->orderRepository->findOneByNumber($orderNumber); + + if ($order === null) { + throw OrderNotFound::withNumber($orderNumber); + } + + $payment = $order->getLastPayment(PaymentInterface::STATE_COMPLETED); + + if ($payment === null) { + throw CompletedPaymentNotFound::withNumber($orderNumber); + } + + return $payment->getId(); + } +} diff --git a/src/Provider/RelatedPaymentIdProviderInterface.php b/src/Provider/RelatedPaymentIdProviderInterface.php new file mode 100644 index 00000000..14b44856 --- /dev/null +++ b/src/Provider/RelatedPaymentIdProviderInterface.php @@ -0,0 +1,12 @@ + + diff --git a/src/Resources/config/services/provider.xml b/src/Resources/config/services/provider.xml index 79a99562..9add5e64 100644 --- a/src/Resources/config/services/provider.xml +++ b/src/Resources/config/services/provider.xml @@ -27,5 +27,9 @@ + + + +