<?php declare(strict_types=1);
namespace Iwv\IwvDatevV6\Subscriber;
use Iwv\IwvDatevV6\Core\Content\IwvDatevPayment\IwvDatevPaymentDefinition;
use Iwv\IwvDatevV6\Service\VariablesExporterExt\VariablesExporterConfig;
use Iwv\IwvDatevV6\Service\VariablesExporterService;
use Psr\Log\LoggerInterface;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\Uuid\Uuid;
use Shopware\Core\System\StateMachine\Event\StateMachineStateChangeEvent;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class OrderPaymentStateChangeListener implements EventSubscriberInterface
{
/** @var EntityRepositoryInterface */
private $datevPaymentsRepository;
/** @var EntityRepositoryInterface */
private $transactionRepository;
/** @var VariablesExporterService */
private $variablesExporterService;
/** @var SystemConfigService */
private $systemConfigService;
/** @var LoggerInterface $logger */
private $logger;
public function __construct(
EntityRepositoryInterface $datevPaymentsRepository,
EntityRepositoryInterface $transactionRepository,
VariablesExporterService $variablesExporterService,
SystemConfigService $systemConfigService,
LoggerInterface $logger
) {
$this->datevPaymentsRepository = $datevPaymentsRepository;
$this->transactionRepository = $transactionRepository;
$this->variablesExporterService = $variablesExporterService;
$this->systemConfigService = $systemConfigService;
$this->logger = $logger;
}
public static function getSubscribedEvents(): array
{
return [
'state_machine.order_transaction.state_changed' => 'onOrderPaymentStateChange',
];
}
/**
* @param StateMachineStateChangeEvent $event
* @return void
*/
public function onOrderPaymentStateChange(StateMachineStateChangeEvent $event): void
{
if ($event->getTransitionSide() !== 'state_enter' || !in_array($event->getStateName(), ['paid', 'paid_partially', 'refunded', 'refunded_partially'])) {
return;
}
try {
$orderTransactionId = $event->getTransition()->getEntityId();
$criteria = new Criteria([$orderTransactionId]);
$criteria->addAssociation('order.documents.documentType');
$criteria->getAssociation('order.documents')->addSorting(new FieldSorting('createdAt', FieldSorting::DESCENDING));
/** @var \Shopware\Core\Checkout\Order\Aggregate\OrderTransaction\OrderTransactionEntity $orderTransactionDB */
$orderTransactionDB = $this->transactionRepository
->search($criteria, $event->getContext())
->first();
/** @var \Shopware\Core\Checkout\Order\OrderEntity $orderDB */
$orderDB = $orderTransactionDB->getOrder();
if ($orderDB) {
$this->variablesExporterService->loadLatestOrders(new Criteria([$orderDB->getId()]), new VariablesExporterConfig(), $event->getContext());
$variables = $this->variablesExporterService->getLatestOrderVariables($orderDB->getId(), []);
$timezone = $this->systemConfigService->get('IwvDatevV6.config.exportTimezone', $orderDB->getCurrencyId()) ?: 'Europe/Berlin';
$paymentEntryData = [
'id' => Uuid::randomHex(),
'orderId' => $orderDB->getId(),
'orderVersionId' => $orderDB->getVersionId(),
'paymentDate' => (new \DateTime)->setTimezone(new \DateTimeZone($timezone))->format('Y-m-d'),
'amount' => $orderDB->getAmountTotal() * (in_array($event->getStateName(), ['refunded', 'refunded_partially']) ? -1 : 1),
'currencyId' => $orderDB->getCurrencyId(),
'paymentMethodId' => $orderTransactionDB->getPaymentMethodId(),
'paymentReference' => $variables['{order_transaction_id}'],
'isSystem' => true
];
$profiles = (array)$this->systemConfigService->get('IwvDatevV6.config.' . ($paymentEntryData['amount'] < 0 ? 'creditNoteProfileDocuments' : 'invoiceProfileDocuments'));
if (isset($profiles[0]) && $profiles[0] === 'credit_note,storno') {
$profiles = ['credit_note', 'storno'];
}
foreach ($orderDB->getDocuments() as $documentDB) {
if (in_array($documentDB->getDocumentType()->getTechnicalName(), $profiles)) {
$paymentEntryData['documentId'] = $documentDB->getId();
break 1;
}
}
$event->getContext()->scope(Context::SYSTEM_SCOPE, function (Context $context) use ($paymentEntryData): void {
$this->datevPaymentsRepository->create([$paymentEntryData], $context);
});
}
} catch (\Throwable $ex) {
$this->logger->error('Error on creating DATEV Payment: ' . $ex->getMessage() . ' ' . basename($ex->getFile()) . ':' . $ex->getLine());
}
}
}