<?php
declare(strict_types=1);
namespace Proc\ProcOrderSimulate\Subscriber;
use Proc\ProcFoundation\Helper\RequestHandler;
use Proc\ProcFoundation\Helper\ErrorHandler;
use Proc\ProcFoundation\Service\ProcFoundationService;
use Proc\ProcOrderSimulate\Helper\BuildRequestHelper;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\CartBehavior;
use Shopware\Core\Checkout\Cart\Event\CheckoutOrderPlacedEvent;
use Shopware\Core\Checkout\Cart\Exception\MissingPriceDefinitionException;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
use Shopware\Core\Checkout\Cart\Price\AbsolutePriceCalculator;
use Shopware\Core\Checkout\Cart\Price\CurrencyPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\PercentagePriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\AbsolutePriceDefinition;
use Shopware\Core\Checkout\Cart\Price\Struct\CartPrice;
use Shopware\Core\Checkout\Cart\Price\Struct\CurrencyPriceDefinition;
use Shopware\Core\Checkout\Cart\Price\Struct\PercentagePriceDefinition;
use Shopware\Core\Checkout\Cart\Price\Struct\ListPrice;
use Shopware\Core\Checkout\Cart\Tax\Struct\CalculatedTax;
use Shopware\Core\Checkout\Cart\Tax\Struct\CalculatedTaxCollection;
use Shopware\Core\Checkout\Cart\Price\Struct\CalculatedPrice;
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRuleCollection;
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRule;
use Shopware\Core\Checkout\Order\OrderEntity;
use Shopware\Core\Content\MailTemplate\Service\Event\MailBeforeValidateEvent;
use Shopware\Core\Content\Product\Cart\ProductCartProcessor;
use Shopware\Core\Content\Product\DataAbstractionLayer\CheapestPrice\CalculatedCheapestPrice;
use Shopware\Core\Content\Product\DataAbstractionLayer\CheapestPrice\CheapestPriceContainer;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Exception\InconsistentCriteriaIdsException;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\System\SalesChannel\Context\AbstractSalesChannelContextFactory;
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextFactory;
use Shopware\Core\System\SalesChannel\Context\SalesChannelContextService;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Shopware\Storefront\Page\Checkout\Cart\CheckoutCartPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Confirm\CheckoutConfirmPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Finish\CheckoutFinishPageLoadedEvent;
use Shopware\Storefront\Page\Checkout\Offcanvas\OffcanvasCartPageLoadedEvent;
use Shopware\Storefront\Page\PageLoadedEvent;
use Shopware\Core\Checkout\Cart\Delivery\Struct\Delivery;
use Shopware\Core\Checkout\Cart\Delivery\Struct\DeliveryCollection;
use Shopware\Core\Framework\DataAbstractionLayer\EntityCollection;
use Shopware\Core\Checkout\Cart\AbstractCartPersister;
use Shopware\Storefront\Page\Product\ProductPageLoadedEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
/**
* Class OrderSimulateSubscriber
*
* @package Proc\ProcOrderSimulate\Subscriber
*/
class OrderSimulateSubscriber implements EventSubscriberInterface
{
private const PLUGINNAME = 'ProcOderSimulate';
private const PATH = '/iman/order-simulate';
public const EUR_THRESHOLD = 250;
public const ZLOTY_THRESHOLD = 1062;
/**
* @var RequestHandler
*/
private $requestHandler;
/**
* @var ErrorHandler
*/
private $errorHandler;
/**
* @var string
*/
private $host,
$port,
$customerNumber;
private $error = null;
/**
* @var ProcFoundationService
*/
private $foundationService;
/**
* @var EntityRepositoryInterface
*/
private $productRepository;
/**
* @var CheckoutCartPageLoadedEvent | CheckoutConfirmPageLoadedEvent | CheckoutFinishPageLoadedEvent | ProductPageLoadedEvent | CheckoutOrderPlacedEvent | MailBeforeValidateEvent
*/
private $event;
/**
* @var array
*/
private $result;
/**
* @var CalculatedTaxCollection
*/
private $calculatedTaxCollection;
/**
* @var TaxRuleCollection
*/
private $taxRuleCollection;
/**
* @var LineItemCollection
*/
private $lineItems;
/**
* @var Cart
*/
private $cart;
/**
* @var float
*/
private $lineItemsCost;
private $baseObj;
/**
* @var array
*/
private $taxValues = [];
/**
* @var AbstractCartPersister
*/
private $persister;
/**
* @var EntityRepositoryInterface
*/
private $orderRepository;
/**
* @var DeliveryCollection
*/
private $delivery;
/** Used for promotions with a fixed values */
protected const ZRN2 = "ZRN2";
/** Used for promotions with percentage */
protected const ZRN0 = "ZRN0";
/**
* @return array
*/
static function getSubscribedEvents(): array
{
return [
// ProductPageLoadedEvent::class => ['onProductPageLoaded', 1],
// CheckoutCartPageLoadedEvent::class => ['onCartPageLoaded', 1],
// CheckoutConfirmPageLoadedEvent::class => ['onCartPageLoaded', 1],
// OffcanvasCartPageLoadedEvent::class => ['onCartPageLoaded', 1],
// CheckoutFinishPageLoadedEvent::class => ['onFinishPageLoaded', 1],
CheckoutOrderPlacedEvent::class => ['onCheckoutOrderPlaced', 1],
MailBeforeValidateEvent::class => ['mailBeforeSent', 1]
];
}
/**
* OrderSimulateSubscriber constructor.
*
* @param ProcFoundationService $foundationService
* @param RequestHandler $requestHandler
* @param ErrorHandler $errorHandler
* @param EntityRepositoryInterface $repositoryInterface
* @param AbstractCartPersister $persister
* @param SalesChannelContextFactory $salesChannelContextFactory
*/
public function __construct(
ProcFoundationService $foundationService,
RequestHandler $requestHandler,
ErrorHandler $errorHandler,
EntityRepositoryInterface $repositoryInterface,
AbstractCartPersister $persister,
EntityRepositoryInterface $orderRepository,
AbstractSalesChannelContextFactory $salesChannelContextFactory,
private readonly PercentagePriceCalculator $percentageCalculator,
private readonly AbsolutePriceCalculator $absolutePriceCalculator,
) {
$this->foundationService = $foundationService;
$this->requestHandler = $requestHandler;
$this->errorHandler = $errorHandler;
$this->productRepository = $repositoryInterface;
$this->persister = $persister;
$this->orderRepository = $orderRepository;
$this->salesChannelContextFactory = $salesChannelContextFactory;
}
public function mailBeforeSent(MailBeforeValidateEvent $event)
{
$this->event = $event;
$discount = null;
$globalDiscountRate = null;
$globalDiscountValue = null;
$globalTotalAmount = null;
$globalTotalNetAmount = null;
$globalShippingAmount = null;
if (array_key_exists('priceInformations', $this->event->getContext()->getExtensions())) {
$discount = $this->event->getContext()->getExtensions()['priceInformations']['discountSum'];
$globalDiscountValue = $this->event->getContext()->getExtensions()['priceInformations']['globalDiscountValue'];
$globalDiscountRate = $this->event->getContext()->getExtensions()['priceInformations']['globalDiscountRate'];
}
if (array_key_exists('priceTotalInformations', $this->event->getContext()->getExtensions())) {
$globalTotalAmount = $this->event->getContext()->getExtensions()['priceTotalInformations']['globalTotalAmount'];
$globalTotalNetAmount = $this->event->getContext()->getExtensions()['priceTotalInformations']['globalTotalNetAmount'];
$globalShippingAmount = $this->event->getContext()->getExtensions()['priceTotalInformations']['globalShippingAmount'];
}
$this->event->addTemplateData('discount', $discount);
$this->event->addTemplateData('globalDiscountValue', $globalDiscountValue);
$this->event->addTemplateData('globalDiscountRate', $globalDiscountRate);
$this->event->addTemplateData('globalTotalAmount', $globalTotalAmount);
$this->event->addTemplateData('globalTotalNetAmount', $globalTotalNetAmount);
$this->event->addTemplateData('globalShippingAmount', $globalShippingAmount);
}
/**
* @param PageLoadedEvent $event
* @throws \Exception
*/
public function onProductPageLoaded(ProductPageLoadedEvent $event): void
{
$this->event = $event;
/**
* Prüfung ob Benutzer angemeldet ist, sonst keine Live-Abfrage.
*/
if (!($this->customerNumber = $this->foundationService->checkLogin(
$this->event->getSalesChannelContext(),
self::PLUGINNAME
))) {
return;
}
/**
* Configeinstellungen prüfen und setzen.
*/
if (!$this->checkConfig()) {
return;
}
/**
* @var array $articles
*/
$product = $this->event->getPage()->getProduct();
$articles = $this->articleData($product);
$this->result = $this->getArticleInfo($articles);
if (isset($this->result['shipping-costs']) && isset($this->result['shipping-costs']['free-shipping-threshold'])) {
$freeShippingThreshold = (int)$this->result['shipping-costs']['free-shipping-threshold'];
} else {
$freeShippingThreshold = $this->calculateShippingThreshold();
}
$extension = [
'freeShippingThreshold' => $freeShippingThreshold,
];
$this->event->getSalesChannelContext()->getShippingMethod()->addArrayExtension(
'deliveryInformations',
$extension
);
$this->error = $this->errorHandler->error(
$this->errorHandler::UNKNOWN_REQUEST,
get_class($this),
'Result: ' . print_r($this->result, true)
);
$this->errorHandler->writeErrorLog($this->error);
}
private function articleData($product): array
{
$articleData = [];
$customFields = $product->getCustomFields();
$article['number'] = $product->getProductNumber();
$article['quantity'] = $product->getCalculatedPrice()->getQuantity();
$article['division'] = $customFields['custom_salesdata_division'];
$article['quantity-unit'] = $product->getPackUnit();
$article["position"] = 0;
$articleData[] = $article;
return $articleData;
}
public function onCartPageLoaded(PageLoadedEvent $event): void
{
$this->event = $event;
/**
* Prüfung ob Benutzer angemeldet ist, sonst keine Live-Abfrage.
*/
if (!($this->customerNumber = $this->foundationService->checkLogin(
$this->event->getSalesChannelContext(),
self::PLUGINNAME
))) {
return;
}
/**
* Configeinstellungen prüfen und setzen.
*/
if (!$this->checkConfig()) {
return;
}
$this->cart = $this->event->getPage()->getCart();
//dd($this->cart);
$this->lineItems = $this->cart->getLineItems()->filterType(LineItem::PRODUCT_LINE_ITEM_TYPE);
/** @var LineItem $promotion */
$promotion = $this->cart->getLineItems()->filterType(LineItem::PROMOTION_LINE_ITEM_TYPE)?->first();
if ($this->lineItems->count() < 1) {
return;
}
/** @var array $articles */
$articles = $this->lineItemsToArticles();
$this->addDiscountToRequest($promotion, $articles);
$this->result = $this->getArticleInfo($articles);
$this->error = $this->errorHandler->error(
$this->errorHandler::UNKNOWN_REQUEST,
get_class($this),
'Result: ' . print_r($this->result, true)
);
$this->errorHandler->writeErrorLog($this->error);
if (array_key_exists('head', $this->result) && $this->result['head']['status'] == 'NOK') {
return;
}
$this->taxRuleCollection = new TaxRuleCollection();
$this->calculatedTaxCollection = new CalculatedTaxCollection();
$sum = $this->lineItemsCost = $this->calculateLineItems();
$this->setDiscount($sum);
// Set discount value from response after all other lineItems have their price set "$this->calculateLineItems()"
$this->calculateDiscount($promotion);
/**
* @var CalculatedTax $shippingCosts
*/
$this->cart->setPrice($this->calculateNewCartPrice());
if (isset($this->result['shipping-costs']) && isset($this->result['shipping-costs']['free-shipping-threshold'])) {
// $shippingCosts = $this->result['shipping-costs']['condition-value'];
$freeShippingThreshold = (int)$this->result['shipping-costs']['free-shipping-threshold'];
} else {
$freeShippingThreshold = $this->calculateShippingThreshold();
}
$extension = [
'freeShippingThreshold' => $freeShippingThreshold,
];
$this->event->getPage()->getCart()->getDeliveries()->addArrayExtension('deliveryInformations', $extension);
$this->event->getSalesChannelContext()->setPermissions([ProductCartProcessor::SKIP_PRODUCT_RECALCULATION]);
$this->cart->setBehavior(new CartBehavior([ProductCartProcessor::SKIP_PRODUCT_RECALCULATION]));
$this->persister->save($this->cart, $this->event->getSalesChannelContext());
}
public function onCheckoutOrderPlaced(CheckoutOrderPlacedEvent $event)
{
$this->event = $event;
$this->order = $this->event->getOrder();
/**
* Configeinstellungen prüfen und setzen.
*/
if (!$this->checkConfig()) {
return;
}
$this->lineItems = $this->event->getOrder()->getLineItems()->filterByType(LineItem::PRODUCT_LINE_ITEM_TYPE);
/** @var LineItem $promotion */
$promotion = $this->event->getOrder()->getLineItems()->filterByType(LineItem::PROMOTION_LINE_ITEM_TYPE)?->first();
if ($this->lineItems->count() < 1) {
return;
}
/**
* @var array $articles
*/
$articles = $this->lineItemsToArticles();
$this->addDiscountToRequest($promotion, $articles);
$this->result = $this->getArticleInfo($articles);
$this->error = $this->errorHandler->error(
$this->errorHandler::UNKNOWN_REQUEST,
get_class($this),
'Result: ' . print_r($this->result, true)
);
$this->errorHandler->writeErrorLog($this->error);
if (array_key_exists('head', $this->result) && $this->result['head']['status'] == 'NOK') {
return;
}
$this->taxRuleCollection = new TaxRuleCollection();
$this->calculatedTaxCollection = new CalculatedTaxCollection();
$sum = $this->lineItemsCost = $this->calculateLineItems();
$this->setDiscount($sum);
// Set discount value from response after all other lineItems have their price set "$this->calculateLineItems()"
$this->calculateDiscount($promotion);
}
/**
* @param CheckoutFinishPageLoadedEvent $event
* @throws InconsistentCriteriaIdsException
*/
public function onFinishPageLoaded(CheckoutFinishPageLoadedEvent $event)
{
$this->event = $event;
/**
* Prüfung ob Benutzer angemeldet ist, sonst keine Live-Abfrage.
*/
if (!($this->customerNumber = $this->foundationService->checkLogin(
$this->event->getSalesChannelContext(),
self::PLUGINNAME
))) // $this->errorHandler->writeErrorLog(['foundationService']);
{
return;
}
/**
* Configeinstellungen prüfen und setzen.
*/
if (!$this->checkConfig()) // $this->errorHandler->writeErrorLog(['checkConfig']);
{
return;
}
$this->lineItems = $this->event->getPage()->getOrder()->getLineItems()->filterByType(LineItem::PRODUCT_LINE_ITEM_TYPE);
$promotion = $this->event->getPage()->getOrder()->getLineItems()->filterByType(LineItem::PROMOTION_LINE_ITEM_TYPE)?->first();
/**
* @var array $articles
*/
$articles = $this->lineItemsToArticles();
$this->addDiscountToRequest($promotion, $articles);
if ($articles === false) {
return;
}
$this->result = $this->getArticleInfo($articles);
if ($this->result['head']['status'] == 'NOK') {
// $this->errorHandler->writeErrorLog(['status']);
return;
}
$freeShippingThreshold = $this->calculateShippingThreshold();
$shippingCosts = 0;
if (array_key_exists('free-shipping-threshold', $this->result['shipping-costs']))
$freeShippingThreshold = (int) $this->result['shipping-costs']['free-shipping-threshold'];
if (array_key_exists('pickup-only', $this->result['shipping-costs'])) {
$pickupOnly = (bool)$this->result['shipping-costs']['pickup-only'];
} else {
$pickupOnly = false;
}
$this->taxRuleCollection = new TaxRuleCollection();
$this->calculatedTaxCollection = new CalculatedTaxCollection();
$sum = $this->lineItemsCost = $this->calculateLineItems();
$this->setDiscount($sum);
// Set discount value from response after all other lineItems have their price set "$this->calculateLineItems()"
$this->calculateDiscount($promotion);
/**
* @var OrderEntity $order
*/
$order = $this->event->getPage()->getOrder();
$order->setPrice($this->calculateNewCartPrice());
$netPrice = $order->getPrice()->getPositionPrice();
if (array_key_exists('condition-value', $this->result['shipping-costs']) && ($netPrice < $freeShippingThreshold)) {
$shippingCosts = (float) $this->result['shipping-costs']['condition-value'];
}
$this->saveOrder(
$order->getId(),
$order->getPrice(),
$pickupOnly,
$freeShippingThreshold,
$shippingCosts,
$this->result['shipping-costs']
);
}
/**
* @param string $orderId
* @param CartPrice $price
* @return void
*/
private function saveOrder(string $orderId, CartPrice $price, $pickupOnly, $freeShippingThreshold, $shippingCosts, $tempConditionTree)
{
$tax = (float) $tempConditionTree['condition-value'];
$taxRate = (float) $tempConditionTree['condition-rate'];
$calTaxCollection = new CalculatedTaxCollection();
$taxRuleCollection = new TaxRuleCollection();
$calTaxCollection->add(new CalculatedTax($tax, $taxRate, $price->getTotalPrice()));
$taxRuleCollection->add(new TaxRule($taxRate));
foreach ($this->lineItems as $lineItem) {
$lineItems[] = [
"id" => $lineItem->getId(),
"identifier" => $lineItem->getIdentifier(),
"totalPrice" => $lineItem->getPrice()->getTotalPrice(),
"unitPrice" => $lineItem->getPrice()->getUnitPrice(),
"label" => $lineItem->getLabel(),
"price" => $lineItem->getPrice(),
"quantity" => $lineItem->getQuantity(),
];
}
$shippingCostsArray = [
'taxRules' => $taxRuleCollection,
'calculatedTaxes' => $calTaxCollection,
'quantity' => 1,
'totalPrice' => $shippingCosts,
'unitPrice' => $shippingCosts
];
$orderData = [
'id' => $orderId,
'price' => $price,
'shippingCosts' => $shippingCostsArray,
'lineItems' => $lineItems,
'deliveries' => [
[
'id' => $this->delivery->getId(),
'shippingCosts' => $shippingCostsArray,
'shippingDateLatest' => $this->delivery->getShippingDateLatest(),
'shippingDateEarliest' => $this->delivery->getShippingDateEarliest(),
'shippingOrderAddressId' => $this->delivery->getShippingOrderAddressId(),
'shippingMethodId' => $this->delivery->getShippingMethodId(),
'trackingCodes' => $this->delivery->getTrackingCodes()
]
],
'customFields' => [
'custom_shippingCosts_pickupOnly' => (bool)$pickupOnly,
'custom_shippingCosts_freeShippingThreshold' => (int)$freeShippingThreshold
]
];
$this->errorHandler->writeErrorLog($orderData);
$this->orderRepository->update([$orderData], $this->event->getContext());
}
/**
* @param array $articles
* @param int $shopInstance
* @param string $salesOrganization
* @param string $distributionChannel
* @param string $division
* @param string $currency
* @param string $language
* @return array
*/
public function getArticleInfo(
array $articles,
int $shopInstance = 1,
string $salesOrganization = 'DE01',
string $distributionChannel = '01',
string $division = '00',
string $language = 'DE'
): array {
if (!$this->customerNumber && $this->order) {
$this->customerNumber = $this->order->getOrderCustomer()->getCustomer()->getCustomFields()['custom_sap_number'];
}
$params = [
'shop-instance' => $shopInstance,
'language' => $language,
'customer' => $this->customerNumber,
'customer-we' => $this->customerNumber,
'order-type' => 'ZDSA',
'currency' => $this->getCurrencyISO(),
'delivery-date' => date('Y-m-d'),
];
$buildRequestHelper = new BuildRequestHelper($params, $articles, $this->errorHandler);
/**
* @var string $request
*/
$request = $this->requestHandler->buildRequest($buildRequestHelper, self::PLUGINNAME);
if ($request !== '') {
/**
* @var string $result
*/
$result = $this->requestHandler->sendRequest($this->host, $this->port, self::PATH, $request);
} else {
$this->error = $this->errorHandler->error(
$this->errorHandler::UNKNOWN_REQUEST,
get_class($this),
'Fehler im Aufbau des Request'
);
$this->errorHandler->writeErrorLog($this->error);
return [];
}
$this->error = $this->errorHandler->error(
$this->errorHandler::UNKNOWN_REQUEST,
get_class($this),
$request
);
$this->error = $this->errorHandler->error(
$this->errorHandler::UNKNOWN_REQUEST,
get_class($this),
$result
);
/**
* @var array $resultArray
*/
return $this->requestHandler->parseResult($result);
}
/**
* @return bool
*/
private function checkConfig(): bool
{
if ($this->foundationService->getConfigStatus()) {
$this->host = $this->foundationService->getHost();
$this->port = $this->foundationService->getPort();
return true;
}
$this->error = $this->errorHandler->error(
$this->errorHandler::CONFIG_NOT_VALID,
get_class($this),
'Konnte die Konfiguration nicht ermitteln'
);
$this->errorHandler->writeErrorLog($this->error);
return false;
}
/**
* @return array
*/
private function lineItemsToArticles(): array
{
/**
* @var array $articles
*/
$articles = [];
/**
* @todo Die position-id noch richtig machen
*/
$count = 0;
/** @var LineItem $lineItem */
foreach ($this->lineItems as $lineItem) {
if ($lineItem->getType() === LineItem::PROMOTION_LINE_ITEM_TYPE) {
continue;
}
$count++;
$product = $this->getProduct($lineItem->getReferencedId());
$customFields = $product->getCustomFields();
$article['position'] = $count;
$article['number'] = $product->getProductNumber();
$article['quantity'] = $lineItem->getPrice()->getQuantity();
$article['division'] = $customFields['custom_salesdata_division'];
$article['quantity-unit'] = $product->getPackUnit();
$articles[] = $article;
}
return $articles;
}
/**
* @param string $productID
* @return ProductEntity
*/
public function getProduct(string $productID, array $associations = null): ProductEntity
{
/**
* @var Criteria $criteria
*/
$criteria = new Criteria([$productID]);
if ($associations !== null) {
foreach ($associations as $association) {
$criteria->addAssociation($association);
}
}
/**
* @var EntityCollection $products
*/
$products = $this->productRepository->search(
$criteria,
\Shopware\Core\Framework\Context::createDefaultContext()
);
/**
* @var array $productList
*/
$productList = $products->getElements();
/**
* @var ProductEntity $product
*/
$product = $productList[$productID];
return $product;
}
function calculateLineItems(): float
{
// $this->result = Ergebnis des Requests
$count = 0;
$sum = 0.0;
/** @var LineItem $lineItem */
foreach ($this->lineItems as $lineItem) {
if ($lineItem->getType() === LineItem::PROMOTION_LINE_ITEM_TYPE) {
continue;
}
if (array_key_exists(0, $this->result['articles']['article'])) {
$articleArray = $this->result['articles']['article'][$count];
} else {
$articleArray = $this->result['articles']['article'];
}
$tempConditionTree = null;
if (array_key_exists(0, $articleArray['conditions']['condition'])) {
if ($articleArray['conditions']['condition'][0]['condition-type'] === 'MWST') {
$tempConditionTree = $articleArray['conditions']['condition'][0];
} else {
$tempConditionTree = $articleArray['conditions']['condition'][1];
}
} else {
$tempConditionTree = $articleArray['conditions']['condition'];
}
$tax = $price = (float)$tempConditionTree['condition-value'];
$taxRate = (float)$tempConditionTree['condition-rate'];
$calTaxCollection = new CalculatedTaxCollection();
$taxRuleCollection = new TaxRuleCollection();
$calTaxCollection->add(new CalculatedTax($tax, $taxRate, $price));
$taxRuleCollection->add(new TaxRule($taxRate));
if (!array_key_exists((string)$taxRate, $this->taxValues)) {
$this->taxValues[(string)$taxRate] = 0.0;
}
$this->taxValues[(string)$taxRate] += $price;
$this->taxRuleCollection->add(new TaxRule($taxRate));
$newCalculatedPrice = new CalculatedPrice(
(float)$articleArray['net-position-value'],
(float)$articleArray['net-position-sum'],
$calTaxCollection,
$taxRuleCollection,
(int)$articleArray['quantity']
);
$sum += (float)$articleArray['net-position-sum'];
$lineItem->setPrice($newCalculatedPrice);
$count++;
}
return $sum;
}
function calculateNewTotals()
{
/**
* @var CalculatedPrice
*/
$pickup = false;
$addPrice = 0;
if ($this->result['shipping-costs']) {
$addPrice = isset($this->result['shipping-costs']['condition-value']) ? (float)$this->result['shipping-costs']['condition-value'] : 0.0;
if (isset($this->result['shipping-costs']['free-shipping-threshold'])) {
$freeShippingThreshold = (int)$this->result['shipping-costs']['free-shipping-threshold'];
} else {
$freeShippingThreshold = $this->calculateShippingThreshold();
}
if ($this->lineItemsCost >= $freeShippingThreshold || $pickup) {
$addPrice = 0.0;
}
}
/**
* @var CalculatedPrice
*/
$newShippingPrice = $this->getNewShippingPrice($addPrice);
$taxSum = 0.0;
foreach ($this->taxValues as $key => $value) {
$this->calculatedTaxCollection->add(new CalculatedTax($value, (float) $key, $value));
$taxSum += $value;
}
$globalTotalAmount = $this->lineItemsCost + $newShippingPrice->getTotalPrice() + $taxSum;
$globalTotalNetAmount = $this->lineItemsCost + $newShippingPrice->getTotalPrice();
$extension = array();
$extension['globalTotalAmount'] = (float)$globalTotalAmount;
$extension['globalTotalNetAmount'] = (float)$globalTotalNetAmount;
$extension['globalShippingAmount'] = (float)$addPrice;
$this->event->getContext()->addArrayExtension('priceTotalInformations', $extension);
}
function calculateNewCartPrice()
{
if ($this->event instanceof CheckoutFinishPageLoadedEvent) {
$this->baseObj = $this->event->getPage()->getOrder();
} else {
$this->baseObj = $this->event->getPage()->getCart();
}
/**
* @var CartPrice
*/
$cartPrice = $this->baseObj->getPrice();
/**
* @var DeliveryCollection
*/
$deliveryCosts = $this->baseObj->getDeliveries();
/**
* @var Delivery
*/
$delivery = $deliveryCosts->first();
/**
* @var CalculatedPrice
*/
$customfields = $this->event->getSalesChannelContext()->getCustomer()->getCustomFields();
$pickup = key_exists('custom_sap_pickup', $customfields) ? $customfields['custom_sap_pickup'] : false;
if (isset($this->result['shipping-costs'])) {
$addPrice = isset($this->result['shipping-costs']['condition-value']) ? (float)$this->result['shipping-costs']['condition-value'] : 0.0;
if (isset($this->result['shipping-costs']['free-shipping-threshold'])) {
$freeShippingThreshold = (int)$this->result['shipping-costs']['free-shipping-threshold'];
} else {
$freeShippingThreshold = $this->calculateShippingThreshold();
}
if ($this->lineItemsCost >= $freeShippingThreshold || $pickup) {
$addPrice = 0.0;
}
}
/**
* @var CalculatedPrice
*/
$newShippingPrice = $this->getNewShippingPrice($addPrice);
$delivery->setShippingCosts($newShippingPrice);
$this->delivery = $delivery;
$taxSum = 0.0;
foreach ($this->taxValues as $key => $value) {
$this->calculatedTaxCollection->add(new CalculatedTax($value, (float)$key, $value));
$taxSum += $value;
}
$globalTotalAmount = $this->lineItemsCost + $newShippingPrice->getTotalPrice() + $taxSum;
$globalTotalNetAmount = $this->lineItemsCost + $newShippingPrice->getTotalPrice();
$newCartPrice = new CartPrice(
$globalTotalNetAmount,
$globalTotalAmount,
$this->lineItemsCost,
$this->calculatedTaxCollection,
$this->taxRuleCollection,
$cartPrice->getTaxStatus()
);
return $newCartPrice;
}
private function getNewShippingPrice(float $addPrice): CalculatedPrice
{
$unitPrice = $totalPrice = $addPrice;
return new CalculatedPrice($unitPrice, $totalPrice, new CalculatedTaxCollection(), new TaxRuleCollection());
}
private function setDiscount($sum)
{
/**
* @var int $count
*/
$count = 0;
$discountSum = 0;
$globalDiscountValueSum = 0;
$globalDiscountRate = 0;
$discountRate = 0;
foreach ($this->lineItems as $lineItem) {
if (count($this->lineItems) > 1 && array_key_exists($count, $this->result['articles']['article'])) {
$articleArray = $this->result['articles']['article'][$count];
} else {
$articleArray = $this->result['articles']['article'];
}
if (array_key_exists('condition-type', $condition = $articleArray['conditions']['condition'])) {
if ($condition['condition-type'] == "ZRN1") {
$discountValue = $condition['condition-value'];
$discountRate = $condition['condition-rate'];
$extension = [
'discountValue' => (float) $discountValue,
'discountRate' => round((float) $discountRate, 2)
];
$lineItem->addArrayExtension('lineItemDiscount', $extension);
$discountSum += $discountValue;
$this->addCustomField($lineItem, "discountLabel", "Shop Gutschein ZRN1 wurde als Sondernachlaß berücksichtigt");
} elseif ($condition['condition-type'] == "ZECO") {
$globalDiscountValue = $condition['condition-value'];
$globalDiscountValueSum += $globalDiscountValue;
$globalDiscountRate = $condition['condition-rate'];
$extension = [
'globalDiscountValue' => (float) $globalDiscountValue,
'globalDiscountRate' => round((float) $globalDiscountRate, 2)
];
$lineItem->addArrayExtension('lineItemGlobalDiscount', $extension);
$this->addCustomField($lineItem, "discountLabel", "Shop Gutschein ZECO wurde als Sondernachlaß berücksichtigt");
}
} else {
foreach ($articleArray['conditions']['condition'] as $condition) {
if ($condition['condition-type'] == "ZRN1") {
$discountValue = $condition['condition-value'];
$discountRate = $condition['condition-rate'];
$extension = [
'discountValue' => (float) $discountValue,
'discountRate' => round((float) $discountRate, 2)
];
$lineItem->addArrayExtension('lineItemDiscount', $extension);
$discountSum += $discountValue;
$this->addCustomField($lineItem, "discountLabel", "Shop Gutschein ZECO wurde als Sondernachlaß berücksichtigt");
}
if ($condition['condition-type'] == "ZECO") {
$globalDiscountValue = $condition['condition-value'];
$globalDiscountValueSum += $globalDiscountValue;
$globalDiscountRate = $condition['condition-rate'];
$extension = [
'globalDiscountValue' => (float) $globalDiscountValue,
'globalDiscountRate' => round((float) $globalDiscountRate, 2)
];
$lineItem->addArrayExtension('lineItemGlobalDiscount', $extension);
$this->addCustomField($lineItem, "discountLabel", "Shop Gutschein ZECO wurde als Sondernachlaß berücksichtigt");
}
}
}
$count++;
}
$extension = [
'discountRate' => round((float) $discountRate, 2),
'discountSum' => $discountSum,
'globalDiscountValue' => (float) $globalDiscountValueSum,
'globalDiscountRate' => round((float) $globalDiscountRate, 2),
];
$this->event->getContext()->addArrayExtension('priceInformations', $extension);
}
/**
* fts - Retrieve currency iso code from saleschannel context
* @return string
*/
private function getCurrencyISO(): string
{
return $this->getSalesChannelContext()?->getCurrency()->getIsoCode() ?? "EUR";
}
/**
* If the current currency is not EUR, then the default threshold (250€)
* will be converted to the appropriate currency using the currency factor.
* @return int
*/
private function calculateShippingThreshold(): int
{
if ($this->getSalesChannelContext()->getCurrency()->getIsoCode() === "PLN") {
return self::ZLOTY_THRESHOLD;
} else {
return self::EUR_THRESHOLD;
}
}
private function getSalesChannelContext(): SalesChannelContext
{
if ($this->event instanceof CheckoutOrderPlacedEvent) {
return $this->salesChannelContextFactory->create("", $this->event->getSalesChannelId());
} else {
return $this->event->getSalesChannelContext();
}
}
/**
* @426 - Set discount value from response after all other lineItems have their price set "$this->calculateLineItems()"
* **lineItemsCost += discount value**
* @param OrderLineItemEntity|LineItem|null $promotion
* @return void
*/
private function calculateDiscount(OrderLineItemEntity|LineItem|null $promotion): void
{
if ($promotion && isset($this->result["discounts"])) {
if ($this->event instanceof CheckoutOrderPlacedEvent) {
$context = $this->salesChannelContextFactory->create("", $this->event->getSalesChannelId());
} else {
$context = $this->event->getSalesChannelContext();
}
foreach ($this->result["discounts"] as $discount) {
if (!isset($discount["code"]) || !isset($discount["value"])) {
continue;
}
// Promotion with percentage, calculate
if ($discount["code"] === self::ZRN0) {
$value = -abs((float)$discount["value"]);
// Set value that was calculated from SAP. Dont use shopware's price calculation
$promotion->addArrayExtension("sap",["discountValue" => $value]);
$calculated_price = $this->percentageCalculator->calculate(
(float)$value,
$this->lineItems->getPrices(),
$context
);
} elseif ($discount["code"] === self::ZRN2) {
$value = -abs((float)$discount["value"]);
// Set value that was calculated from SAP. Dont use shopware's price calculation
$promotion->addArrayExtension("sap",["discountValue" => $value]);
// Promotion with fixed value, calculate
$calculated_price = $this->absolutePriceCalculator->calculate(
(float)$value,
$this->lineItems->getPrices(),
$context
);
}
if ($calculated_price !== null) {
$promotion->setPrice($calculated_price);
// Subtract the discount from the current total
$this->lineItemsCost += $promotion->getPrice()->getTotalPrice();
}
}
}
}
/**
* @426 - Adds the promotion with it's corresponding code (ZRN0 | ZRN2) to the request array.
* @param LineItem|OrderLineItemEntity|null $promotion
* @param array $articles
* @return void
*/
private function addDiscountToRequest(OrderLineItemEntity|LineItem|null $promotion, array &$articles): void
{
if ($promotion) {
$promotionType = $promotion?->getPayload()["discountType"];
$code = $promotionType === "percentage" ? self::ZRN0 : self::ZRN2;
$articles["discounts"][] = ["code" => $code, "value" => $promotion?->getPayload()["value"]];
}
}
private function addCustomField(LineItem|OrderLineItemEntity &$lineItem, string $key, mixed $value): void
{
if($lineItem instanceof OrderLineItemEntity) {
$payload = $lineItem->getPayload();
$payload["customFields"][$key] = $value;
} else {
$customFields = $lineItem->getPayloadValue("customFields");
$customFields[$key] = $value;
$lineItem->setPayloadValue("customFields", $customFields);
}
}
}