custom/plugins/ProcOrderSimulate/src/Subscriber/OrderSimulateSubscriber.php line 241

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace Proc\ProcOrderSimulate\Subscriber;
  4. use Proc\ProcFoundation\Helper\RequestHandler;
  5. use Proc\ProcFoundation\Helper\ErrorHandler;
  6. use Proc\ProcFoundation\Service\ProcFoundationService;
  7. use Proc\ProcOrderSimulate\Helper\BuildRequestHelper;
  8. use Shopware\Core\Checkout\Cart\Cart;
  9. use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
  10. use Shopware\Core\Checkout\Cart\Exception\MissingPriceDefinitionException;
  11. use Shopware\Core\Checkout\Cart\LineItem\LineItem;
  12. use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
  13. use Shopware\Core\Checkout\Cart\Price\AbsolutePriceCalculator;
  14. use Shopware\Core\Checkout\Cart\Price\CurrencyPriceCalculator;
  15. use Shopware\Core\Checkout\Cart\Price\PercentagePriceCalculator;
  16. use Shopware\Core\Checkout\Cart\Price\Struct\AbsolutePriceDefinition;
  17. use Shopware\Core\Checkout\Cart\Price\Struct\CartPrice;
  18. use Shopware\Core\Checkout\Cart\Price\Struct\CurrencyPriceDefinition;
  19. use Shopware\Core\Checkout\Cart\Price\Struct\PercentagePriceDefinition;
  20. use Shopware\Core\Checkout\Cart\Price\Struct\ListPrice;
  21. use Shopware\Core\Checkout\Cart\Tax\Struct\CalculatedTax;
  22. use Shopware\Core\Checkout\Cart\Tax\Struct\CalculatedTaxCollection;
  23. use Shopware\Core\Checkout\Cart\Price\Struct\CalculatedPrice;
  24. use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRuleCollection;
  25. use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRule;
  26. use Shopware\Core\Checkout\Order\OrderEntity;
  27. use Shopware\Core\Content\MailTemplate\Service\Event\MailBeforeValidateEvent;
  28. use Shopware\Core\Content\Product\DataAbstractionLayer\CheapestPrice\CalculatedCheapestPrice;
  29. use Shopware\Core\Content\Product\DataAbstractionLayer\CheapestPrice\CheapestPriceContainer;
  30. use Shopware\Core\Content\Product\ProductEntity;
  31. use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
  32. use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
  33. use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
  34. use Shopware\Core\System\SalesChannel\Context\AbstractSalesChannelContextFactory;
  35. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextFactory;
  36. use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
  37. use Shopware\Core\System\SalesChannel\SalesChannelContext;
  38. use Shopware\Core\System\SystemConfig\SystemConfigService;
  39. use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
  40. use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
  41. use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
  42. use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
  43. use Shopware\Storefront\Page\PageLoadedEvent;
  44. use Shopware\Core\Checkout\Cart\Delivery\Struct\Delivery;
  45. use Shopware\Core\Checkout\Cart\Delivery\Struct\DeliveryCollection;
  46. use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
  47. use Shopware\Core\Checkout\Cart\AbstractCartPersister;
  48. use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
  49. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  50. use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
  51. /**
  52.  * Class OrderSimulateSubscriber
  53.  *
  54.  * @package Proc\ProcOrderSimulate\Subscriber
  55.  */
  56. class OrderSimulateSubscriber implements EventSubscriberInterface
  57. {
  58.     private const PLUGINNAME 'ProcOderSimulate';
  59.     private const PATH '/iman/order-simulate';
  60.     public const EUR_THRESHOLD 250;
  61.     public const ZLOTY_THRESHOLD 1062;
  62.     /**
  63.      * @var RequestHandler
  64.      */
  65.     private $requestHandler;
  66.     /**
  67.      * @var ErrorHandler
  68.      */
  69.     private $errorHandler;
  70.     /**
  71.      * @var string
  72.      */
  73.     private $host,
  74.         $port,
  75.         $customerNumber;
  76.     private $error null;
  77.     /**
  78.      * @var ProcFoundationService
  79.      */
  80.     private $foundationService;
  81.     /**
  82.      * @var EntityRepositoryInterface
  83.      */
  84.     private $productRepository;
  85.     /**
  86.      * @var CheckoutCartPageLoadedEvent | CheckoutConfirmPageLoadedEvent | CheckoutFinishPageLoadedEvent | ProductPageLoadedEvent | CheckoutOrderPlacedEvent | MailBeforeValidateEvent
  87.      */
  88.     private $event;
  89.     /**
  90.      * @var array
  91.      */
  92.     private $result;
  93.     /**
  94.      * @var CalculatedTaxCollection
  95.      */
  96.     private $calculatedTaxCollection;
  97.     /**
  98.      * @var TaxRuleCollection
  99.      */
  100.     private $taxRuleCollection;
  101.     /**
  102.      * @var LineItemCollection
  103.      */
  104.     private $lineItems;
  105.     /**
  106.      * @var Cart
  107.      */
  108.     private $cart;
  109.     /**
  110.      * @var float
  111.      */
  112.     private $lineItemsCost;
  113.     private $baseObj;
  114.     /**
  115.      * @var array
  116.      */
  117.     private $taxValues = [];
  118.     /**
  119.      * @var AbstractCartPersister
  120.      */
  121.     private $persister;
  122.     /**
  123.      * @var EntityRepositoryInterface
  124.      */
  125.     private $orderRepository;
  126.     /**
  127.      * @var DeliveryCollection
  128.      */
  129.     private $delivery;
  130.     /** Used for promotions with a fixed values */
  131.     protected const ZRN2 "ZRN2";
  132.     /** Used for promotions with percentage */
  133.     protected const ZRN0 "ZRN0";
  134.     /**
  135.      * @return array
  136.      */
  137.     static function getSubscribedEvents(): array
  138.     {
  139.         return [
  140.             ProductPageLoadedEvent::class => ['onProductPageLoaded'1],
  141.             CheckoutCartPageLoadedEvent::class => ['onCartPageLoaded'1],
  142.             CheckoutConfirmPageLoadedEvent::class => ['onCartPageLoaded'1],
  143.             OffcanvasCartPageLoadedEvent::class => ['onCartPageLoaded'1],
  144.             CheckoutFinishPageLoadedEvent::class => ['onFinishPageLoaded'1],
  145.             CheckoutOrderPlacedEvent::class => ['onCheckoutOrderPlaced'1],
  146.             MailBeforeValidateEvent::class => ['mailBeforeSent'1]
  147.         ];
  148.     }
  149.     /**
  150.      * OrderSimulateSubscriber constructor.
  151.      *
  152.      * @param ProcFoundationService $foundationService
  153.      * @param RequestHandler $requestHandler
  154.      * @param ErrorHandler $errorHandler
  155.      * @param EntityRepositoryInterface $repositoryInterface
  156.      * @param AbstractCartPersister $persister
  157.      * @param SalesChannelContextFactory $salesChannelContextFactory
  158.      */
  159.     public function __construct(
  160.         ProcFoundationService $foundationService,
  161.         RequestHandler $requestHandler,
  162.         ErrorHandler $errorHandler,
  163.         EntityRepositoryInterface $repositoryInterface,
  164.         AbstractCartPersister $persister,
  165.         EntityRepositoryInterface $orderRepository,
  166.         AbstractSalesChannelContextFactory $salesChannelContextFactory,
  167.         private readonly PercentagePriceCalculator $percentageCalculator,
  168.         private readonly AbsolutePriceCalculator $absolutePriceCalculator,
  169.     ) {
  170.         $this->foundationService $foundationService;
  171.         $this->requestHandler $requestHandler;
  172.         $this->errorHandler $errorHandler;
  173.         $this->productRepository $repositoryInterface;
  174.         $this->persister $persister;
  175.         $this->orderRepository $orderRepository;
  176.         $this->salesChannelContextFactory $salesChannelContextFactory;
  177.     }
  178.     public function mailBeforeSent(MailBeforeValidateEvent $event)
  179.     {
  180.         $this->event $event;
  181.         $discount null;
  182.         $globalDiscountRate null;
  183.         $globalDiscountValue null;
  184.         $globalTotalAmount null;
  185.         $globalTotalNetAmount null;
  186.         $globalShippingAmount null;
  187.         if (array_key_exists('priceInformations'$this->event->getContext()->getExtensions())) {
  188.             $discount $this->event->getContext()->getExtensions()['priceInformations']['discountSum'];
  189.             $globalDiscountValue $this->event->getContext()->getExtensions()['priceInformations']['globalDiscountValue'];
  190.             $globalDiscountRate $this->event->getContext()->getExtensions()['priceInformations']['globalDiscountRate'];
  191.         }
  192.         if (array_key_exists('priceTotalInformations'$this->event->getContext()->getExtensions())) {
  193.             $globalTotalAmount $this->event->getContext()->getExtensions()['priceTotalInformations']['globalTotalAmount'];
  194.             $globalTotalNetAmount $this->event->getContext()->getExtensions()['priceTotalInformations']['globalTotalNetAmount'];
  195.             $globalShippingAmount $this->event->getContext()->getExtensions()['priceTotalInformations']['globalShippingAmount'];
  196.         }
  197.         $this->event->addTemplateData('discount'$discount);
  198.         $this->event->addTemplateData('globalDiscountValue'$globalDiscountValue);
  199.         $this->event->addTemplateData('globalDiscountRate'$globalDiscountRate);
  200.         $this->event->addTemplateData('globalTotalAmount'$globalTotalAmount);
  201.         $this->event->addTemplateData('globalTotalNetAmount'$globalTotalNetAmount);
  202.         $this->event->addTemplateData('globalShippingAmount'$globalShippingAmount);
  203.     }
  204.     /**
  205.      * @param PageLoadedEvent $event
  206.      * @throws \Exception
  207.      */
  208.     public function onProductPageLoaded(ProductPageLoadedEvent $event): void
  209.     {
  210.         $this->event $event;
  211.         /**
  212.          * Prüfung ob Benutzer angemeldet ist, sonst keine Live-Abfrage.
  213.          */
  214.         if (!($this->customerNumber $this->foundationService->checkLogin(
  215.             $this->event->getSalesChannelContext(),
  216.             self::PLUGINNAME
  217.         ))) {
  218.             return;
  219.         }
  220.         /**
  221.          * Configeinstellungen prüfen und setzen.
  222.          */
  223.         if (!$this->checkConfig()) {
  224.             return;
  225.         }
  226.         /**
  227.          * @var array $articles
  228.          */
  229.         $product $this->event->getPage()->getProduct();
  230.         $articles $this->articleData($product);
  231.         $this->result $this->getArticleInfo($articles);
  232.         if (isset($this->result['shipping-costs']) && isset($this->result['shipping-costs']['free-shipping-threshold'])) {
  233.             $freeShippingThreshold = (int)$this->result['shipping-costs']['free-shipping-threshold'];
  234.         } else {
  235.             $freeShippingThreshold $this->calculateShippingThreshold();
  236.         }
  237.         $extension = [
  238.             'freeShippingThreshold' => $freeShippingThreshold,
  239.         ];
  240.         $this->event->getSalesChannelContext()->getShippingMethod()->addArrayExtension(
  241.             'deliveryInformations',
  242.             $extension
  243.         );
  244.         $this->error $this->errorHandler->error(
  245.             $this->errorHandler::UNKNOWN_REQUEST,
  246.             get_class($this),
  247.             'Result: ' print_r($this->resulttrue)
  248.         );
  249.         $this->errorHandler->writeErrorLog($this->error);
  250.     }
  251.     private function articleData($product): array
  252.     {
  253.         $articleData = [];
  254.         $customFields $product->getCustomFields();
  255.         $article['number'] = $product->getProductNumber();
  256.         $article['quantity'] = $product->getCalculatedPrice()->getQuantity();
  257.         $article['division'] = $customFields['custom_salesdata_division'];
  258.         $article['quantity-unit'] = $product->getPackUnit();
  259.         $article["position"] = 0;
  260.         $articleData[] = $article;
  261.         return $articleData;
  262.     }
  263.     public function onCartPageLoaded(PageLoadedEvent $event): void
  264.     {
  265.         $this->event $event;
  266.         /**
  267.          * Prüfung ob Benutzer angemeldet ist, sonst keine Live-Abfrage.
  268.          */
  269.         if (!($this->customerNumber $this->foundationService->checkLogin(
  270.             $this->event->getSalesChannelContext(),
  271.             self::PLUGINNAME
  272.         ))) {
  273.             return;
  274.         }
  275.         /**
  276.          * Configeinstellungen prüfen und setzen.
  277.          */
  278.         if (!$this->checkConfig()) {
  279.             return;
  280.         }
  281.         $this->cart $this->event->getPage()->getCart();
  282.         $this->lineItems $this->cart->getLineItems()->filterType(LineItem::PRODUCT_LINE_ITEM_TYPE);
  283.         /** @var LineItem $promotion */
  284.         $promotion $this->cart->getLineItems()->filterType(LineItem::PROMOTION_LINE_ITEM_TYPE)?->first();
  285.         if ($this->lineItems->count() < 1) {
  286.             return;
  287.         }
  288.         /** @var array $articles */
  289.         $articles $this->lineItemsToArticles();
  290.         $this->addDiscountToRequest($promotion$articles);
  291.         $this->result $this->getArticleInfo($articles);
  292.         $this->error $this->errorHandler->error(
  293.             $this->errorHandler::UNKNOWN_REQUEST,
  294.             get_class($this),
  295.             'Result: ' print_r($this->resulttrue)
  296.         );
  297.         $this->errorHandler->writeErrorLog($this->error);
  298.         if (array_key_exists('head'$this->result) && $this->result['head']['status'] == 'NOK') {
  299.             return;
  300.         }
  301.         $this->taxRuleCollection = new TaxRuleCollection();
  302.         $this->calculatedTaxCollection = new CalculatedTaxCollection();
  303.         $sum $this->lineItemsCost $this->calculateLineItems();
  304.         $this->setDiscount($sum);
  305.         // Set discount value from response after all other lineItems have their price set "$this->calculateLineItems()"
  306.         $this->calculateDiscount($promotion);
  307.         /**
  308.          * @var CalculatedTax $shippingCosts
  309.          */
  310.         $this->cart->setPrice($this->calculateNewCartPrice());
  311.         if (isset($this->result['shipping-costs']) && isset($this->result['shipping-costs']['free-shipping-threshold'])) {
  312.             //            $shippingCosts = $this->result['shipping-costs']['condition-value'];
  313.             $freeShippingThreshold = (int)$this->result['shipping-costs']['free-shipping-threshold'];
  314.         } else {
  315.             $freeShippingThreshold $this->calculateShippingThreshold();
  316.         }
  317.         $extension = [
  318.             'freeShippingThreshold' => $freeShippingThreshold,
  319.         ];
  320.         $this->event->getPage()->getCart()->getDeliveries()->addArrayExtension('deliveryInformations'$extension);
  321.         $this->persister->save($this->cart$this->event->getSalesChannelContext());
  322.     }
  323.     public function onCheckoutOrderPlaced(CheckoutOrderPlacedEvent $event)
  324.     {
  325.         $this->event $event;
  326.         $this->order $this->event->getOrder();
  327.         /**
  328.          * Configeinstellungen prüfen und setzen.
  329.          */
  330.         if (!$this->checkConfig()) {
  331.             return;
  332.         }
  333.         $this->lineItems $this->event->getOrder()->getLineItems()->filterByType(LineItem::PRODUCT_LINE_ITEM_TYPE);
  334.         /** @var LineItem $promotion */
  335.         $promotion $this->event->getOrder()->getLineItems()->filterByType(LineItem::PROMOTION_LINE_ITEM_TYPE)?->first();
  336.         if ($this->lineItems->count() < 1) {
  337.             return;
  338.         }
  339.         /**
  340.          * @var array $articles
  341.          */
  342.         $articles $this->lineItemsToArticles();
  343.         $this->addDiscountToRequest($promotion$articles);
  344.         $this->result $this->getArticleInfo($articles);
  345.         $this->error $this->errorHandler->error(
  346.             $this->errorHandler::UNKNOWN_REQUEST,
  347.             get_class($this),
  348.             'Result: ' print_r($this->resulttrue)
  349.         );
  350.         $this->errorHandler->writeErrorLog($this->error);
  351.         if (array_key_exists('head'$this->result) && $this->result['head']['status'] == 'NOK') {
  352.             return;
  353.         }
  354.         $this->taxRuleCollection = new TaxRuleCollection();
  355.         $this->calculatedTaxCollection = new CalculatedTaxCollection();
  356.         $sum $this->lineItemsCost $this->calculateLineItems();
  357.         $this->setDiscount($sum);
  358.         // Set discount value from response after all other lineItems have their price set "$this->calculateLineItems()"
  359.         $this->calculateDiscount($promotion);
  360.     }
  361.     /**
  362.      * @param CheckoutFinishPageLoadedEvent $event
  363.      * @throws InconsistentCriteriaIdsException
  364.      */
  365.     public function onFinishPageLoaded(CheckoutFinishPageLoadedEvent $event)
  366.     {
  367.         $this->event $event;
  368.         /**
  369.          * Prüfung ob Benutzer angemeldet ist, sonst keine Live-Abfrage.
  370.          */
  371.         if (!($this->customerNumber $this->foundationService->checkLogin(
  372.             $this->event->getSalesChannelContext(),
  373.             self::PLUGINNAME
  374.         ))) // $this->errorHandler->writeErrorLog(['foundationService']);
  375.         {
  376.             return;
  377.         }
  378.         /**
  379.          * Configeinstellungen prüfen und setzen.
  380.          */
  381.         if (!$this->checkConfig()) // $this->errorHandler->writeErrorLog(['checkConfig']);
  382.         {
  383.             return;
  384.         }
  385.         $this->lineItems $this->event->getPage()->getOrder()->getLineItems()->filterByType(LineItem::PRODUCT_LINE_ITEM_TYPE);
  386.         $promotion $this->event->getPage()->getOrder()->getLineItems()->filterByType(LineItem::PROMOTION_LINE_ITEM_TYPE)?->first();
  387.         /**
  388.          * @var array $articles
  389.          */
  390.         $articles $this->lineItemsToArticles();
  391.         $this->addDiscountToRequest($promotion$articles);
  392.         if ($articles === false) {
  393.             return;
  394.         }
  395.         $this->result $this->getArticleInfo($articles);
  396.         if ($this->result['head']['status'] == 'NOK') {
  397.             // $this->errorHandler->writeErrorLog(['status']);
  398.             return;
  399.         }
  400.         $freeShippingThreshold $this->calculateShippingThreshold();
  401.         $shippingCosts 0;
  402.         if (array_key_exists('free-shipping-threshold'$this->result['shipping-costs']))
  403.             $freeShippingThreshold = (int) $this->result['shipping-costs']['free-shipping-threshold'];
  404.         if (array_key_exists('pickup-only'$this->result['shipping-costs'])) {
  405.             $pickupOnly = (bool)$this->result['shipping-costs']['pickup-only'];
  406.         } else {
  407.             $pickupOnly false;
  408.         }
  409.         $this->taxRuleCollection = new TaxRuleCollection();
  410.         $this->calculatedTaxCollection = new CalculatedTaxCollection();
  411.         $sum $this->lineItemsCost $this->calculateLineItems();
  412.         $this->setDiscount($sum);
  413.         // Set discount value from response after all other lineItems have their price set "$this->calculateLineItems()"
  414.         $this->calculateDiscount($promotion);
  415.         /**
  416.          * @var OrderEntity $order
  417.          */
  418.         $order $this->event->getPage()->getOrder();
  419.         $order->setPrice($this->calculateNewCartPrice());
  420.         $netPrice $order->getPrice()->getPositionPrice();
  421.         if (array_key_exists('condition-value'$this->result['shipping-costs']) && ($netPrice $freeShippingThreshold)) {
  422.             $shippingCosts = (float) $this->result['shipping-costs']['condition-value'];
  423.         }
  424.         $this->saveOrder(
  425.             $order->getId(),
  426.             $order->getPrice(),
  427.             $pickupOnly,
  428.             $freeShippingThreshold,
  429.             $shippingCosts,
  430.             $this->result['shipping-costs']
  431.         );
  432.     }
  433.     /**
  434.      * @param string $orderId
  435.      * @param CartPrice $price
  436.      * @return void
  437.      */
  438.     private function saveOrder(string $orderIdCartPrice $price$pickupOnly$freeShippingThreshold$shippingCosts$tempConditionTree)
  439.     {
  440.         $tax = (float) $tempConditionTree['condition-value'];
  441.         $taxRate = (float) $tempConditionTree['condition-rate'];
  442.         $calTaxCollection = new CalculatedTaxCollection();
  443.         $taxRuleCollection = new TaxRuleCollection();
  444.         $calTaxCollection->add(new CalculatedTax($tax$taxRate$price->getTotalPrice()));
  445.         $taxRuleCollection->add(new TaxRule($taxRate));
  446.         foreach ($this->lineItems as $lineItem) {
  447.             $lineItems[] = [
  448.                 "id" => $lineItem->getId(),
  449.                 "identifier" => $lineItem->getIdentifier(),
  450.                 "totalPrice" => $lineItem->getPrice()->getTotalPrice(),
  451.                 "unitPrice" => $lineItem->getPrice()->getUnitPrice(),
  452.                 "label" => $lineItem->getLabel(),
  453.                 "price" => $lineItem->getPrice(),
  454.                 "quantity" => $lineItem->getQuantity(),
  455.             ];
  456.         }
  457.         $shippingCostsArray = [
  458.             'taxRules' => $taxRuleCollection,
  459.             'calculatedTaxes' => $calTaxCollection,
  460.             'quantity' => 1,
  461.             'totalPrice' => $shippingCosts,
  462.             'unitPrice' => $shippingCosts
  463.         ];
  464.         $orderData = [
  465.             'id' => $orderId,
  466.             'price' => $price,
  467.             'shippingCosts' => $shippingCostsArray,
  468.             'lineItems' => $lineItems,
  469.             'deliveries' => [
  470.                 [
  471.                     'id' => $this->delivery->getId(),
  472.                     'shippingCosts' => $shippingCostsArray,
  473.                     'shippingDateLatest' => $this->delivery->getShippingDateLatest(),
  474.                     'shippingDateEarliest' => $this->delivery->getShippingDateEarliest(),
  475.                     'shippingOrderAddressId' => $this->delivery->getShippingOrderAddressId(),
  476.                     'shippingMethodId' => $this->delivery->getShippingMethodId(),
  477.                     'trackingCodes' => $this->delivery->getTrackingCodes()
  478.                 ]
  479.             ],
  480.             'customFields' => [
  481.                 'custom_shippingCosts_pickupOnly' => (bool)$pickupOnly,
  482.                 'custom_shippingCosts_freeShippingThreshold' => (int)$freeShippingThreshold
  483.             ]
  484.         ];
  485.         $this->errorHandler->writeErrorLog($orderData);
  486.         $this->orderRepository->update([$orderData], $this->event->getContext());
  487.     }
  488.     /**
  489.      * @param array $articles
  490.      * @param int $shopInstance
  491.      * @param string $salesOrganization
  492.      * @param string $distributionChannel
  493.      * @param string $division
  494.      * @param string $currency
  495.      * @param string $language
  496.      * @return array
  497.      */
  498.     public function getArticleInfo(
  499.         array  $articles,
  500.         int    $shopInstance 1,
  501.         string $salesOrganization 'DE01',
  502.         string $distributionChannel '01',
  503.         string $division '00',
  504.         string $language 'DE'
  505.     ): array {
  506.         if (!$this->customerNumber && $this->order) {
  507.             $this->customerNumber $this->order->getOrderCustomer()->getCustomer()->getCustomFields()['custom_sap_number'];
  508.         }
  509.         $params = [
  510.             'shop-instance' => $shopInstance,
  511.             'language'      => $language,
  512.             'customer'      => $this->customerNumber,
  513.             'customer-we'   => $this->customerNumber,
  514.             'order-type'    => 'ZDSA',
  515.             'currency'      => $this->getCurrencyISO(),
  516.             'delivery-date' => date('Y-m-d'),
  517.         ];
  518.         $buildRequestHelper = new BuildRequestHelper($params$articles$this->errorHandler);
  519.         /**
  520.          * @var string $request
  521.          */
  522.         $request $this->requestHandler->buildRequest($buildRequestHelperself::PLUGINNAME);
  523.         if ($request !== '') {
  524.             /**
  525.              * @var string $result
  526.              */
  527.             $result $this->requestHandler->sendRequest($this->host$this->portself::PATH$request);
  528.         } else {
  529.             $this->error $this->errorHandler->error(
  530.                 $this->errorHandler::UNKNOWN_REQUEST,
  531.                 get_class($this),
  532.                 'Fehler im Aufbau des Request'
  533.             );
  534.             $this->errorHandler->writeErrorLog($this->error);
  535.             return [];
  536.         }
  537.         /**
  538.          * @var array $resultArray
  539.          */
  540.         return $this->requestHandler->parseResult($result);
  541.     }
  542.     /**
  543.      * @return bool
  544.      */
  545.     private function checkConfig(): bool
  546.     {
  547.         if ($this->foundationService->getConfigStatus()) {
  548.             $this->host $this->foundationService->getHost();
  549.             $this->port $this->foundationService->getPort();
  550.             return true;
  551.         }
  552.         $this->error $this->errorHandler->error(
  553.             $this->errorHandler::CONFIG_NOT_VALID,
  554.             get_class($this),
  555.             'Konnte die Konfiguration nicht ermitteln'
  556.         );
  557.         $this->errorHandler->writeErrorLog($this->error);
  558.         return false;
  559.     }
  560.     /**
  561.      * @return array
  562.      */
  563.     private function lineItemsToArticles(): array
  564.     {
  565.         /**
  566.          * @var array $articles
  567.          */
  568.         $articles = [];
  569.         /**
  570.          * @todo Die position-id noch richtig machen
  571.          */
  572.         $count 0;
  573.         /** @var LineItem $lineItem */
  574.         foreach ($this->lineItems as $lineItem) {
  575.             if ($lineItem->getType() === LineItem::PROMOTION_LINE_ITEM_TYPE) {
  576.                 continue;
  577.             }
  578.             $count++;
  579.             $product $this->getProduct($lineItem->getReferencedId());
  580.             $customFields $product->getCustomFields();
  581.             $article['position'] = $count;
  582.             $article['number'] = $product->getProductNumber();
  583.             $article['quantity'] = $lineItem->getPrice()->getQuantity();
  584.             $article['division'] = $customFields['custom_salesdata_division'];
  585.             $article['quantity-unit'] = $product->getPackUnit();
  586.             $articles[] = $article;
  587.         }
  588.         return $articles;
  589.     }
  590.     /**
  591.      * @param string $productID
  592.      * @return ProductEntity
  593.      */
  594.     public function getProduct(string $productID, array $associations null): ProductEntity
  595.     {
  596.         /**
  597.          * @var Criteria $criteria
  598.          */
  599.         $criteria = new Criteria([$productID]);
  600.         if ($associations !== null) {
  601.             foreach ($associations as $association) {
  602.                 $criteria->addAssociation($association);
  603.             }
  604.         }
  605.         /**
  606.          * @var EntityCollection $products
  607.          */
  608.         $products $this->productRepository->search(
  609.             $criteria,
  610.             \Shopware\Core\Framework\Context::createDefaultContext()
  611.         );
  612.         /**
  613.          * @var array $productList
  614.          */
  615.         $productList $products->getElements();
  616.         /**
  617.          * @var ProductEntity $product
  618.          */
  619.         $product $productList[$productID];
  620.         return $product;
  621.     }
  622.     function calculateLineItems(): float
  623.     {
  624.         // $this->result = Ergebnis des Requests
  625.         $count 0;
  626.         $sum 0.0;
  627.         /** @var LineItem $lineItem */
  628.         foreach ($this->lineItems as $lineItem) {
  629.             if ($lineItem->getType() === LineItem::PROMOTION_LINE_ITEM_TYPE) {
  630.                 continue;
  631.             }
  632.             if (array_key_exists(0$this->result['articles']['article'])) {
  633.                 $articleArray $this->result['articles']['article'][$count];
  634.             } else {
  635.                 $articleArray $this->result['articles']['article'];
  636.             }
  637.             $tempConditionTree null;
  638.             if (array_key_exists(0$articleArray['conditions']['condition'])) {
  639.                 if ($articleArray['conditions']['condition'][0]['condition-type'] === 'MWST') {
  640.                     $tempConditionTree $articleArray['conditions']['condition'][0];
  641.                 } else {
  642.                     $tempConditionTree $articleArray['conditions']['condition'][1];
  643.                 }
  644.             } else {
  645.                 $tempConditionTree $articleArray['conditions']['condition'];
  646.             }
  647.             $tax $price = (float)$tempConditionTree['condition-value'];
  648.             $taxRate = (float)$tempConditionTree['condition-rate'];
  649.             $calTaxCollection = new CalculatedTaxCollection();
  650.             $taxRuleCollection = new TaxRuleCollection();
  651.             $calTaxCollection->add(new CalculatedTax($tax$taxRate$price));
  652.             $taxRuleCollection->add(new TaxRule($taxRate));
  653.             if (!array_key_exists((string)$taxRate$this->taxValues)) {
  654.                 $this->taxValues[(string)$taxRate] = 0.0;
  655.             }
  656.             $this->taxValues[(string)$taxRate] += $price;
  657.             $this->taxRuleCollection->add(new TaxRule($taxRate));
  658.             $newCalculatedPrice = new CalculatedPrice(
  659.                 (float)$articleArray['net-position-value'],
  660.                 (float)$articleArray['net-position-sum'],
  661.                 $calTaxCollection,
  662.                 $taxRuleCollection,
  663.                 (int)$articleArray['quantity']
  664.             );
  665.             $sum += (float)$articleArray['net-position-sum'];
  666.             $lineItem->setPrice($newCalculatedPrice);
  667.             $count++;
  668.         }
  669.         return $sum;
  670.     }
  671.     function calculateNewTotals()
  672.     {
  673.         /**
  674.          * @var CalculatedPrice
  675.          */
  676.         $pickup false;
  677.         $addPrice 0;
  678.         if ($this->result['shipping-costs']) {
  679.             $addPrice = isset($this->result['shipping-costs']['condition-value']) ? (float)$this->result['shipping-costs']['condition-value'] : 0.0;
  680.             if (isset($this->result['shipping-costs']['free-shipping-threshold'])) {
  681.                 $freeShippingThreshold = (int)$this->result['shipping-costs']['free-shipping-threshold'];
  682.             } else {
  683.                 $freeShippingThreshold $this->calculateShippingThreshold();
  684.             }
  685.             if ($this->lineItemsCost >= $freeShippingThreshold || $pickup) {
  686.                 $addPrice 0.0;
  687.             }
  688.         }
  689.         /**
  690.          * @var CalculatedPrice
  691.          */
  692.         $newShippingPrice $this->getNewShippingPrice($addPrice);
  693.         $taxSum 0.0;
  694.         foreach ($this->taxValues as $key => $value) {
  695.             $this->calculatedTaxCollection->add(new CalculatedTax($value, (float) $key$value));
  696.             $taxSum += $value;
  697.         }
  698.         $globalTotalAmount $this->lineItemsCost $newShippingPrice->getTotalPrice() + $taxSum;
  699.         $globalTotalNetAmount $this->lineItemsCost $newShippingPrice->getTotalPrice();
  700.         $extension = array();
  701.         $extension['globalTotalAmount'] = (float)$globalTotalAmount;
  702.         $extension['globalTotalNetAmount'] = (float)$globalTotalNetAmount;
  703.         $extension['globalShippingAmount'] = (float)$addPrice;
  704.         $this->event->getContext()->addArrayExtension('priceTotalInformations'$extension);
  705.     }
  706.     function calculateNewCartPrice()
  707.     {
  708.         if ($this->event instanceof CheckoutFinishPageLoadedEvent) {
  709.             $this->baseObj $this->event->getPage()->getOrder();
  710.         } else {
  711.             $this->baseObj $this->event->getPage()->getCart();
  712.         }
  713.         /**
  714.          * @var CartPrice
  715.          */
  716.         $cartPrice $this->baseObj->getPrice();
  717.         /**
  718.          * @var DeliveryCollection
  719.          */
  720.         $deliveryCosts $this->baseObj->getDeliveries();
  721.         /**
  722.          * @var Delivery
  723.          */
  724.         $delivery $deliveryCosts->first();
  725.         /**
  726.          * @var CalculatedPrice
  727.          */
  728.         $customfields $this->event->getSalesChannelContext()->getCustomer()->getCustomFields();
  729.         $pickup key_exists('custom_sap_pickup'$customfields) ? $customfields['custom_sap_pickup'] : false;
  730.         if (isset($this->result['shipping-costs'])) {
  731.             $addPrice = isset($this->result['shipping-costs']['condition-value']) ? (float)$this->result['shipping-costs']['condition-value'] : 0.0;
  732.             if (isset($this->result['shipping-costs']['free-shipping-threshold'])) {
  733.                 $freeShippingThreshold = (int)$this->result['shipping-costs']['free-shipping-threshold'];
  734.             } else {
  735.                 $freeShippingThreshold $this->calculateShippingThreshold();
  736.             }
  737.             if ($this->lineItemsCost >= $freeShippingThreshold || $pickup) {
  738.                 $addPrice 0.0;
  739.             }
  740.         }
  741.         /**
  742.          * @var CalculatedPrice
  743.          */
  744.         $newShippingPrice $this->getNewShippingPrice($addPrice);
  745.         $delivery->setShippingCosts($newShippingPrice);
  746.         $this->delivery $delivery;
  747.         $taxSum 0.0;
  748.         foreach ($this->taxValues as $key => $value) {
  749.             $this->calculatedTaxCollection->add(new CalculatedTax($value, (float)$key$value));
  750.             $taxSum += $value;
  751.         }
  752.         $globalTotalAmount $this->lineItemsCost $newShippingPrice->getTotalPrice() + $taxSum;
  753.         $globalTotalNetAmount $this->lineItemsCost $newShippingPrice->getTotalPrice();
  754.         $newCartPrice = new CartPrice(
  755.             $globalTotalNetAmount,
  756.             $globalTotalAmount,
  757.             $this->lineItemsCost,
  758.             $this->calculatedTaxCollection,
  759.             $this->taxRuleCollection,
  760.             $cartPrice->getTaxStatus()
  761.         );
  762.         return $newCartPrice;
  763.     }
  764.     private function getNewShippingPrice(float $addPrice): CalculatedPrice
  765.     {
  766.         $unitPrice $totalPrice $addPrice;
  767.         return new CalculatedPrice($unitPrice$totalPrice, new CalculatedTaxCollection(), new TaxRuleCollection());
  768.     }
  769.     private function setDiscount($sum)
  770.     {
  771.         /**
  772.          * @var int $count
  773.          */
  774.         $count 0;
  775.         $discountSum 0;
  776.         $globalDiscountValueSum 0;
  777.         $globalDiscountRate 0;
  778.         $discountRate 0;
  779.         foreach ($this->lineItems as $lineItem) {
  780.             if (count($this->lineItems) > && array_key_exists($count$this->result['articles']['article'])) {
  781.                 $articleArray $this->result['articles']['article'][$count];
  782.             } else {
  783.                 $articleArray $this->result['articles']['article'];
  784.             }
  785.             if (array_key_exists('condition-type'$condition $articleArray['conditions']['condition'])) {
  786.                 if ($condition['condition-type'] == "ZRN1") {
  787.                     $discountValue $condition['condition-value'];
  788.                     $discountRate $condition['condition-rate'];
  789.                     $extension = [
  790.                         'discountValue' => (float) $discountValue,
  791.                         'discountRate' => round((float) $discountRate2)
  792.                     ];
  793.                     $lineItem->addArrayExtension('lineItemDiscount'$extension);
  794.                     $discountSum += $discountValue;
  795.                     $this->addCustomField($lineItem"discountLabel""Shop Gutschein ZRN1 wurde als Sondernachlaß berücksichtigt");
  796.                 } elseif ($condition['condition-type'] == "ZECO") {
  797.                     $globalDiscountValue $condition['condition-value'];
  798.                     $globalDiscountValueSum += $globalDiscountValue;
  799.                     $globalDiscountRate $condition['condition-rate'];
  800.                     $extension = [
  801.                         'globalDiscountValue' => (float) $globalDiscountValue,
  802.                         'globalDiscountRate' => round((float) $globalDiscountRate2)
  803.                     ];
  804.                     $lineItem->addArrayExtension('lineItemGlobalDiscount'$extension);
  805.                     $this->addCustomField($lineItem"discountLabel""Shop Gutschein ZECO wurde als Sondernachlaß berücksichtigt");
  806.                 }
  807.             } else {
  808.                 foreach ($articleArray['conditions']['condition'] as $condition) {
  809.                     if ($condition['condition-type'] == "ZRN1") {
  810.                         $discountValue $condition['condition-value'];
  811.                         $discountRate $condition['condition-rate'];
  812.                         $extension = [
  813.                             'discountValue' => (float) $discountValue,
  814.                             'discountRate' => round((float) $discountRate2)
  815.                         ];
  816.                         $lineItem->addArrayExtension('lineItemDiscount'$extension);
  817.                         $discountSum += $discountValue;
  818.                         $this->addCustomField($lineItem"discountLabel""Shop Gutschein ZECO wurde als Sondernachlaß berücksichtigt");
  819.                     }
  820.                     if ($condition['condition-type'] == "ZECO") {
  821.                         $globalDiscountValue $condition['condition-value'];
  822.                         $globalDiscountValueSum += $globalDiscountValue;
  823.                         $globalDiscountRate $condition['condition-rate'];
  824.                         $extension = [
  825.                             'globalDiscountValue' => (float) $globalDiscountValue,
  826.                             'globalDiscountRate' => round((float) $globalDiscountRate2)
  827.                         ];
  828.                         $lineItem->addArrayExtension('lineItemGlobalDiscount'$extension);
  829.                         $this->addCustomField($lineItem"discountLabel""Shop Gutschein ZECO wurde als Sondernachlaß berücksichtigt");
  830.                     }
  831.                 }
  832.             }
  833.             $count++;
  834.         }
  835.         $extension = [
  836.             'discountRate' =>  round((float) $discountRate2),
  837.             'discountSum'  => $discountSum,
  838.             'globalDiscountValue' => (float) $globalDiscountValueSum,
  839.             'globalDiscountRate' => round((float) $globalDiscountRate2),
  840.         ];
  841.         $this->event->getContext()->addArrayExtension('priceInformations'$extension);
  842.     }
  843.     /**
  844.      * fts - Retrieve currency iso code from saleschannel context
  845.      * @return string
  846.      */
  847.     private function getCurrencyISO(): string
  848.     {
  849.         return $this->getSalesChannelContext()?->getCurrency()->getIsoCode() ?? "EUR";
  850.     }
  851.     /**
  852.      * If the current currency is not EUR, then the default threshold (250€)
  853.      * will be converted to the appropriate currency using the currency factor.
  854.      * @return int
  855.      */
  856.     private function calculateShippingThreshold(): int
  857.     {
  858.         if ($this->getSalesChannelContext()->getCurrency()->getIsoCode() === "PLN") {
  859.             return self::ZLOTY_THRESHOLD;
  860.         } else {
  861.             return self::EUR_THRESHOLD;
  862.         }
  863.     }
  864.     private function getSalesChannelContext(): SalesChannelContext
  865.     {
  866.         if ($this->event instanceof CheckoutOrderPlacedEvent) {
  867.             return $this->salesChannelContextFactory->create(""$this->event->getSalesChannelId());
  868.         } else {
  869.             return $this->event->getSalesChannelContext();
  870.         }
  871.     }
  872.     /**
  873.      * @426 - Set discount value from response after all other lineItems have their price set "$this->calculateLineItems()"
  874.      * **lineItemsCost += discount value**
  875.      * @param OrderLineItemEntity|LineItem|null $promotion
  876.      * @return void
  877.      */
  878.     private function calculateDiscount(OrderLineItemEntity|LineItem|null $promotion): void
  879.     {
  880.         if ($promotion && isset($this->result["discounts"])) {
  881.             if ($this->event instanceof CheckoutOrderPlacedEvent) {
  882.                 $context $this->salesChannelContextFactory->create(""$this->event->getSalesChannelId());
  883.             } else {
  884.                 $context $this->event->getSalesChannelContext();
  885.             }
  886.             foreach ($this->result["discounts"] as $discount) {
  887.                 if (!isset($discount["code"]) || !isset($discount["value"])) {
  888.                     continue;
  889.                 }
  890.                 // Promotion with percentage, calculate
  891.                 if ($discount["code"] === self::ZRN0) {
  892.                     $value = -abs((float)$discount["value"]);
  893.                     $promotion->setPriceDefinition(new PercentagePriceDefinition((float)$value));
  894.                     $calculated_price $this->percentageCalculator->calculate(
  895.                         (float)$value,
  896.                         $this->lineItems->getPrices(),
  897.                         $context
  898.                     );
  899.                 } elseif ($discount["code"] === self::ZRN2) {
  900.                     $value = -abs((float)$discount["value"]);
  901.                     $promotion->setPriceDefinition(new AbsolutePriceDefinition((float)$value));
  902.                     // Promotion with fixed value, calculate
  903.                     $calculated_price $this->absolutePriceCalculator->calculate(
  904.                         (float)$value,
  905.                         $this->lineItems->getPrices(),
  906.                         $context
  907.                     );
  908.                 }
  909.                 if ($calculated_price !== null) {
  910.                     $promotion->setPrice($calculated_price);
  911.                     // Subtract the discount from the current total
  912.                     $this->lineItemsCost += $promotion->getPrice()->getTotalPrice();
  913.                 }
  914.             }
  915.         }
  916.     }
  917.     /**
  918.      * @426 - Adds the promotion with it's corresponding code (ZRN0 | ZRN2) to the request array.
  919.      * @param LineItem|OrderLineItemEntity|null $promotion
  920.      * @param array $articles
  921.      * @return void
  922.      */
  923.     private function addDiscountToRequest(OrderLineItemEntity|LineItem|null $promotion, array &$articles): void
  924.     {
  925.         if ($promotion) {
  926.             $promotionType $promotion?->getPayload()["discountType"];
  927.             $code $promotionType === "percentage" self::ZRN0 self::ZRN2;
  928.             $articles["discounts"][] = ["code" => $code"value" => $promotion?->getPayload()["value"]];
  929.         }
  930.     }
  931.     private function addCustomField(LineItem|OrderLineItemEntity &$lineItemstring $keymixed $value): void
  932.     {
  933.         if($lineItem instanceof OrderLineItemEntity) {
  934.             $payload $lineItem->getPayload();
  935.             $payload["customFields"][$key] = $value;
  936.         } else {
  937.             $customFields $lineItem->getPayloadValue("customFields");
  938.             $customFields[$key] = $value;
  939.             $lineItem->setPayloadValue("customFields"$customFields);
  940.         }
  941.     }
  942. }