<?php
declare(strict_types=1);
namespace CioApprovalThreshold;
use CioApprovalThreshold\States\ApprovalStates;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
use Shopware\Core\Checkout\Order\OrderStates;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Plugin;
use Shopware\Core\Framework\Plugin\Context\InstallContext;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\StateMachine\Aggregation\StateMachineState\StateMachineStateEntity;
use Shopware\Core\System\StateMachine\Aggregation\StateMachineTransition\StateMachineTransitionEntity;
use Shopware\Core\System\StateMachine\StateMachineEntity;
class CioApprovalThreshold extends Plugin
{
protected ?EntityRepository $stateMachineRepository;
protected ?EntityRepository $stateMachineStateRepository;
protected ?EntityRepository $stateMachineTransitionRepository;
public function install(InstallContext $installContext): void
{
parent::install($installContext);
$this->initDependencies();
$stateMachine = $this->getStateMachine($installContext->getContext());
$this->createStateMachineState(ApprovalStates::STATE_OPEN_APPROVAL_REQUEST, 'Wartet auf Freigabe', 'Waiting for approval', $stateMachine, $installContext->getContext());
$this->createStateMachineState(ApprovalStates::STATE_SUCCESSFULLY_APPROVED, 'Freigabe ist erfolgt', 'Approval has been given', $stateMachine, $installContext->getContext());
$this->createStateMachineState(ApprovalStates::STATE_APPROVAL_DENIED, 'Freigabe verweigert', 'Approval canceled', $stateMachine, $installContext->getContext());
$this->createStateMachineState(ApprovalStates::STATE_APPROVAL_DENIED_AND_REVISION_REQUESTED, 'Revision angefordert', 'Requested revision', $stateMachine, $installContext->getContext());
$newStateMachineTransitions = [
[
'actionName' => ApprovalStates::NEEDS_APPROVAL_TRANSITION_NAME,
'stateMachineId' => $stateMachine->getId(),
'fromStateId' => $this->getStateMachineState(OrderStates::STATE_OPEN, $stateMachine, $installContext->getContext())->getId(),
'toStateId' => $this->getStateMachineState(ApprovalStates::STATE_OPEN_APPROVAL_REQUEST, $stateMachine, $installContext->getContext())->getId(),
],
[
'actionName' => ApprovalStates::APPROVED_TRANSITION_NAME,
'stateMachineId' => $stateMachine->getId(),
'fromStateId' => $this->getStateMachineState(ApprovalStates::STATE_OPEN_APPROVAL_REQUEST, $stateMachine, $installContext->getContext())->getId(),
'toStateId' => $this->getStateMachineState(ApprovalStates::STATE_SUCCESSFULLY_APPROVED, $stateMachine, $installContext->getContext())->getId(),
],
[
'actionName' => ApprovalStates::CANCEL_TRANSITION_NAME,
'stateMachineId' => $stateMachine->getId(),
'fromStateId' => $this->getStateMachineState(ApprovalStates::STATE_OPEN_APPROVAL_REQUEST, $stateMachine, $installContext->getContext())->getId(),
'toStateId' => $this->getStateMachineState(ApprovalStates::STATE_APPROVAL_DENIED, $stateMachine, $installContext->getContext())->getId(),
],
[
'actionName' => ApprovalStates::CANCEL_AND_REVISION_TRANSITION_NAME,
'stateMachineId' => $stateMachine->getId(),
'fromStateId' => $this->getStateMachineState(ApprovalStates::STATE_OPEN_APPROVAL_REQUEST, $stateMachine, $installContext->getContext())->getId(),
'toStateId' => $this->getStateMachineState(ApprovalStates::STATE_APPROVAL_DENIED_AND_REVISION_REQUESTED, $stateMachine, $installContext->getContext())->getId(),
],
[
'actionName' => ApprovalStates::CANCEL_REQUEST_AND_STORNO_ORDER_TRANSITION_NAME,
'stateMachineId' => $stateMachine->getId(),
'fromStateId' => $this->getStateMachineState(ApprovalStates::STATE_OPEN_APPROVAL_REQUEST, $stateMachine, $installContext->getContext())->getId(),
'toStateId' => $this->getStateMachineState(OrderStates::STATE_CANCELLED, $stateMachine, $installContext->getContext())->getId(),
],
[
'actionName' => ApprovalStates::APPROVED_ORDER_COMPLETED_TRANSITION_NAME,
'stateMachineId' => $stateMachine->getId(),
'fromStateId' => $this->getStateMachineState(ApprovalStates::STATE_SUCCESSFULLY_APPROVED, $stateMachine, $installContext->getContext())->getId(),
'toStateId' => $this->getStateMachineState(OrderStates::STATE_COMPLETED, $stateMachine, $installContext->getContext())->getId(),
]
];
foreach ($newStateMachineTransitions as $newStateMachineTransition) {
$stateMachineTransition = $this->getStateMachineTransition($newStateMachineTransition['actionName'], $newStateMachineTransition['stateMachineId'], $newStateMachineTransition['fromStateId'], $newStateMachineTransition['toStateId'], $installContext->getContext());
if (!$stateMachineTransition instanceof StateMachineTransitionEntity) {
$this->stateMachineTransitionRepository->create([$newStateMachineTransition], $installContext->getContext());
}
}
$mailTemplateTypeId = Uuid::randomHex();
$this->createEmailTypeWithTemplates(
[
'id' => $mailTemplateTypeId,
'name' => 'Freigabe notwendig Email für den berechtigten Freigeber',
'technicalName' => 'checkout_order_releaser_has_to_verify_type',
'availableEntities' => [
'order' => 'order'
]
],
[
[
'id' => Uuid::randomHex(),
'mailTemplateTypeId' => $mailTemplateTypeId,
'senderName' => '{{ salesChannel.name }}',
'subject' => [
'en-GB' => 'Prüfen sie die Bestellung mit der Nummer {{ order.orderNumber }}',
'de-DE' => 'Prüfen sie die Bestellung mit der Nummer {{ order.orderNumber }}'
],
'contentPlain' => "Sie wurden als Beauftragter für die Prüfung einer neuen Bestellung mit der Nummer {{ order.orderNumber }} ausgewählt. Sie können diese unter folgendem Link prüfen: {{ confirmUrl }}.",
'contentHtml' => '<p>Sie wurden als Beauftragter für die Prüfung einer neuen Bestellung mit der Nummer {{ order.orderNumber }} ausgewählt.</p><p>Sie können diese unter folgendem Link prüfen: <a href="{{ confirmUrl }}">{{ confirmUrl }}</a>.</p>',
]
],
$installContext->getContext()
);
$mailTemplateTypeId = Uuid::randomHex();
$this->createEmailTypeWithTemplates(
[
'id' => $mailTemplateTypeId,
'name' => 'Kunden über die erfolgte Freigabe informieren',
'technicalName' => 'checkout_order_customer_successfully_release_info',
'availableEntities' => [
'order' => 'order'
]
],
[
[
'id' => Uuid::randomHex(),
'mailTemplateTypeId' => $mailTemplateTypeId,
'senderName' => '{{ salesChannel.name }}',
'subject' => [
'en-GB' => 'Ihre Bestellung mit der Nummer {{ order.orderNumber }} wurde freigegeben',
'de-DE' => 'Ihre Bestellung mit der Nummer {{ order.orderNumber }} wurde freigegeben'
],
'contentPlain' => "Ihre Bestellung mit der Nummer {{ order.orderNumber }} wurde freigegeben. Wir werden ihre Bestellung jetzt zeitnah bearbeiten und an sie versenden.",
'contentHtml' => '<p>Ihre Bestellung mit der Nummer {{ order.orderNumber }} wurde freigegeben. Wir werden ihre Bestellung jetzt zeitnah bearbeiten und an sie versenden.</p>',
]
],
$installContext->getContext()
);
$mailTemplateTypeId = Uuid::randomHex();
$this->createEmailTypeWithTemplates(
[
'id' => $mailTemplateTypeId,
'name' => 'Kunden über die Verweigerung der Freigabe informieren',
'technicalName' => 'checkout_order_customer_not_released_info',
'availableEntities' => [
'order' => 'order'
]
],
[
[
'id' => Uuid::randomHex(),
'mailTemplateTypeId' => $mailTemplateTypeId,
'senderName' => '{{ salesChannel.name }}',
'subject' => [
'en-GB' => 'Ihre Bestellung mit der Nummer {{ order.orderNumber }} wurde storniert',
'de-DE' => 'Ihre Bestellung mit der Nummer {{ order.orderNumber }} wurde storniert'
],
'contentPlain' => "Es tut uns leid, ihnen mitteilen zu müssen, dass ihre Bestellung mit der Nummer {{ order.orderNumber }} nicht freigegeben wurde. Der Kommentar des Freigebers: {{ comment }} Sie befindet sich jetzt in dem Status storniert.",
'contentHtml' => '<p>Es tut uns leid, ihnen mitteilen zu müssen, dass ihre Bestellung mit der Nummer {{ order.orderNumber }} nicht freigegeben wurde. Der Kommentar des Freigebers: </p><p>{{ comment }}</p><p> Sie befindet sich jetzt in dem Status storniert.</p>',
]
],
$installContext->getContext()
);
$mailTemplateTypeId = Uuid::randomHex();
$this->createEmailTypeWithTemplates(
[
'id' => $mailTemplateTypeId,
'name' => 'Kunden über die Anforderung einer Revision informieren',
'technicalName' => 'checkout_order_customer_requested_revision_info',
'availableEntities' => [
'order' => 'order'
]
],
[
[
'id' => Uuid::randomHex(),
'mailTemplateTypeId' => $mailTemplateTypeId,
'senderName' => '{{ salesChannel.name }}',
'subject' => [
'en-GB' => 'Für ihre Bestellung mit der Nummer {{ order.orderNumber }} wurde eine Revision angefordert',
'de-DE' => 'Für ihre Bestellung mit der Nummer {{ order.orderNumber }} wurde eine Revision angefordert'
],
'contentPlain' => "Ihre Bestellung mit der Nummer {{ order.orderNumber }} wurde vom Freigeber nicht freigegeben und eine Revision angefordert. Der Kommentar des Freigebers: {{ comment }} Sie können den Warenkorb erneut laden und anpassen unter dem Link {{ confirmUrl }}.",
'contentHtml' => '<p>Ihre Bestellung mit der Nummer {{ order.orderNumber }} wurde vom Freigeber nicht freigegeben und eine Revision angefordert. Der Kommentar des Freigebers: </p><p>{{ comment }}</p><p>Sie können den Warenkorb erneut laden und anpassen unter dem Link <a href="{{ confirmUrl }}">{{ confirmUrl }}</a>.</p>',
]
],
$installContext->getContext()
);
}
protected function initDependencies()
{
$this->stateMachineRepository = $this->container->get('state_machine.repository');
$this->stateMachineStateRepository = $this->container->get('state_machine_state.repository');
$this->stateMachineTransitionRepository = $this->container->get('state_machine_transition.repository');
}
protected function getStateMachine(Context $context): ?StateMachineEntity
{
$stateMachineCriteria = new Criteria();
$stateMachineCriteria->addFilter(new EqualsFilter('technicalName', ApprovalStates::STATE_MACHINE));
return $this->stateMachineRepository->search($stateMachineCriteria, $context)->first();
}
protected function getStateMachineState(string $technicalName, StateMachineEntity $stateMachine, Context $context): ?StateMachineStateEntity
{
$stateMachineStateCriteria = new Criteria();
$stateMachineStateCriteria->addFilter(new EqualsFilter('stateMachineId', $stateMachine->getId()));
$stateMachineStateCriteria->addFilter(new EqualsFilter('technicalName', $technicalName));
return $this->stateMachineStateRepository->search($stateMachineStateCriteria, $context)->first();
}
protected function getStateMachineTransition(string $actionName, string $stateMachineId, string $fromStateId, string $toStateId, Context $context): ?StateMachineTransitionEntity
{
$stateMachineTransitionCriteria = new Criteria();
$stateMachineTransitionCriteria->addFilter(new EqualsFilter('actionName', $actionName));
$stateMachineTransitionCriteria->addFilter(new EqualsFilter('stateMachineId', $stateMachineId));
$stateMachineTransitionCriteria->addFilter(new EqualsFilter('fromStateId', $fromStateId));
$stateMachineTransitionCriteria->addFilter(new EqualsFilter('toStateId', $toStateId));
return $this->stateMachineTransitionRepository->search($stateMachineTransitionCriteria, $context)->first();
}
protected function createEmailTypeWithTemplates(array $type, array $templates, Context $context)
{
/** @var EntityRepositoryInterface $mailTemplateTypeRepository */
$mailTemplateTypeRepository = $this->container->get('mail_template_type.repository');
/** @var EntityRepositoryInterface $mailTemplateRepository */
$mailTemplateRepository = $this->container->get('mail_template.repository');
try {
$mailTemplateTypeRepository->create([$type], $context);
$mailTemplateRepository->create($templates, $context);
} catch (UniqueConstraintViolationException $exception) {
// No, we've already installed the fields, it's fine.
}
}
protected function createStateMachineState(string $technicalName, string $gerName, string $engName, StateMachineEntity $stateMachine, Context $context)
{
$stateMachineSuccessfullyApprovedState = $this->getStateMachineState($technicalName, $stateMachine, $context);
if (!$stateMachineSuccessfullyApprovedState instanceof StateMachineStateEntity) {
$newState = [
'technicalName' => $technicalName,
'stateMachineId' => $stateMachine->getId(),
'translations' => [
'de-DE' => [
'name' => $gerName
],
'en-GB' => [
'name' => $engName
]
]
];
$this->stateMachineStateRepository->create([$newState], $context);
}
}
}