<?php declare(strict_types=1);
namespace Fgits\AutoInvoice\Subscriber;
use Fgits\AutoInvoice\ScheduledTask\Export\AutoInvoiceExportTask;
use Fgits\AutoInvoice\ScheduledTask\OrderScan\AutoInvoiceOrderScanTask;
use Fgits\AutoInvoice\Service\CustomFields\OrderCustomFields;
use Fgits\AutoInvoice\Service\DB\Order as DBOrder;
use Fgits\AutoInvoice\Service\FgitsLibrary\ScheduledTask;
use Fgits\AutoInvoice\Service\FgitsLibrary\Utility;
use Fgits\AutoInvoice\Service\OrderProcessor;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Cart\Exception\OrderDeliveryNotFoundException;
use Shopware\Core\Checkout\Cart\Exception\OrderNotFoundException;
use Shopware\Core\Checkout\Cart\Exception\OrderTransactionNotFoundException;
use Shopware\Core\Checkout\Order\Aggregate\OrderDelivery\OrderDeliveryEntity;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\StateMachine\Event\StateMachineStateChangeEvent;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
* Copyright (c) 2020. GOLLE IT.
*
* @author Andrey Grigorkin <andrey@golle-it.de>
*/
class OrderSubscriber implements EventSubscriberInterface
{
private DBOrder $dbOrder;
private OrderCustomFields $orderCustomFields;
private ScheduledTask $scheduledTask;
private OrderProcessor $orderProcessor;
private EntityRepositoryInterface $orderRepository;
private EntityRepositoryInterface $orderDeliveryRepository;
private EntityRepositoryInterface $orderTransactionRepository;
private Utility $utility;
private RequestStack $requestStack;
private SessionInterface $session;
private SystemConfigService $systemConfigService;
private LoggerInterface $logger;
/**
* OrderSubscriber constructor.
*
* @param DBOrder $dbOrder
* @param OrderCustomFields $orderCustomFields
* @param ScheduledTask $scheduledTask
* @param OrderProcessor $orderProcessor
* @param EntityRepositoryInterface $orderRepository
* @param EntityRepositoryInterface $orderDeliveryRepository
* @param EntityRepositoryInterface $orderTransactionRepository
* @param Utility $utility
* @param RequestStack $requestStack
* @param SessionInterface $session
* @param SystemConfigService $systemConfigService
* @param LoggerInterface $logger
*/
public function __construct(
DBOrder $dbOrder,
OrderCustomFields $orderCustomFields,
ScheduledTask $scheduledTask,
OrderProcessor $orderProcessor,
EntityRepositoryInterface $orderRepository,
EntityRepositoryInterface $orderDeliveryRepository,
EntityRepositoryInterface $orderTransactionRepository,
Utility $utility,
RequestStack $requestStack,
SessionInterface $session,
SystemConfigService $systemConfigService,
LoggerInterface $logger
) {
$this->dbOrder = $dbOrder;
$this->orderCustomFields = $orderCustomFields;
$this->scheduledTask = $scheduledTask;
$this->orderProcessor = $orderProcessor;
$this->orderRepository = $orderRepository;
$this->orderDeliveryRepository = $orderDeliveryRepository;
$this->orderTransactionRepository = $orderTransactionRepository;
$this->utility = $utility;
$this->requestStack = $requestStack;
$this->session = $session;
$this->systemConfigService = $systemConfigService;
$this->logger = $logger;
}
public static function getSubscribedEvents(): array
{
return[
CheckoutOrderPlacedEvent::class => [['scheduleScheduledTasks'], ['onOrderPlaced']],
'state_machine.order_transaction.state_changed' => 'onOrderTransactionStateChanged',
'state_machine.order_delivery.state_changed' => 'onOrderDeliveryStateChanged',
'state_machine.order.state_changed' => [['onOrderStateChanged'], ['onOrderStateChangedTickets']]
];
}
public function scheduleScheduledTasks(): void
{
$this->scheduledTask->schedule(AutoInvoiceExportTask::getTaskName());
$this->scheduledTask->schedule(AutoInvoiceOrderScanTask::getTaskName());
}
/**
* Gets invoked when an order is created.
*
* @param CheckoutOrderPlacedEvent $event
*/
public function onOrderPlaced(CheckoutOrderPlacedEvent $event): void
{
$this->session->set('fgits_autoinvoice_latest_order_id', $event->getOrder()->getId());
$config = $this->systemConfigService->get('fgitsAutoinvoiceSW6.config', $event->getSalesChannelId());
if (!$config['active']) {
return;
}
$request = $this->requestStack->getCurrentRequest();
if ($config['changeCheckoutEmail'] && isset($request) && $request->get('fgitsChangeCheckoutEmail')) {
$this->orderCustomFields->setCheckoutEmail($event->getOrder(), $request->get('fgitsChangeCheckoutEmail'));
}
if ($config['sendCustomerInvoice'] && isset($request) && !$request->get('fgitsSendCustomerInvoice')) {
$this->orderCustomFields->setCustomerNoInvoice($event->getOrder());
}
$context = $this->utility->getContext($event->getOrder(), $event->getContext());
$order = $this->dbOrder->getOrderById($event->getOrderId(), $this->utility->getOrderAssociations(), $context);
try {
$this->orderProcessor->processOrder($order, $context, true);
} catch (\Exception $e) {
$this->logger->error('[#fgits] fgitsAutoinvoiceSW6: ' . __CLASS__ . '::' . __FUNCTION__ . '(): Order #' . $order->getOrderNumber() . ': ' . print_r($e->getMessage(), true));
}
}
/**
* Gets invoked when the payment status is changed.
*
* @param StateMachineStateChangeEvent $event
*/
public function onOrderTransactionStateChanged(StateMachineStateChangeEvent $event): void
{
$config = $this->systemConfigService->get('fgitsAutoinvoiceSW6.config', $event->getSalesChannelId());
if (!$config['active'] || empty($config['conditionPaymentStatus'])) {
return;
}
$orderTransactionId = $event->getTransition()->getEntityId();
$criteria = new Criteria([$orderTransactionId]);
$criteria->addAssociation('paymentMethod');
$criteria->addAssociation('order.orderCustomer');
$criteria->addAssociation('order.transactions');
/** @var OrderTransactionEntity|null $orderTransaction */
$orderTransaction = $this->orderTransactionRepository->search($criteria, $event->getContext())->first();
if ($orderTransaction === null) {
throw new OrderTransactionNotFoundException($orderTransactionId);
}
if ($orderTransaction->getPaymentMethod() === null) {
throw new OrderTransactionNotFoundException($orderTransactionId);
}
if ($orderTransaction->getOrder() === null) {
throw new OrderNotFoundException($orderTransactionId);
}
$context = $this->utility->getContext($orderTransaction->getOrder(), $event->getContext());
$order = $this->dbOrder->getOrderById($orderTransaction->getOrderId(), $this->utility->getOrderAssociations(), $context);
$order->fgitsAutoinvoiceOrderTransactionId = $orderTransactionId;
try {
$this->orderProcessor->processOrder($order, $context);
} catch (\Exception $e) {
$this->logger->error('[#fgits] fgitsAutoinvoiceSW6: ' . __CLASS__ . '::' . __FUNCTION__ . '(): Order #' . $order->getOrderNumber() . ': ' . print_r($e->getMessage(), true));
}
}
/**
* Gets invoked when the delivery status is changed.
*
* @param StateMachineStateChangeEvent $event
*/
public function onOrderDeliveryStateChanged(StateMachineStateChangeEvent $event): void
{
$config = $this->systemConfigService->get('fgitsAutoinvoiceSW6.config', $event->getSalesChannelId());
if (!$config['active'] || empty($config['conditionDeliveryStatus'])) {
return;
}
$orderDeliveryId = $event->getTransition()->getEntityId();
$criteria = new Criteria([$orderDeliveryId]);
$criteria->addAssociation('order.orderCustomer');
$criteria->addAssociation('order.transactions');
/** @var OrderDeliveryEntity|null $orderDelivery */
$orderDelivery = $this->orderDeliveryRepository->search($criteria, $event->getContext())->first();
if ($orderDelivery === null) {
throw new OrderDeliveryNotFoundException($orderDeliveryId);
}
if ($orderDelivery->getOrder() === null) {
throw new OrderNotFoundException($orderDeliveryId);
}
$context = $this->utility->getContext($orderDelivery->getOrder(), $event->getContext());
$order = $this->dbOrder->getOrderById($orderDelivery->getOrderId(), $this->utility->getOrderAssociations(), $context);
try {
$this->orderProcessor->processOrder($order, $context);
} catch (\Exception $e) {
$this->logger->error('[#fgits] fgitsAutoinvoiceSW6: ' . __CLASS__ . '::' . __FUNCTION__ . '(): Order #' . $order->getOrderNumber() . ': ' . print_r($e->getMessage(), true));
}
}
/**
* Gets invoked when the order status is changed.
*
* @param StateMachineStateChangeEvent $event
*/
public function onOrderStateChanged(StateMachineStateChangeEvent $event): void
{
$config = $this->systemConfigService->get('fgitsAutoinvoiceSW6.config', $event->getSalesChannelId());
if (!$config['active'] || empty($config['conditionOrderStatus'])) {
return;
}
$orderId = $event->getTransition()->getEntityId();
$criteria = new Criteria([$orderId]);
$criteria->addAssociation('orderCustomer');
$criteria->addAssociation('transactions');
$order = $this->orderRepository->search($criteria, $event->getContext())->first();
if ($order === null) {
throw new OrderNotFoundException($orderId);
}
$context = $this->utility->getContext($order, $event->getContext());
$order = $this->dbOrder->getOrderById($orderId, $this->utility->getOrderAssociations(), $context);
try {
$this->orderProcessor->processOrder($order, $context);
} catch (\Exception $e) {
$this->logger->error('[#fgits] fgitsAutoinvoiceSW6: ' . __CLASS__ . '::' . __FUNCTION__ . '(): Order #' . $order->getOrderNumber() . ': ' . print_r($e->getMessage(), true));
}
}
/**
* Gets invoked when the order status is changed.
*
* @param StateMachineStateChangeEvent $event
*/
public function onOrderStateChangedTickets(StateMachineStateChangeEvent $event): void
{
$config = $this->systemConfigService->get('FgitsTicketsV3.config', $event->getSalesChannelId());
if (!$this->utility->isPluginActive('FgitsTicketsV3') || !$config['extrasActive'] || ($config['extrasActionOnCancel'] == 'none' && $config['extrasActionOnReopen'] == 'none')) {
return;
}
if ($event->getNextState()->getTechnicalName() == 'cancelled') {
$ticketsExtras = $this->utility->getService('Fgits\FgitsTicketsV3\Service\Extras');
switch ($config['extrasActionOnCancel']) {
case 'deactivate':
$ticketsExtras->deactivateTickets($event->getTransition()->getEntityId(), $event->getContext());
break;
case 'delete':
$ticketsExtras->deleteTickets($event->getTransition()->getEntityId(), $event->getContext());
break;
}
} elseif ($event->getNextState()->getTechnicalName() == 'open' && $event->getPreviousState()->getTechnicalName() == 'cancelled' && $config['extrasActionOnReopen'] == 'activate') {
$ticketsExtras = $this->utility->getService('Fgits\FgitsTicketsV3\Service\Extras');
$ticketsExtras->activateTickets($event->getTransition()->getEntityId(), $event->getContext());
}
}
}