Skip to content

Commit

Permalink
NTR: PISHPS-360: fix order expiration (#845)
Browse files Browse the repository at this point in the history
Co-authored-by: Vitalij Mik <[email protected]>
  • Loading branch information
BlackScorp and Vitalij Mik committed Sep 26, 2024
1 parent 4ac353e commit e375077
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 45 deletions.
105 changes: 105 additions & 0 deletions src/Components/OrderExpiration/ExpireAction.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
<?php
declare(strict_types=1);

namespace Kiener\MolliePayments\Components\OrderExpiration;

use Kiener\MolliePayments\Repository\Order\OrderRepositoryInterface;
use Kiener\MolliePayments\Repository\SalesChannel\SalesChannelRepositoryInterface;
use Kiener\MolliePayments\Service\Order\OrderExpireService;
use Kiener\MolliePayments\Service\SettingsService;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates;
use Shopware\Core\Checkout\Order\OrderCollection;
use Shopware\Core\Defaults;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\System\SalesChannel\SalesChannelEntity;

class ExpireAction
{
private OrderRepositoryInterface $orderRepository;
private SalesChannelRepositoryInterface $salesChannelRepository;
private OrderExpireService $orderExpireService;
private SettingsService $settingsService;
private LoggerInterface $logger;

public function __construct(
OrderRepositoryInterface $orderRepository,
SalesChannelRepositoryInterface $salesChannelRepository,
OrderExpireService $orderExpireService,
SettingsService $settingsService,
LoggerInterface $logger
) {
$this->orderRepository = $orderRepository;
$this->salesChannelRepository = $salesChannelRepository;
$this->orderExpireService = $orderExpireService;
$this->settingsService = $settingsService;
$this->logger = $logger;
}

public function expireOrders(Context $context): void
{
$this->logger->debug('Start resetting in_progress orders');

$salesChannelsCriteria = new Criteria();
$salesChannelsCriteria->addFilter(new EqualsFilter('active', true));

$salesChannels = $this->salesChannelRepository->search($salesChannelsCriteria, $context);

if ($salesChannels->count() === 0) {
$this->logger->debug('No sales channels found');
return;
}

/**
* @var SalesChannelEntity $salesChannel
*/
foreach ($salesChannels->getIterator() as $salesChannel) {
$this->expireOrdersInSalesChannel($salesChannel, $context);
}
}

private function expireOrdersInSalesChannel(SalesChannelEntity $salesChannelEntity, Context $context): void
{
$settings = $this->settingsService->getSettings($salesChannelEntity->getId());

if ($settings->isAutomaticOrderExpire() === false) {
$this->logger->debug('Automatic order expire is disabled for this saleschannel', ['salesChannel' => $salesChannelEntity->getName()]);
return;
}

$this->logger->info('Start expire orders for saleschannel', ['salesChannel' => $salesChannelEntity->getName()]);

$date = new \DateTime();
$date->modify('-2 months');

$criteria = new Criteria();
$criteria->addAssociation('transactions.stateMachineState');
$criteria->addFilter(new EqualsFilter('transactions.stateMachineState.technicalName', OrderTransactionStates::STATE_IN_PROGRESS));
$criteria->addFilter(new EqualsFilter('salesChannelId', $salesChannelEntity->getId()));
$criteria->addFilter(new RangeFilter('orderDateTime', [RangeFilter::GTE => $date->format(Defaults::STORAGE_DATE_TIME_FORMAT)]));
$criteria->addSorting(new FieldSorting('orderDateTime', FieldSorting::DESCENDING));
$criteria->setLimit(10);

$this->logger->debug('Search for orders with payment status in progress');

$searchResult = $this->orderRepository->search($criteria, $context);
if ($searchResult->count() === 0) {
$this->logger->debug('No orders found with payment status in progress');
return;
}

$this->logger->info('Found orders which are in progress', ['foundOrders' => $searchResult->count()]);

/**
* @var OrderCollection $orders
*/
$orders = $searchResult->getEntities();
$expiredOrders = $this->orderExpireService->cancelExpiredOrders($orders, $context);

$this->logger->info('Expired orders with status in progress', ['expiredOrders' => $expiredOrders]);
}
}
8 changes: 8 additions & 0 deletions src/Components/OrderExpiration/ExpireActionResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php
declare(strict_types=1);

namespace Kiener\MolliePayments\Components\OrderExpiration;

class ExpireActionResult
{
}
10 changes: 10 additions & 0 deletions src/Resources/config/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,16 @@
<helpText lang="de-DE">Wenn aktiviert, storniert das Plugin Mollie-Bestellungen automatisch, wenn sie in Shopware storniert werden. Nur Bestellungen, die erstellt, autorisiert oder teilweise versandt wurden, werden storniert. Bei teilweisem Versand werden nur Artikel storniert, die nicht versendet wurden.</helpText>
<helpText lang="nl-NL">Indien ingeschakeld, zal de plug-in automatisch Mollie-bestellingen annuleren wanneer ze worden geannuleerd in Shopware. Alleen bestellingen die zijn aangemaakt, geautoriseerd of gedeeltelijk zijn verzonden, worden geannuleerd. Indien gedeeltelijk verzonden, worden alleen artikelen geannuleerd die niet zijn verzonden.</helpText>
</input-field>
<input-field type="bool">
<name>automaticOrderExpire</name>
<defaultValue>false</defaultValue>
<label>Automatic Expiration</label>
<label lang="de-DE">Automatische Ablauf</label>
<label lang="nl-NL">Automatische vervaldatum</label>
<helpText>If enabled, the plugin will automatically expire orders with the payment status "In Progress".</helpText>
<helpText lang="de-DE">Wenn aktiviert, lässt das Plugin Bestellungen mit dem Status „In Bearbeitung“ und dem Zahlungsstatus „Offen“ oder „Autorisiert“ automatisch ablaufen.</helpText>
<helpText lang="nl-NL">Als deze optie is ingeschakeld, verlopen bestellingen met de status 'In uitvoering' en de betalingsstatus 'Open' of 'Geautoriseerd' automatisch.</helpText>
</input-field>
</card>
<card>
<title>Refund Manager</title>
Expand Down
3 changes: 1 addition & 2 deletions src/Resources/config/services/scheduled_tasks.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,7 @@

<service id="Kiener\MolliePayments\ScheduledTask\OrderStatus\ExpireOrderTaskHandler">
<argument type="service" id="Kiener\MolliePayments\Repository\ScheduledTask\ScheduledTaskRepository"/>
<argument type="service" id="Kiener\MolliePayments\Repository\Order\OrderRepository"/>
<argument type="service" id="Kiener\MolliePayments\Service\Order\OrderExpireService"/>
<argument type="service" id="Kiener\MolliePayments\Components\OrderExpiration\ExpireAction"/>
<argument type="service" id="mollie_payments.logger"/>
<tag name="messenger.message_handler"/>
</service>
Expand Down
7 changes: 7 additions & 0 deletions src/Resources/config/services/services.xml
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,13 @@
<tag name="mollie_payments.mail.attachment_generator"/>
</service>

<service id="Kiener\MolliePayments\Components\OrderExpiration\ExpireAction">
<argument type="service" id="Kiener\MolliePayments\Repository\Order\OrderRepository"/>
<argument type="service" id="Kiener\MolliePayments\Repository\SalesChannel\SalesChannelRepository"/>
<argument type="service" id="Kiener\MolliePayments\Service\Order\OrderExpireService"/>
<argument type="service" id="Kiener\MolliePayments\Service\SettingsService"/>
<argument type="service" id="mollie_payments.logger"/>
</service>



Expand Down
54 changes: 11 additions & 43 deletions src/ScheduledTask/OrderStatus/ExpireOrderTaskHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,64 +3,32 @@

namespace Kiener\MolliePayments\ScheduledTask\OrderStatus;

use Kiener\MolliePayments\Repository\Order\OrderRepositoryInterface;
use Kiener\MolliePayments\Components\OrderExpiration\ExpireAction;
use Kiener\MolliePayments\Repository\ScheduledTask\ScheduledTaskRepositoryInterface;
use Kiener\MolliePayments\Service\Order\OrderExpireService;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Order\OrderCollection;
use Shopware\Core\Checkout\Order\OrderStates;
use Shopware\Core\Framework\Api\Context\SystemSource;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\MessageQueue\ScheduledTask\ScheduledTaskHandler;

#[\Symfony\Component\Messenger\Attribute\AsMessageHandler(handles: ExpireOrderTask::class)]
class ExpireOrderTaskHandler extends ScheduledTaskHandler
{
private LoggerInterface $logger;
private OrderRepositoryInterface $orderRepository;
private OrderExpireService $orderExpireService;

public function __construct(ScheduledTaskRepositoryInterface $scheduledTaskRepository, OrderRepositoryInterface $orderRepository, OrderExpireService $orderExpireService, LoggerInterface $logger)
{
/** @phpstan-ignore-next-line */
private ExpireAction $expireAction;

public function __construct(
ScheduledTaskRepositoryInterface $scheduledTaskRepository,
ExpireAction $expireAction,
LoggerInterface $logger
) {
/** @phpstan-ignore-next-line */
parent::__construct($scheduledTaskRepository->getRepository(), $logger);
$this->logger = $logger;
$this->orderRepository = $orderRepository;
$this->orderExpireService = $orderExpireService;
$this->expireAction = $expireAction;
}

public function run(): void
{
$this->logger->debug('Start resetting in_progress orders');

$context = new Context(new SystemSource());

$criteria = new Criteria();
$criteria->addAssociation('transactions.stateMachineState');
$criteria->addFilter(new EqualsFilter('transactions.stateMachineState.technicalName', OrderStates::STATE_IN_PROGRESS));
$criteria->addSorting(new FieldSorting('orderDateTime', FieldSorting::DESCENDING));
$criteria->setLimit(10);

$this->logger->debug('Search for orders which are in progress state');

$searchResult = $this->orderRepository->search($criteria, $context);
if ($searchResult->count() === 0) {
$this->logger->debug('No in progress orders found');
return;
}

$this->logger->info('Found orders which are in progress', ['foundOrders' => $searchResult->count()]);

/**
* @var OrderCollection $orders
*/
$orders = $searchResult->getEntities();
$resetted = $this->orderExpireService->cancelExpiredOrders($orders, $context);

$this->logger->info('Rested expired orders', ['restedOrders' => $resetted]);
$this->expireAction->expireOrders($context);
}

/**
Expand Down
15 changes: 15 additions & 0 deletions src/Setting/MollieSettingStruct.php
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ class MollieSettingStruct extends Struct
*/
protected $refundManagerCreateCreditNotesSuffix = '';

/**
* @var bool
*/
protected $automaticOrderExpire = false;

/**
* @return string
*/
Expand Down Expand Up @@ -1073,4 +1078,14 @@ public function setRefundManagerCreateCreditNotesSuffix(string $refundManagerCre
{
$this->refundManagerCreateCreditNotesSuffix = $refundManagerCreateCreditNotesSuffix;
}

public function isAutomaticOrderExpire(): bool
{
return $this->automaticOrderExpire;
}

public function setAutomaticOrderExpire(bool $automaticOrderExpire): void
{
$this->automaticOrderExpire = $automaticOrderExpire;
}
}

0 comments on commit e375077

Please sign in to comment.