<?php
/**
* WBFK OG
* Copyright (c) 2024 WBFK OG
*
* @copyright Copyright (c) 2024 WBFK OG (https://wbfk.at)
* @author WBFK OG <info@wbfk.at>
*/
declare(strict_types=1);
namespace Wbfk\DigitalInvoice\Subscriber;
use Easybill\ZUGFeRD2\Builder;
use Shopware\Core\Checkout\Document\Renderer\CreditNoteRenderer;
use Shopware\Core\Checkout\Document\Renderer\InvoiceRenderer;
use Shopware\Core\Checkout\Document\Renderer\StornoRenderer;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Wbfk\DigitalInvoice\Core\Document\DigitalDocumentConfigExtension;
use Wbfk\DigitalInvoice\Core\Document\DigitalGeneratedDocumentExtension;
use Wbfk\DigitalInvoice\Entity\Order\WbfkInvoiceDetailsOrderExtensionEntity;
use Wbfk\DigitalInvoice\Event\GenerateDocumentEvent;
use Wbfk\DigitalInvoice\Service\Document\DocumentService;
use Wbfk\DigitalInvoice\Service\Document\ZugferdException;
use Wbfk\DigitalInvoice\Service\Document\ZugferdService;
use Wbfk\DigitalInvoice\Service\Utils\SystemConfigReader;
class GenerateDocumentSubscriber implements EventSubscriberInterface
{
public function __construct(
private readonly ZugferdService $zugferdService,
private readonly SystemConfigReader $systemConfigReader,
) {
}
public static function getSubscribedEvents(): array
{
return [
DocumentService::GENERATE_DOCUMENT_EVENT => 'generateDocumentEvent',
];
}
/**
* @throws ZugferdException
*/
public function generateDocumentEvent(GenerateDocumentEvent $event): void
{
$wbfkDocumentExtension = DigitalDocumentConfigExtension::fromDocumentConfig($event->documentConfiguration);
if (!$wbfkDocumentExtension) {
return;
}
$defaultInvoiceType = $this->systemConfigReader->stringOrNull('defaultInvoiceType');
$invoiceType = $wbfkDocumentExtension?->getInvoiceType() ?: $defaultInvoiceType;
if ($invoiceType === WbfkInvoiceDetailsOrderExtensionEntity::$INVOICE_TYPE_ZUGFERD_EN16931) {
$this->zugferd(Builder::GUIDELINE_SPECIFIED_DOCUMENT_CONTEXT_ID_EN16931, $wbfkDocumentExtension, $event);
} elseif (
$invoiceType === WbfkInvoiceDetailsOrderExtensionEntity::$INVOICE_TYPE_X_INVOICE
|| $invoiceType === WbfkInvoiceDetailsOrderExtensionEntity::$INVOICE_TYPE_ZUGFERD_X_INVOICE
) {
$this->zugferd(Builder::GUIDELINE_SPECIFIED_DOCUMENT_CONTEXT_ID_XRECHNUNG, $wbfkDocumentExtension, $event);
}
}
/**
* @throws ZugferdException
*/
private function zugferd(string $profile, DigitalDocumentConfigExtension $wbfkDocumentExtension, GenerateDocumentEvent $event): void
{
$docExt = new DigitalGeneratedDocumentExtension();
$docExt->type = ($profile === Builder::GUIDELINE_SPECIFIED_DOCUMENT_CONTEXT_ID_XRECHNUNG) ?
DigitalGeneratedDocumentExtension::TYPE_XINVOICE : DigitalGeneratedDocumentExtension::TYPE_ZUGFERD;
/** @noinspection PhpDeprecationInspection */
$event->generatedDocument->addExtension(DigitalGeneratedDocumentExtension::NAME, $docExt);
$this->catchAndShowErrorInPreview(function () use ($profile, $event, $docExt, $wbfkDocumentExtension) {
$docName = $event->documentType->getTechnicalName();
if ($docName === InvoiceRenderer::TYPE) {
$docExt->zugferdXml = $this->zugferdService->invoice($profile, $event->documentConfiguration, $wbfkDocumentExtension, $event->order);
} elseif ($docName === CreditNoteRenderer::TYPE) {
$docExt->zugferdXml = $this->zugferdService->creditNote($profile, $event->documentConfiguration, $wbfkDocumentExtension, $event->order);
} elseif ($docName === StornoRenderer::TYPE) {
$docExt->zugferdXml = $this->zugferdService->cancellation($profile, $event->documentConfiguration, $wbfkDocumentExtension, $event->order);
}
}, $event->isPreview, $docExt);
}
/**
* @throws ZugferdException
*/
private function catchAndShowErrorInPreview(callable $func, bool $isPreview, DigitalGeneratedDocumentExtension $docExt): void
{
if ($isPreview) {
try {
$func();
} catch (ZugferdException $exception) {
$docExt->errors[] = $exception;
}
} else {
$func();
}
}
}