<?php
namespace CodeCouncil\ErpOrdersWriter\Subscriber;
use CodeCouncil\ErpOrdersWriter\ERP\ERPConnectorService;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedCriteriaEvent;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity;
use Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionStates;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\StateMachine\Event\StateMachineStateChangeEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class OrderSubscriber implements EventSubscriberInterface
{
private ERPConnectorService $ERPConnectorService;
private LoggerInterface $logger;
private EntityRepository $orderTransactionRepository;
public function __construct(ERPConnectorService $ERPConnectorService, LoggerInterface $logger, EntityRepository $orderTransactionRepository)
{
$this->ERPConnectorService = $ERPConnectorService;
$this->logger = $logger;
$this->orderTransactionRepository = $orderTransactionRepository;
}
public static function getSubscribedEvents()
{
return [
CheckoutOrderPlacedCriteriaEvent::class => 'orderCreatedCriteriaEvent',
CheckoutOrderPlacedEvent::class => "orderCreatedEvent",
'state_machine.order_transaction.state_changed' => 'orderTransactionStateChange',
];
}
public function orderCreatedCriteriaEvent(CheckoutOrderPlacedCriteriaEvent $event)
{
//We need following for email sent to order@iceberg.de
$criteria = $event->getCriteria();
$criteria->addAssociations([
'billingAddress.country',
'billingAddress.countryState',
'deliveries.shippingOrderAddress.country',
'deliveries.shippingOrderAddress.countryState'
]);
}
/**
* Triggered when order is placed.
*
* @param CheckoutOrderPlacedEvent $event
* @return void
*/
public function orderCreatedEvent(CheckoutOrderPlacedEvent $event)
{
$this->logger->info("Order placed event order: " . $event->getOrder()->getOrderNumber());
$orderIds = $this->ERPConnectorService->createOrder($event->getOrder(), $event->getContext());
if ($orderIds === null) {
$this->logger->error("Failed to place order (number) " . $event->getOrder()->getOrderNumber() . " into ERP after order has been placed in shop!");
return;
}
['erpOrderId' => $orderId, 'erpCustomerId' => $customerId] = $orderIds;
$this->ERPConnectorService->sendInvoicePDFForOrder($orderId, $customerId);
}
public function orderTransactionStateChange(StateMachineStateChangeEvent $event)
{
$nextState = $event->getNextState()->getTechnicalName();
$prevState = $event->getPreviousState()->getTechnicalName();
$this->logger->info("Order transaction state changed from: " . $prevState . " to: " . $nextState);
//We want to mark paid if new state is paid or authorized.
if ($nextState !== OrderTransactionStates::STATE_PAID && $nextState !== OrderTransactionStates::STATE_AUTHORIZED)
return;
//Probably after order is authortized it will be marked as paid so if from state is authorized lets not do anything.
if($prevState === OrderTransactionStates::STATE_AUTHORIZED)
return;
if ($event->getTransition()->getEntityName() !== 'order_transaction') {
$this->logger->warning("Expected orderTransactionStateChange entity name to be order_transaction, given: " . $event->getTransition()->getEntityName());
return;
}
$context = $event->getContext();
$criteria = new Criteria([$event->getTransition()->getEntityId()]);
$criteria->setLimit(1);
$criteria->addAssociation('order.transactions');
/** @var OrderTransactionEntity $orderTransaction */
$orderTransaction = $this->orderTransactionRepository->search($criteria, $context)->first();
if ($orderTransaction === null) {
$this->logger->error("Failed to fetch order transaction inside orderTransactionStateChange event!");
return;
}
$order = $orderTransaction->getOrder();
if ($order === null) {
$this->logger->error("Failed to fetch order inside orderTransactionStateChange event!");
return;
}
$this->logger->info("Marking order " . $order->getOrderNumber() . " as paid...");
$status = $this->ERPConnectorService->markOrderAsPaid($order, $context);
if (!$status)
$this->logger->error("Failed to mark order as paid inside orderTransactionStateChange event!");
}
}