<?php
namespace PixupCheapestPrice\Subscriber;
use Psr\Log\LoggerInterface;
use Shopware\Core\Checkout\Cart\Price\CashRounding;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Content\Product\ProductEvents;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityLoadedEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Event\EntityWrittenEvent;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Aggregation\Metric\MinAggregation;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\RangeFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Sorting\FieldSorting;
use Shopware\Core\Framework\Struct\ArrayEntity;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class ProductSubscriber implements EventSubscriberInterface
{
private LoggerInterface $logger;
private EntityRepositoryInterface $productRepository;
private EntityRepositoryInterface $cheapestPriceProductRepository;
private EntityRepositoryInterface $cheapestPriceProductPriceRepository;
private CashRounding $rounding;
public function __construct(LoggerInterface $logger,
EntityRepositoryInterface $productRepository,
EntityRepositoryInterface $cheapestPriceProductRepository,
EntityRepositoryInterface $cheapestPriceProductPriceRepository,
CashRounding $rounding
)
{
$this->logger = $logger;
$this->productRepository = $productRepository;
$this->cheapestPriceProductRepository = $cheapestPriceProductRepository;
$this->cheapestPriceProductPriceRepository = $cheapestPriceProductPriceRepository;
$this->rounding = $rounding;
}
/**
* @inheritDoc
*/
public static function getSubscribedEvents(): array
{
return [
ProductEvents::PRODUCT_WRITTEN_EVENT => 'productWritten', //product | normal product
ProductEvents::PRODUCT_PRICE_WRITTEN_EVENT => 'productPriceWritten', //product_price | advanced pricing
];
}
public function productWritten(EntityWrittenEvent $event) {
if(is_null($event->getPayloads())) {
return;
}
foreach ($event->getPayloads() as $payload) {
try {
if(isset($payload["id"])) {
$product = $payload['id'];
foreach ($payload['price'] as $priceItem) {
$currency = $priceItem->getCurrencyId();
$priceNet = $this->rounding->cashRound($priceItem->getNet(), $event->getContext()->getRounding());
$priceGross = $this->rounding->cashRound($priceItem->getGross(), $event->getContext()->getRounding());
//Get old price
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('product', $product));
$criteria->addFilter(new EqualsFilter('currency', $currency));
$criteria->addSorting(new FieldSorting('activeFrom', FieldSorting::DESCENDING));
$criteria->setLimit(1);
$oldPrice = $this->cheapestPriceProductRepository->search($criteria, $event->getContext())->first();
//if no old price OR old price !== new price
if(!$oldPrice || (!($oldPrice['net'] == $priceNet && $oldPrice['gross'] == $priceGross))) {
//If old price !== new price
if(isset($oldPrice)) {
if (!(($oldPrice['net'] == $priceNet && $oldPrice['gross'] == $priceGross))) {
//End old price
$this->cheapestPriceProductRepository->update([
[
'id' => $oldPrice['id'],
'activeTill' => new \DateTime()
]
], $event->getContext());
}
}
//Insert new price
$this->cheapestPriceProductRepository->create([[
'product' => $product,
'currency' => $currency,
'net' => $priceNet,
'gross' => $priceGross,
'activeFrom' => (new \DateTime())->format('Y-m-d H:i:s')
]], $event->getContext());
}
}
}
} catch (\Exception $e) {}
}
}
public function productPriceWritten(EntityWrittenEvent $event) {
if(is_null($event->getPayloads())) {
return;
}
foreach ($event->getPayloads() as $payload) {
try {
if(isset($payload["id"])) {
$productPrice = $payload['id'];
if(isset($payload['price'])) {
foreach ($payload['price'] as $priceItem) {
$currency = $priceItem->getCurrencyId();
$priceNet = $this->rounding->cashRound($priceItem->getNet(), $event->getContext()->getRounding());
$priceGross = $this->rounding->cashRound($priceItem->getGross(), $event->getContext()->getRounding());
//End old price
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('productPrice', $productPrice));
$criteria->addFilter(new EqualsFilter('currency', $currency));
$criteria->addSorting(new FieldSorting('activeFrom', FieldSorting::DESCENDING));
$criteria->setLimit(1);
$oldPrice = $this->cheapestPriceProductPriceRepository->search($criteria, $event->getContext())->first();
//if no old price OR old price !== new price
if (!$oldPrice || !($oldPrice['net'] == $priceNet && $oldPrice['gross'] == $priceGross)) {
//If old price !== new price
if(isset($oldPrice)) {
if (!($oldPrice['net'] == $priceNet && $oldPrice['gross'] == $priceGross)) {
//End old price
$this->cheapestPriceProductPriceRepository->update([
[
'id' => $oldPrice['id'],
'activeTill' => new \DateTime()
]
], $event->getContext());
}
}
//Insert new price
$this->cheapestPriceProductPriceRepository->create([[
'productPrice' => $productPrice,
'currency' => $currency,
'net' => $priceNet,
'gross' => $priceGross,
'activeFrom' => (new \DateTime())->format('Y-m-d H:i:s')
]], $event->getContext());
}
}
}
}
} catch (\Exception $e) {}
}
}
}