<?php declare(strict_types=1);
namespace Tds\MerwareDiscounts\Core\Content\Product\SalesChannel;
use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\PriceCollection;
use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Shopware\Core\Checkout\Customer\CustomerEntity;
use Shopware\Core\Content\Product\SalesChannel\SalesChannelProductEntity;
use Shopware\Core\System\SalesChannel\Entity\SalesChannelEntityLoadedEvent;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Tds\MerwareDiscounts\Core\Checkout\Cart\Price\DiscountPriceCalculator;
use Tds\MerwareDiscounts\Service\DiscountService;
/**
* Class SalesChannelProductSubscriber
*
* @package Tds\MerwareDiscounts\Core\Content\Product\SalesChannel
*/
class SalesChannelProductSubscriber implements EventSubscriberInterface
{
/**
* @var DiscountPriceCalculator
*/
private $discountPriceCalculator;
/**
* @var QuantityPriceCalculator
*/
private $quantityPriceCalculator;
/**
* @var SystemConfigService
*/
private $systemConfigService;
/**
* @var DiscountService
*/
private $discountService;
/**
* SalesChannelProductSubscriber constructor.
* #
* @param DiscountPriceCalculator $priceCalculator
* @param QuantityPriceCalculator $quantityPriceCalculator
* @param SystemConfigService $systemConfigService
* @param DiscountService $discountService
*/
public function __construct(
DiscountPriceCalculator $priceCalculator,
QuantityPriceCalculator $quantityPriceCalculator,
SystemConfigService $systemConfigService,
DiscountService $discountService
) {
$this->discountPriceCalculator = $priceCalculator;
$this->quantityPriceCalculator = $quantityPriceCalculator;
$this->systemConfigService = $systemConfigService;
$this->discountService = $discountService;
}
/**
* {@inheritDoc}
*/
public static function getSubscribedEvents()
{
return [
'sales_channel.product.loaded' => 'loaded',
];
}
/**
* Event function to trigger storefront price calculations
*
* @param SalesChannelEntityLoadedEvent $event
*/
public function loaded(SalesChannelEntityLoadedEvent $event): void
{
/** @var SalesChannelProductEntity $product */
foreach ($event->getEntities() as $product) {
$this->calculatePrices(
$event->getSalesChannelContext(),
$product,
$event->getSalesChannelContext()->getCustomer()
);
}
}
/**
* Function to calculate storefront prices (called per product).
*
* @param SalesChannelContext $context
* @param SalesChannelProductEntity $product
* @param CustomerEntity|null $customer
*/
private function calculatePrices(SalesChannelContext $context, SalesChannelProductEntity $product, $customer = null): void
{
// [{"artcode": "SW10001", "price": "40"}, {"artcode": "SW10002", "price": "30"}]
if (!empty($customer)) {
$generalDiscount = $this->discountService->getGeneralDiscount($customer, $product);
$productDiscountPrice = $this->discountService->getProductDiscountPrice($customer, $product);
if ($product->getCalculatedPrices()) {
$priceCollection = new PriceCollection();
foreach ($product->getCalculatedPrices() as $price) {
$definition = new QuantityPriceDefinition(
$price->getUnitPrice(),
$price->getTaxRules(),
$price->getQuantity()
);
/**
* discount price: remove list prices (from/to)
*/
if (!empty($productDiscountPrice)) {
$discountPrice = $this->discountPriceCalculator->createCalculatePrice($definition, $context, $generalDiscount, $productDiscountPrice);
} else {
/**
* no discount price: add (possible) general customer discounts
*/
$discountPrice = $this->discountPriceCalculator->createCalculatePrice($definition, $context, $generalDiscount);
}
$priceCollection->add($discountPrice);
}
$product->setCalculatedPrices($priceCollection);
}
$definition = new QuantityPriceDefinition(
$product->getCalculatedPrice()->getUnitPrice(),
$product->getCalculatedPrice()->getTaxRules(),
$product->getCalculatedPrice()->getQuantity()
);
/**
* discount price: remove list prices (from/to)
*/
if (!empty($productDiscountPrice)) {
$discountPrice = $this->discountPriceCalculator->createCalculatePrice($definition, $context, $generalDiscount, $productDiscountPrice);
$cheapestDiscountPrice = $this->discountPriceCalculator->createCheapestPrice($definition, $context, $generalDiscount, $productDiscountPrice);
} else {
/**
* no discount price: add (possible) general customer discounts
*/
$discountPrice = $this->discountPriceCalculator->createCalculatePrice($definition, $context, $generalDiscount);
$cheapestDiscountPrice = $this->discountPriceCalculator->createCheapestPrice($definition, $context, $generalDiscount);
}
$product->setCalculatedPrice($discountPrice);
$product->setCalculatedCheapestPrice($cheapestDiscountPrice);
}
}
}