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

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