vendor/shopware/core/Content/Flow/Dispatching/Action/GenerateDocumentAction.php line 60

Open in your IDE?
  1. <?php declare(strict_types=1);
  2. namespace Shopware\Core\Content\Flow\Dispatching\Action;
  3. use Doctrine\DBAL\Connection;
  4. use Psr\Log\LoggerInterface;
  5. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  6. use Shopware\Core\Checkout\Document\DocumentConfigurationFactory;
  7. use Shopware\Core\Checkout\Document\DocumentGenerator\CreditNoteGenerator;
  8. use Shopware\Core\Checkout\Document\DocumentGenerator\DeliveryNoteGenerator;
  9. use Shopware\Core\Checkout\Document\DocumentGenerator\InvoiceGenerator;
  10. use Shopware\Core\Checkout\Document\DocumentGenerator\StornoGenerator;
  11. use Shopware\Core\Checkout\Document\DocumentService;
  12. use Shopware\Core\Checkout\Document\FileGenerator\FileTypes;
  13. use Shopware\Core\Defaults;
  14. use Shopware\Core\Framework\Event\FlowEvent;
  15. use Shopware\Core\Framework\Event\OrderAware;
  16. use Shopware\Core\Framework\Event\SalesChannelAware;
  17. use Shopware\Core\System\NumberRange\ValueGenerator\NumberRangeValueGeneratorInterface;
  18. class GenerateDocumentAction extends FlowAction
  19. {
  20.     protected DocumentService $documentService;
  21.     protected Connection $connection;
  22.     private NumberRangeValueGeneratorInterface $valueGenerator;
  23.     private LoggerInterface $logger;
  24.     public function __construct(
  25.         DocumentService $documentService,
  26.         NumberRangeValueGeneratorInterface $valueGenerator,
  27.         Connection $connection,
  28.         LoggerInterface $logger
  29.     ) {
  30.         $this->documentService $documentService;
  31.         $this->valueGenerator $valueGenerator;
  32.         $this->connection $connection;
  33.         $this->logger $logger;
  34.     }
  35.     public static function getName(): string
  36.     {
  37.         return 'action.generate.document';
  38.     }
  39.     public static function getSubscribedEvents(): array
  40.     {
  41.         return [
  42.             self::getName() => 'handle',
  43.         ];
  44.     }
  45.     public function requirements(): array
  46.     {
  47.         return [OrderAware::class];
  48.     }
  49.     public function handle(FlowEvent $event): void
  50.     {
  51.         $baseEvent $event->getEvent();
  52.         if (!$baseEvent instanceof OrderAware || !$baseEvent instanceof SalesChannelAware) {
  53.             return;
  54.         }
  55.         $eventConfig $event->getConfig();
  56.         $documentType $eventConfig['documentType'];
  57.         $documentRangerType $eventConfig['documentRangerType'];
  58.         if (!$documentType || !$documentRangerType) {
  59.             return;
  60.         }
  61.         $documentNumber $this->valueGenerator->getValue(
  62.             $eventConfig['documentRangerType'],
  63.             $baseEvent->getContext(),
  64.             $baseEvent->getSalesChannelId()
  65.         );
  66.         $now = (new \DateTime())->format(Defaults::STORAGE_DATE_TIME_FORMAT);
  67.         $eventConfig['documentNumber'] = $documentNumber;
  68.         $eventConfig['documentDate'] = $now;
  69.         $customConfig $this->getEventCustomConfig(
  70.             $documentType,
  71.             $documentNumber,
  72.             $now,
  73.             $baseEvent->getOrderId()
  74.         );
  75.         if (empty($customConfig)) {
  76.             return;
  77.         }
  78.         $eventConfig['custom'] = $customConfig;
  79.         $documentConfig DocumentConfigurationFactory::createConfiguration($eventConfig);
  80.         $this->documentService->create(
  81.             $baseEvent->getOrderId(),
  82.             $documentType,
  83.             $eventConfig['fileType'] ?? FileTypes::PDF,
  84.             $documentConfig,
  85.             $baseEvent->getContext(),
  86.             $customConfig['referencedInvoiceId'] ?? null,
  87.             $eventConfig['static'] ?? false
  88.         );
  89.     }
  90.     private function getEventCustomConfig(string $documentTypestring $documentNumberstring $nowstring $orderId): array
  91.     {
  92.         switch ($documentType) {
  93.             case InvoiceGenerator::INVOICE:
  94.                 return ['invoiceNumber' => $documentNumber];
  95.             case DeliveryNoteGenerator::DELIVERY_NOTE:
  96.                 return [
  97.                     'deliveryNoteNumber' => $documentNumber,
  98.                     'deliveryDate' => $now,
  99.                     'deliveryNoteDate' => $now,
  100.                 ];
  101.             case StornoGenerator::STORNO:
  102.             case CreditNoteGenerator::CREDIT_NOTE:
  103.                 return $this->getConfigWithReferenceDoc($documentType$documentNumber$orderId);
  104.             default:
  105.                 return [];
  106.         }
  107.     }
  108.     private function getConfigWithReferenceDoc(string $documentTypestring $documentNumberstring $orderId): array
  109.     {
  110.         $referencedInvoiceDocument $this->connection->fetchAssociative(
  111.             'SELECT LOWER (HEX(`document`.`id`)) as `id` , `document`.`config` as `config`
  112.                     FROM `document` JOIN `document_type` ON `document`.`document_type_id` = `document_type`.`id`
  113.                     WHERE `document_type`.`technical_name` = :techName AND hex(`document`.`order_id`) = :orderId
  114.                     ORDER BY `document`.`created_at` DESC LIMIT 1',
  115.             [
  116.                 'techName' => InvoiceGenerator::INVOICE,
  117.                 'orderId' => $orderId,
  118.             ]
  119.         );
  120.         if (empty($referencedInvoiceDocument)) {
  121.             $this->logger->info(
  122.                 'Can not generate ' $documentType ' document because no invoice document exists. OrderId: ' $orderId
  123.             );
  124.             return [];
  125.         }
  126.         if ($documentType === CreditNoteGenerator::CREDIT_NOTE && !$this->hasCreditItem($orderId)) {
  127.             $this->logger->info(
  128.                 'Can not generate the credit note document because no credit items exist. OrderId: ' $orderId
  129.             );
  130.             return [];
  131.         }
  132.         $documentRefer json_decode($referencedInvoiceDocument['config'], true);
  133.         $documentNumberRefer $documentRefer['custom']['invoiceNumber'];
  134.         return array_filter([
  135.             'invoiceNumber' => $documentNumberRefer,
  136.             'stornoNumber' => $documentType === StornoGenerator::STORNO $documentNumber null,
  137.             'creditNoteNumber' => $documentType === CreditNoteGenerator::CREDIT_NOTE $documentNumber null,
  138.             'referencedInvoiceId' => $referencedInvoiceDocument['id'],
  139.         ]);
  140.     }
  141.     private function hasCreditItem(string $orderId): bool
  142.     {
  143.         $lineItem $this->connection->fetchFirstColumn(
  144.             'SELECT 1 FROM `order_line_item` WHERE hex(`order_id`) = :orderId and `type` = :itemType LIMIT 1',
  145.             [
  146.                 'orderId' => $orderId,
  147.                 'itemType' => LineItem::CREDIT_LINE_ITEM_TYPE,
  148.             ]
  149.         );
  150.         return !empty($lineItem);
  151.     }
  152. }