<?php
namespace CioApprovalThreshold\Subscriber;
use CioApprovalThreshold\Event\ReleaserHasToVerifyOrderEvent;
use CioApprovalThreshold\States\ApprovalStates;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Checkout\Order\OrderDefinition;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Event\EventData\MailRecipientStruct;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\SalesChannel\Context\AbstractSalesChannelContextFactory;
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
use Shopware\Core\System\StateMachine\StateMachineRegistry;
use Shopware\Core\System\StateMachine\Transition;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Routing\Router;
use Symfony\Component\Routing\RouterInterface;
class OrderPlacedSubscriber implements EventSubscriberInterface
{
private EventDispatcherInterface $eventDispatcher;
private RequestStack $requestStack;
private EntityRepository $orderRepository;
private EntityRepository $customerRepository;
private StateMachineRegistry $stateMachineRegistry;
private AbstractSalesChannelContextFactory $salesChannelContextFactory;
private RouterInterface $router;
public function __construct(EventDispatcherInterface $eventDispatcher, RequestStack $requestStack, EntityRepository $orderRepository, EntityRepository $customerRepository, StateMachineRegistry $stateMachineRegistry, AbstractSalesChannelContextFactory $salesChannelContextFactory, RouterInterface $router)
{
$this->eventDispatcher = $eventDispatcher;
$this->requestStack = $requestStack;
$this->orderRepository = $orderRepository;
$this->customerRepository = $customerRepository;
$this->stateMachineRegistry = $stateMachineRegistry;
$this->salesChannelContextFactory = $salesChannelContextFactory;
$this->router = $router;
}
public static function getSubscribedEvents()
{
return [
CheckoutOrderPlacedEvent::class => 'onCheckoutOrderPlacedEvent'
];
}
public function onCheckoutOrderPlacedEvent(CheckoutOrderPlacedEvent $event)
{
$order = $event->getOrder();
$request = $this->requestStack->getCurrentRequest();
$releaseCustomerId = $request->request->get('cioSelectedReleaseCustomerId');
if (is_string($releaseCustomerId) && Uuid::isValid($releaseCustomerId)) {
$criteria = new Criteria([$releaseCustomerId]);
$releaseCustomer = $this->customerRepository->search($criteria, $event->getContext())->first();
if ($releaseCustomer instanceof CustomerEntity) {
// load current version of order from repository
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('id', $order->getId()));
$orderForCustomFields = $this->orderRepository->search($criteria, $event->getContext())->first();
$customFields = [];
if ($orderForCustomFields instanceof OrderEntity && is_array($orderForCustomFields->getCustomFields())) {
$customFields = $orderForCustomFields->getCustomFields();
}
$customFields['cioApprovalThresholdReleaseCustomerFirstName'] = $releaseCustomer->getFirstName();
$customFields['cioApprovalThresholdReleaseCustomerLastName'] = $releaseCustomer->getLastName();
// save on checkout confirm page selected customer that is responsible for releasing this new order
$this->orderRepository->update([
[
'id' => $order->getId(),
'approvalThresholdExtension' => [
'selectedReleaseCustomerId' => $releaseCustomer->getId()
],
'customFields' => $customFields
]
], $event->getContext());
$order->setCustomFields($customFields);
// change state of order from "open" to "needs release"
$salesChannelContext = $this->salesChannelContextFactory->create('', $order->getSalesChannelId(), [SalesChannelContextService::LANGUAGE_ID => $order->getLanguageId()]);
$this->stateMachineRegistry->transition(
new Transition(
OrderDefinition::ENTITY_NAME,
$order->getId(),
ApprovalStates::NEEDS_APPROVAL_TRANSITION_NAME,
'stateId'
),
$salesChannelContext->getContext()
);
// customer that is responsible for releasing this new order must get a mail with url that allows verification of the order, event is available in flow builder
$confirmUrl = $this->router->generate('storefront.cioapprovalthreshold.verify.page', [
'orderId' => $order->getId()
], Router::ABSOLUTE_URL);
$event = new ReleaserHasToVerifyOrderEvent($event->getContext(), $order, $order->getSalesChannelId(), $confirmUrl, new MailRecipientStruct([$releaseCustomer->getEmail() => $releaseCustomer->getEmail()]));
$this->eventDispatcher->dispatch($event);
}
}
}
}