diff --git a/.phpstan.neon b/.phpstan.neon index 72ff805e4..4a80b6d09 100644 --- a/.phpstan.neon +++ b/.phpstan.neon @@ -1,5 +1,6 @@ parameters: level: 8 + checkGenericClassInNonGenericObjectType: false paths: - ./src excludePaths: @@ -21,6 +22,8 @@ parameters: message: 'might overwrite existing variables' scanDirectories: - polyfill/Shopware + ignoreErrors: + - '#.*Shopware\\Commercial\\ReturnManagement\\Entity\\OrderReturn.*#' services: - class: MolliePayments\PHPStan\Rules\NoManufacturerRule diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..55fd863db --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,12 @@ +# Change Log +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/) +and this project adheres to [Semantic Versioning](http://semver.org/). + +## [Unreleased] + + +### Features +- Return over Shopware Commercial plugins is now transfered to Mollie when the Return status is set to "Done" and can be cancelled with the "Cancelled" status. Please note that the refund cannot be cancelled after two hours. + \ No newline at end of file diff --git a/polyfill/Shopware/Core/Framework/DataAbstractionLayer/EntityRepository.php b/polyfill/Shopware/Core/Framework/DataAbstractionLayer/EntityRepository.php new file mode 100644 index 000000000..07eb878cd --- /dev/null +++ b/polyfill/Shopware/Core/Framework/DataAbstractionLayer/EntityRepository.php @@ -0,0 +1,316 @@ +definition = $definition; + $this->reader = $reader; + $this->versionManager = $versionManager; + $this->searcher = $searcher; + $this->aggregator = $aggregator; + $this->eventDispatcher = $eventDispatcher; + $this->eventFactory = $eventFactory; + } + + public function getDefinition(): EntityDefinition + { + return $this->definition; + } + + /** + * @return EntitySearchResult + */ + public function search(Criteria $criteria, Context $context): EntitySearchResult + { + if (!$criteria->getTitle()) { + return $this->_search($criteria, $context); + } + + return Profiler::trace($criteria->getTitle(), fn () => $this->_search($criteria, $context), 'repository'); + } + + public function aggregate(Criteria $criteria, Context $context): AggregationResultCollection + { + if (!$criteria->getTitle()) { + return $this->_aggregate($criteria, $context); + } + + return Profiler::trace($criteria->getTitle(), fn () => $this->_aggregate($criteria, $context), 'repository'); + } + + public function searchIds(Criteria $criteria, Context $context): IdSearchResult + { + if (!$criteria->getTitle()) { + return $this->_searchIds($criteria, $context); + } + + return Profiler::trace($criteria->getTitle(), fn () => $this->_searchIds($criteria, $context), 'repository'); + } + + /** + * @param array> $data + */ + public function update(array $data, Context $context): EntityWrittenContainerEvent + { + ReplicaConnection::ensurePrimary(); + + $affected = $this->versionManager->update($this->definition, $data, WriteContext::createFromContext($context)); + $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []); + $this->eventDispatcher->dispatch($event); + + return $event; + } + + /** + * @param array> $data + */ + public function upsert(array $data, Context $context): EntityWrittenContainerEvent + { + ReplicaConnection::ensurePrimary(); + + $affected = $this->versionManager->upsert($this->definition, $data, WriteContext::createFromContext($context)); + $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []); + $this->eventDispatcher->dispatch($event); + + return $event; + } + + /** + * @param array> $data + */ + public function create(array $data, Context $context): EntityWrittenContainerEvent + { + ReplicaConnection::ensurePrimary(); + + $affected = $this->versionManager->insert($this->definition, $data, WriteContext::createFromContext($context)); + $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, []); + $this->eventDispatcher->dispatch($event); + + return $event; + } + + /** + * @param array> $ids + */ + public function delete(array $ids, Context $context): EntityWrittenContainerEvent + { + ReplicaConnection::ensurePrimary(); + + $affected = $this->versionManager->delete($this->definition, $ids, WriteContext::createFromContext($context)); + $event = EntityWrittenContainerEvent::createWithDeletedEvents($affected->getDeleted(), $context, $affected->getNotFound()); + + if ($affected->getWritten()) { + $updates = EntityWrittenContainerEvent::createWithWrittenEvents($affected->getWritten(), $context, []); + + if ($updates->getEvents() !== null) { + $event->addEvent(...$updates->getEvents()); + } + } + + $this->eventDispatcher->dispatch($event); + + return $event; + } + + public function createVersion(string $id, Context $context, ?string $name = null, ?string $versionId = null): string + { + ReplicaConnection::ensurePrimary(); + + if (!$this->definition->isVersionAware()) { + throw new \RuntimeException(\sprintf('Entity %s is not version aware', $this->definition->getEntityName())); + } + + return $this->versionManager->createVersion($this->definition, $id, WriteContext::createFromContext($context), $name, $versionId); + } + + public function merge(string $versionId, Context $context): void + { + ReplicaConnection::ensurePrimary(); + + if (!$this->definition->isVersionAware()) { + throw new \RuntimeException(\sprintf('Entity %s is not version aware', $this->definition->getEntityName())); + } + $this->versionManager->merge($versionId, WriteContext::createFromContext($context)); + } + + public function clone(string $id, Context $context, ?string $newId = null, ?CloneBehavior $behavior = null): EntityWrittenContainerEvent + { + ReplicaConnection::ensurePrimary(); + + $newId ??= Uuid::randomHex(); + if (!Uuid::isValid($newId)) { + throw new InvalidUuidException($newId); + } + + $affected = $this->versionManager->clone( + $this->definition, + $id, + $newId, + $context->getVersionId(), + WriteContext::createFromContext($context), + $behavior ?? new CloneBehavior() + ); + + $event = EntityWrittenContainerEvent::createWithWrittenEvents($affected, $context, [], true); + $this->eventDispatcher->dispatch($event); + + return $event; + } + + /** + * @return TEntityCollection + */ + private function read(Criteria $criteria, Context $context): EntityCollection + { + $criteria = clone $criteria; + + /** @var TEntityCollection $entities */ + $entities = $this->reader->read($this->definition, $criteria, $context); + + if ($criteria->getFields() === []) { + $event = $this->eventFactory->create($entities->getElements(), $context); + } else { + $event = $this->eventFactory->createPartial($entities->getElements(), $context); + } + + $this->eventDispatcher->dispatch($event); + + return $entities; + } + + /** + * @return EntitySearchResult + */ + private function _search(Criteria $criteria, Context $context): EntitySearchResult + { + $criteria = clone $criteria; + $aggregations = null; + if ($criteria->getAggregations()) { + $aggregations = $this->aggregate($criteria, $context); + } + + if (!RepositorySearchDetector::isSearchRequired($this->definition, $criteria)) { + $this->eventDispatcher->dispatch( + new EntitySearchedEvent($criteria, $this->definition, $context) + ); + $entities = $this->read($criteria, $context); + + return new EntitySearchResult($this->definition->getEntityName(), $entities->count(), $entities, $aggregations, $criteria, $context); + } + + $ids = $this->searchIds($criteria, $context); + + if (empty($ids->getIds())) { + /** @var TEntityCollection $collection */ + $collection = $this->definition->getCollectionClass(); + + return new EntitySearchResult($this->definition->getEntityName(), $ids->getTotal(), new $collection(), $aggregations, $criteria, $context); + } + + $readCriteria = $criteria->cloneForRead($ids->getIds()); + + $entities = $this->read($readCriteria, $context); + + $search = $ids->getData(); + + foreach ($entities as $element) { + if (!\array_key_exists($element->getUniqueIdentifier(), $search)) { + continue; + } + + $data = $search[$element->getUniqueIdentifier()]; + unset($data['id']); + + if (empty($data)) { + continue; + } + + $element->addExtension('search', new ArrayEntity($data)); + } + + $result = new EntitySearchResult($this->definition->getEntityName(), $ids->getTotal(), $entities, $aggregations, $criteria, $context); + $result->addState(...$ids->getStates()); + + $event = new EntitySearchResultLoadedEvent($this->definition, $result); + $this->eventDispatcher->dispatch($event, $event->getName()); + + return $result; + } + + private function _aggregate(Criteria $criteria, Context $context): AggregationResultCollection + { + $criteria = clone $criteria; + + $result = $this->aggregator->aggregate($this->definition, $criteria, $context); + + $event = new EntityAggregationResultLoadedEvent($this->definition, $result, $context); + $this->eventDispatcher->dispatch($event, $event->getName()); + + return $result; + } + + private function _searchIds(Criteria $criteria, Context $context): IdSearchResult + { + $criteria = clone $criteria; + + $this->eventDispatcher->dispatch(new EntitySearchedEvent($criteria, $this->definition, $context)); + + $result = $this->searcher->search($this->definition, $criteria, $context); + + $event = new EntityIdSearchResultLoadedEvent($this->definition, $result); + $this->eventDispatcher->dispatch($event, $event->getName()); + + return $result; + } +} diff --git a/src/Components/RefundManager/Elasticsearch/RefundAdminSearchIndexer.php b/src/Components/RefundManager/Elasticsearch/RefundAdminSearchIndexer.php index 48522b5e7..b26cae4f4 100644 --- a/src/Components/RefundManager/Elasticsearch/RefundAdminSearchIndexer.php +++ b/src/Components/RefundManager/Elasticsearch/RefundAdminSearchIndexer.php @@ -21,6 +21,9 @@ class RefundAdminSearchIndexer extends AbstractAdminIndexer { private Connection $connection; private IteratorFactory $factory; + /** + * @var EntityRepository + */ private EntityRepository $repository; private int $indexingBatchSize; @@ -30,7 +33,10 @@ class RefundAdminSearchIndexer extends AbstractAdminIndexer private const TYPE_BINARY = ParameterType::BINARY + Connection::ARRAY_PARAM_OFFSET; /** - * @internal + * @param Connection $connection + * @param IteratorFactory $factory + * @param EntityRepository $repository + * @param int $indexingBatchSize */ public function __construct( Connection $connection, diff --git a/src/Components/RefundManager/RefundManager.php b/src/Components/RefundManager/RefundManager.php index 0ce4b3cf0..590a92a0c 100644 --- a/src/Components/RefundManager/RefundManager.php +++ b/src/Components/RefundManager/RefundManager.php @@ -20,6 +20,7 @@ use Kiener\MolliePayments\Service\OrderServiceInterface; use Kiener\MolliePayments\Service\Refund\Item\RefundItem; use Kiener\MolliePayments\Service\Refund\Item\RefundItemType; +use Kiener\MolliePayments\Service\Refund\RefundCreditNoteService; use Kiener\MolliePayments\Service\Refund\RefundServiceInterface; use Kiener\MolliePayments\Struct\MollieApi\OrderLineMetaDataStruct; use Kiener\MolliePayments\Struct\Order\OrderAttributes; @@ -81,6 +82,7 @@ class RefundManager implements RefundManagerInterface * @var LoggerInterface */ private $logger; + private RefundCreditNoteService $creditNoteService; /** @@ -94,8 +96,18 @@ class RefundManager implements RefundManagerInterface * @param RefundRepositoryInterface $refundRepository * @param LoggerInterface $logger */ - public function __construct(RefundDataBuilder $refundDataBuilder, OrderServiceInterface $orderService, RefundServiceInterface $refundService, Order $mollieOrder, FlowBuilderFactoryInterface $flowBuilderFactory, FlowBuilderEventFactory $flowBuilderEventFactory, StockManagerInterface $stockUpdater, RefundRepositoryInterface $refundRepository, LoggerInterface $logger) - { + public function __construct( + RefundDataBuilder $refundDataBuilder, + OrderServiceInterface $orderService, + RefundServiceInterface $refundService, + Order $mollieOrder, + FlowBuilderFactoryInterface $flowBuilderFactory, + FlowBuilderEventFactory $flowBuilderEventFactory, + StockManagerInterface $stockUpdater, + RefundRepositoryInterface $refundRepository, + RefundCreditNoteService $creditNoteService, + LoggerInterface $logger + ) { $this->builderData = $refundDataBuilder; $this->orderService = $orderService; $this->mollie = $mollieOrder; @@ -106,6 +118,7 @@ public function __construct(RefundDataBuilder $refundDataBuilder, OrderServiceIn $this->logger = $logger; $this->flowBuilderDispatcher = $flowBuilderFactory->createDispatcher(); + $this->creditNoteService = $creditNoteService; } @@ -300,7 +313,7 @@ public function refund(OrderEntity $order, RefundRequest $request, Context $cont ); } } - + $this->creditNoteService->createCreditNotes($order, $refund, $request, $context); return $refund; } @@ -347,6 +360,8 @@ public function cancelRefund(string $orderId, string $refundId, Context $context ], ], $context); + $this->creditNoteService->cancelCreditNotes($orderId, $context); + return true; } @@ -404,6 +419,18 @@ private function buildRequestItemsFromOrder(OrderEntity $order) return $items; } + public function cancelAllOrderRefunds(OrderEntity $order, Context $context): bool + { + $refunds = $this->refundService->getRefunds($order, $context); + if (count($refunds) === 0) { + return true; + } + foreach ($refunds as $refund) { + $this->cancelRefund($order->getId(), $refund['id'], $context); + } + return true; + } + private function appendRoundingItemFromMollieOrder(RefundRequest $request, ?\Mollie\Api\Resources\Order $mollieOrder): void { if ($mollieOrder === null) { diff --git a/src/Components/RefundManager/RefundManagerInterface.php b/src/Components/RefundManager/RefundManagerInterface.php index b17d3a114..13cd3ed7a 100644 --- a/src/Components/RefundManager/RefundManagerInterface.php +++ b/src/Components/RefundManager/RefundManagerInterface.php @@ -25,6 +25,8 @@ public function getData(OrderEntity $order, Context $context): RefundData; */ public function refund(OrderEntity $order, RefundRequest $request, Context $context): Refund; + public function cancelAllOrderRefunds(OrderEntity $order, Context $context): bool; + /** * @param string $orderId * @param string $refundId diff --git a/src/Components/RefundManager/Service/OrderReturnHandler.php b/src/Components/RefundManager/Service/OrderReturnHandler.php new file mode 100644 index 000000000..ad02adb34 --- /dev/null +++ b/src/Components/RefundManager/Service/OrderReturnHandler.php @@ -0,0 +1,120 @@ +refundManager = $refundManager; + $this->orderReturnRepository = $orderReturnRepository; + $this->logger = $logger; + $this->orderService = $orderService; + $this->featureDisabled = $orderReturnRepository === null; + } + + public function return(OrderEntity $order, Context $context): void + { + if ($this->featureDisabled) { + return; + } + $orderReturn = $this->findReturnByOrder($order, $context); + if ($orderReturn === null) { + return; + } + $request = $this->createRequestFromOrder((string)$order->getOrderNumber(), $orderReturn); + $order = $this->orderService->getOrder($order->getId(), $context); //need to load the order again because the lineitems are not loaded in the event + try { + $this->refundManager->refund($order, $request, $context); + } catch (\Throwable $throwable) { + $this->logger->error("Error during refund status change: {{message}}", ['message'=>$throwable->getMessage()]); + } + } + + public function cancel(OrderEntity $order, Context $context): void + { + if ($this->featureDisabled) { + return; + } + $this->refundManager->cancelAllOrderRefunds($order, $context); + } + + // @phpstan-ignore argument.type + private function createRequestFromOrder(string $orderNumber, OrderReturnEntity $orderReturn): RefundRequest + { + $request = new RefundRequest( + $orderNumber, + (string)$orderReturn->getInternalComment(), + '', + $orderReturn->getAmountTotal() + ); + /** @var OrderReturnLineItemEntity $item */ + foreach ($orderReturn->getLineItems() as $item) { + $refundRequestItem = new RefundRequestItem($item->getOrderLineItemId(), $item->getPrice()->getUnitPrice(), $item->getQuantity(), 0); + $request->addItem($refundRequestItem); + } + + return $request; + } + + // @phpstan-ignore return.type + private function findReturnByOrder(OrderEntity $order, Context $context): ?OrderReturnEntity + { + if ($this->orderReturnRepository === null) { + return null; + } + $criteria = new Criteria(); + $criteria->addFilter(new EqualsFilter('orderId', $order->getId())); + $criteria->addFilter(new EqualsFilter('orderVersionId', $order->getVersionId())); + $criteria->addAssociation('lineItems'); + + $orderReturnSearchResult = $this->orderReturnRepository->search($criteria, $context); + + if ($orderReturnSearchResult->getTotal() === 0) { + $this->logger->warning('Failed to find order return for order {{orderNumber}}', [ + 'orderNumber' => $order->getOrderNumber(), + ]); + return null; + } + + /** @var OrderReturnEntity $orderReturn */ + $orderReturn = $orderReturnSearchResult->first(); + return $orderReturn; + } +} diff --git a/src/Components/Subscription/Elasticsearch/SubscriptionAdminSearchIndexer.php b/src/Components/Subscription/Elasticsearch/SubscriptionAdminSearchIndexer.php index 744f872e5..7a9c23f75 100644 --- a/src/Components/Subscription/Elasticsearch/SubscriptionAdminSearchIndexer.php +++ b/src/Components/Subscription/Elasticsearch/SubscriptionAdminSearchIndexer.php @@ -21,14 +21,21 @@ class SubscriptionAdminSearchIndexer extends AbstractAdminIndexer { private Connection $connection; private IteratorFactory $factory; + /** + * @var EntityRepository + */ private EntityRepository $repository; private int $indexingBatchSize; /** * elasticsearch below 6.6 install old doctrine dbal where binary type does not exists yet */ private const TYPE_BINARY = ParameterType::BINARY + Connection::ARRAY_PARAM_OFFSET; + /** - * @internal + * @param Connection $connection + * @param IteratorFactory $factory + * @param EntityRepository $repository + * @param int $indexingBatchSize */ public function __construct( Connection $connection, diff --git a/src/Controller/Api/Controller/OrderController.php b/src/Controller/Api/Controller/OrderController.php index e32647f15..a95011bfb 100644 --- a/src/Controller/Api/Controller/OrderController.php +++ b/src/Controller/Api/Controller/OrderController.php @@ -46,6 +46,14 @@ class OrderController extends AbstractController */ private $orderRepository; + /** + * @param RequestBagFactory $requestBagFactory + * @param ConfigControllerBase $baseController + * @param ShippingControllerBase $shippingController + * @param OrderControllerBase $orderController + * @param CancelLineController $cancelLineController + * @param EntityRepository $orderRepository + */ public function __construct( RequestBagFactory $requestBagFactory, ConfigControllerBase $baseController, diff --git a/src/Controller/Api/Order/RefundControllerBase.php b/src/Controller/Api/Order/RefundControllerBase.php index 3ca39f33b..03ddda793 100644 --- a/src/Controller/Api/Order/RefundControllerBase.php +++ b/src/Controller/Api/Order/RefundControllerBase.php @@ -7,7 +7,6 @@ use Kiener\MolliePayments\Components\RefundManager\Request\RefundRequestItem; use Kiener\MolliePayments\Exception\PaymentNotFoundException; use Kiener\MolliePayments\Service\OrderService; -use Kiener\MolliePayments\Service\Refund\RefundCreditNoteService; use Kiener\MolliePayments\Service\Refund\RefundService; use Kiener\MolliePayments\Traits\Api\ApiTrait; use Psr\Log\LoggerInterface; @@ -41,10 +40,6 @@ class RefundControllerBase extends AbstractController */ private $logger; - /** - * @var RefundCreditNoteService - */ - private $creditNoteService; /** @@ -57,14 +52,12 @@ public function __construct( OrderService $orderService, RefundManagerInterface $refundManager, RefundService $refundService, - LoggerInterface $logger, - RefundCreditNoteService $creditNoteService + LoggerInterface $logger ) { $this->orderService = $orderService; $this->refundManager = $refundManager; $this->refundService = $refundService; $this->logger = $logger; - $this->creditNoteService = $creditNoteService; } @@ -364,7 +357,6 @@ private function refundAction(string $orderId, string $orderNumber, string $desc $context ); - $this->creditNoteService->createCreditNotes($order, $refund, $refundRequest, $context); return $this->json([ 'success' => true, @@ -388,7 +380,7 @@ private function cancelRefundAction(string $orderId, string $refundId, Context $ try { $success = $this->refundManager->cancelRefund($orderId, $refundId, $context); - $this->creditNoteService->cancelCreditNotes($orderId, $context); + return $this->json([ 'success' => $success diff --git a/src/Resources/config/services/components.xml b/src/Resources/config/services/components.xml index 8f2e79e7d..da18b75d0 100644 --- a/src/Resources/config/services/components.xml +++ b/src/Resources/config/services/components.xml @@ -15,6 +15,7 @@ + @@ -24,6 +25,13 @@ + + + + + + + diff --git a/src/Resources/config/services/controller.xml b/src/Resources/config/services/controller.xml index e8ef55a90..6e9f7c1a8 100644 --- a/src/Resources/config/services/controller.xml +++ b/src/Resources/config/services/controller.xml @@ -72,7 +72,6 @@ - diff --git a/src/Resources/config/services/subscriber.xml b/src/Resources/config/services/subscriber.xml index c23e5b457..577eaeb12 100644 --- a/src/Resources/config/services/subscriber.xml +++ b/src/Resources/config/services/subscriber.xml @@ -86,6 +86,10 @@ + + + + diff --git a/src/Service/CustomFieldsInterface.php b/src/Service/CustomFieldsInterface.php index a068deecb..a26b7563c 100644 --- a/src/Service/CustomFieldsInterface.php +++ b/src/Service/CustomFieldsInterface.php @@ -33,4 +33,6 @@ interface CustomFieldsInterface public const PAYPAL_EXPRESS_AUTHENTICATE_ID = 'mollie_ppe_auth_id'; public const ACCEPTED_DATA_PROTECTION = 'acceptedDataProtection'; + + public const REFUND_KEY = 'mollie_refund_id'; } diff --git a/src/Service/OrderService.php b/src/Service/OrderService.php index 69575b665..233e40c4f 100644 --- a/src/Service/OrderService.php +++ b/src/Service/OrderService.php @@ -91,6 +91,7 @@ public function __construct(OrderRepositoryInterface $orderRepository, ShopwareO public function getOrder(string $orderId, Context $context): OrderEntity { $criteria = new Criteria([$orderId]); + $criteria->addAssociation('currency'); $criteria->addAssociation('addresses'); $criteria->addAssociation('addresses.country'); # required for FlowBuilder -> send confirm email option diff --git a/src/Service/Refund/CompositionMigrationService.php b/src/Service/Refund/CompositionMigrationService.php index 82f176bb0..4d1c35dd6 100644 --- a/src/Service/Refund/CompositionMigrationService.php +++ b/src/Service/Refund/CompositionMigrationService.php @@ -26,6 +26,9 @@ class CompositionMigrationService implements CompositionMigrationServiceInterfac */ private $refundItemRepository; + /** + * @param EntityRepository $refundItemRepository + */ public function __construct(EntityRepository $refundItemRepository) { $this->refundItemRepository = $refundItemRepository; diff --git a/src/Service/Refund/RefundCreditNoteService.php b/src/Service/Refund/RefundCreditNoteService.php index 6a14fd880..458f5ff94 100644 --- a/src/Service/Refund/RefundCreditNoteService.php +++ b/src/Service/Refund/RefundCreditNoteService.php @@ -53,7 +53,12 @@ class RefundCreditNoteService */ private $logger; - + /** + * @param EntityRepository $orderRepository + * @param EntityRepository $orderLineItemRepository + * @param SettingsService $settingsService + * @param LoggerInterface $logger + */ public function __construct( EntityRepository $orderRepository, EntityRepository $orderLineItemRepository, diff --git a/src/Service/Refund/RefundServiceInterface.php b/src/Service/Refund/RefundServiceInterface.php index b107f7d95..28e6e5b3a 100644 --- a/src/Service/Refund/RefundServiceInterface.php +++ b/src/Service/Refund/RefundServiceInterface.php @@ -41,7 +41,7 @@ public function cancel(OrderEntity $order, string $refundId): bool; /** * @param OrderEntity $order - * @return Refund[] + * @return array */ public function getRefunds(OrderEntity $order, Context $context): array; diff --git a/src/Service/Tags/OrderTagService.php b/src/Service/Tags/OrderTagService.php index d15a18c8a..0b1070994 100644 --- a/src/Service/Tags/OrderTagService.php +++ b/src/Service/Tags/OrderTagService.php @@ -27,6 +27,10 @@ class OrderTagService */ private $tagRepository; + /** + * @param EntityRepository $orderRepository + * @param EntityRepository $tagRepository + */ public function __construct( EntityRepository $orderRepository, EntityRepository $tagRepository diff --git a/src/Subscriber/OrderReturnSubscriber.php b/src/Subscriber/OrderReturnSubscriber.php new file mode 100644 index 000000000..d3a15b982 --- /dev/null +++ b/src/Subscriber/OrderReturnSubscriber.php @@ -0,0 +1,36 @@ +orderReturnHandler = $orderReturnHandler; + } + public static function getSubscribedEvents() + { + return [ + 'state_enter.order_return.state.done' => ['onOrderReturnFinished', 10], + 'state_enter.order_return.state.cancelled' => ['onOrderReturnCancelled', 10], + ]; + } + + + public function onOrderReturnCancelled(OrderStateMachineStateChangeEvent $event): void + { + $this->orderReturnHandler->cancel($event->getOrder(), $event->getContext()); + } + + public function onOrderReturnFinished(OrderStateMachineStateChangeEvent $event): void + { + $this->orderReturnHandler->return($event->getOrder(), $event->getContext()); + } +} diff --git a/tests/PHPUnit/Components/RefundManager/RefundManagerTest.php b/tests/PHPUnit/Components/RefundManager/RefundManagerTest.php index 85d2e7b44..a43b44549 100644 --- a/tests/PHPUnit/Components/RefundManager/RefundManagerTest.php +++ b/tests/PHPUnit/Components/RefundManager/RefundManagerTest.php @@ -10,6 +10,7 @@ use Kiener\MolliePayments\Components\RefundManager\Request\RefundRequest; use Kiener\MolliePayments\Components\RefundManager\Request\RefundRequestItem; use Kiener\MolliePayments\Service\MollieApi\Order; +use Kiener\MolliePayments\Service\Refund\RefundCreditNoteService; use Mollie\Api\MollieApiClient; use Mollie\Api\Resources\Order as MollieOrder; use MolliePayments\Tests\Fakes\FakeOrderService; @@ -83,7 +84,7 @@ protected function setUp(): void $flowBuilderEventFactory = new FlowBuilderEventFactory('6.4.8.0'); # use any higher version so that we get real events $this->fakeRefundRespository = new FakeRefundRepository(); - + $fakeRefundCreditNotesService = $this->createMock(RefundCreditNoteService::class); $this->manager = new RefundManager( new RefundDataBuilder($fakeOrderService, $fakeRefundService, $fakeOrder), $fakeOrderService, @@ -93,6 +94,7 @@ protected function setUp(): void $flowBuilderEventFactory, $this->fakeStockUpdater, $this->fakeRefundRespository, + $fakeRefundCreditNotesService, new NullLogger() ); diff --git a/tests/PHPUnit/Fakes/FakeRefundManager.php b/tests/PHPUnit/Fakes/FakeRefundManager.php index edbb6c73b..a55504fc2 100644 --- a/tests/PHPUnit/Fakes/FakeRefundManager.php +++ b/tests/PHPUnit/Fakes/FakeRefundManager.php @@ -107,4 +107,10 @@ private function buildFakeRefund(): Refund return $refund; } + + public function cancelAllOrderRefunds(OrderEntity $order, Context $context): bool + { + // TODO: Implement cancelAllOrderRefunds() method. + } + }