<?php declare(strict_types=1);
namespace AbmAdjustments\Core\Checkout\Cart;
use Psr\Cache\InvalidArgumentException;
use Shopware\Core\System\SystemConfig\SystemConfigService;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Symfony\Contracts\Cache\CacheInterface;
use Shopware\Core\Checkout\Cart\Cart;
use Shopware\Core\Checkout\Cart\CartBehavior;
use Shopware\Core\Checkout\Cart\CartDataCollectorInterface;
use Shopware\Core\Checkout\Cart\CartProcessorInterface;
use Shopware\Core\Checkout\Cart\LineItem\CartDataCollection;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Cart\Price\QuantityPriceCalculator;
use Shopware\Core\Checkout\Cart\Price\Struct\QuantityPriceDefinition;
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRule;
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRuleCollection;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\System\SalesChannel\SalesChannelContext;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class OverwritePriceCollector implements CartDataCollectorInterface, CartProcessorInterface
{
const ALL_ZERO_TAX_GROSS_NET_STG = 'all-zero-tax-gross-net-stg';
const ALL_ZERO_TAX_GROSS_NET_LIVE = 'all-zero-tax-gross-net-live';
private QuantityPriceCalculator $calculator;
/**
* @var EntityRepositoryInterface
*/
private $productRepository;
/**
* @var RequestStack
*/
private $requestStack;
private ContainerInterface $container;
private $systemConfigService;
public function __construct(
QuantityPriceCalculator $calculator,
EntityRepositoryInterface $productRepository,
RequestStack $requestStack,
ContainerInterface $container,
SystemConfigService $systemConfigService
)
{
$this->calculator = $calculator;
$this->productRepository = $productRepository;
$this->requestStack = $requestStack;
$this->container = $container;
$this->systemConfigService = $systemConfigService;
}
public function collect(CartDataCollection $data, Cart $original, SalesChannelContext $context, CartBehavior $behavior): void
{
// get all product ids of current cart
$productIds = $original->getLineItems()->filterType(LineItem::PRODUCT_LINE_ITEM_TYPE)->getReferenceIds();
// remove all product ids which are already fetched from the database
$filtered = $this->filterAlreadyFetchedPrices($productIds, $data);
// Skip execution if there are no prices to be saved
// if (empty($filtered) || $this->systemConfigService->get(self::FORCE_BRUT_TAX_SETTING)) {
if (empty($filtered)) {
return;
}
foreach ($filtered as $id) {
$key = $this->buildKey($id);
$criteria = (new Criteria())->addAssociation('prices');
$criteria->addFilter(new EqualsFilter('id', $id));
/* @var Shopware\Core\Content\Product\ProductEntity $productEntity */
$productEntity = $this->productRepository->search($criteria, Context::createDefaultContext())->first();
$bTax = $productEntity->getTranslated()['customFields']['taxrate'] ?? 1;
if (empty($bTax)) {
if (!empty($productEntity->getPrices()->first())) {
$newPrice = (float)$productEntity->getPrices()->first()->getPrice()->first()->getNet() ?? null;
}
}
// we have to set a value for each product id to prevent duplicate queries in next calculation
if (!empty($newPrice)) {
$data->set($key, $newPrice);
}
}
}
private function filterAlreadyFetchedPrices(array $productIds, CartDataCollection $data): array
{
$filtered = [];
foreach ($productIds as $id) {
$key = $this->buildKey($id);
// already fetched from database?
if ($data->has($key)) {
continue;
}
$filtered[] = $id;
}
return $filtered;
}
private function buildKey(string $id): string
{
return 'price-overwrite-' . $id;
}
public function process(CartDataCollection $data, Cart $original, Cart $toCalculate, SalesChannelContext $context, CartBehavior $behavior): void
{
$oCurrentSession = $this->requestStack->getCurrentRequest()->getSession();
$oCurrentSession->set('isZeroTaxCart', false);
// get all product line items
$products = $original->getLineItems()->filterType(LineItem::PRODUCT_LINE_ITEM_TYPE);
$cache = new FilesystemAdapter();
$sRoute = $this->requestStack->getCurrentRequest()->attributes->get('_route');
if (empty($original->getLineItems()->count()) || $sRoute == 'frontend.account.register.save') {
$oCurrentSession->remove('zero_tax_consent');
}
$i = 0;
$bFirstCheckoutEntry = false;
if($sRoute == 'frontend.checkout.confirm.page') {
if(!$oCurrentSession->get('first_checkout_entry')) {
$oCurrentSession->set('first_checkout_entry', true);
$bFirstCheckoutEntry = true;
}
}
$now = new \DateTime('now', new \DateTimeZone('Europe/Berlin'));
$now->setTime(0, 0, 0);
foreach ($products as $product) {
if (true) {
$releaseDateString = $product->getPayloadValue('releaseDate');
if (!is_null($releaseDateString)) {
$releaseDate = new \DateTime($releaseDateString, new \DateTimeZone('Europe/Berlin'));
$releaseDate->setTime(0, 0, 0);
if ($releaseDate > $now) {
$interval = $now->diff($releaseDate);
$daysDifference = $interval->days;
$earliest = $product->getDeliveryInformation()->getDeliveryTime()->getMin() + $daysDifference;
$latest = $product->getDeliveryInformation()->getDeliveryTime()->getMax() + $daysDifference;
$product->getDeliveryInformation()->getDeliveryTime()->setMin($earliest);
$product->getDeliveryInformation()->getDeliveryTime()->setMax($latest);
}
}
}
$newPrice = null;
$key = $this->buildKey($product->getReferencedId());
if (!$data->has($key) || $data->get($key) === null) {
continue;
}
$criteria = new Criteria([$product->getReferencedId()]);
$products = $this->productRepository->search($criteria, Context::createDefaultContext());
$productEntity = $products->first();
$oTaxRepository = $this->container->get('tax.repository');
/* To remove */
$taxRate = (!empty($oCurrentSession->get('zero_tax_consent')) || $bFirstCheckoutEntry) ? 0.0 : 19;
if($bFirstCheckoutEntry || $oCurrentSession->get('zero_tax_waiver')) {
$taxRate = 19;
}
/* To add */
// $taxRate = (empty($oCurrentSession->get('zero_tax_consent')) || $bFirstCheckoutEntry) && false ? 19 : 0.0;
// $sTaxMode = (
// false &&
// (!$oCurrentSession->get('zero_tax_consent') && !$bFirstCheckoutEntry) ||
// $bFirstCheckoutEntry
// ) ? 'gross' : 'net';
/* to remove */
$sTaxMode = !$oCurrentSession->get('zero_tax_consent') && !$bFirstCheckoutEntry ? 'gross' : 'net';
if($bFirstCheckoutEntry || $oCurrentSession->get('zero_tax_waiver')) {
$sTaxMode = 'gross';
}
if(empty($oCurrentSession->get('zero_tax_consent')) && empty($oCurrentSession->get('zero_tax_waiver'))) {
$sTaxMode = 'net';
$taxRate = 0.0;
}
$criteria = new Criteria();
$criteria->addFilter(new EqualsFilter('taxRate', $taxRate));
$taxes = $oTaxRepository->search($criteria, Context::createDefaultContext());
$tax = $taxes->first();;
$productEntity->setTax($tax);
$taxRule = new TaxRule(
$taxRate,
100
);
$aLinePayload = $original->getLineItems()->getPayload()[$product->getReferencedId()];
$aLinePayload['taxId'] = $tax->getId();
$product->setPayload($aLinePayload);
$criteria = (new Criteria())->addAssociation('prices');
$criteria->addFilter(new EqualsFilter('id', $product->getReferencedId()));
/* @var \Shopware\Core\Content\Product\ProductEntity $productEntity */
$productEntity = $this->productRepository->search($criteria, Context::createDefaultContext())->first();
$bTax = $productEntity->getTranslated()['customFields']['taxrate'] ?? 1;
//
// dump($oCurrentSession->get('zero_tax_consent'));
// dump($oCurrentSession->get('zero_tax_waiver'));
// dump($sTaxMode);
// dd($taxRate);
//
/* @var Shopware\Core\Checkout\Cart\LineItem\LineItem $product */
if (empty($bTax)) {
$i++;
$oCurrentSession->set('isZeroTaxCart', true);
if (!empty($productEntity->getPrices()->first())) {
if ($sTaxMode == 'net') {
$newPrice = (float)$productEntity->getPrices()->first()->getPrice()->first()->getNet() ?? null;
} elseif ($sTaxMode == 'gross') {
$newPrice = (float)$productEntity->getPrices()->first()->getPrice()->first()->getGross() ?? null;
}
}
} else {
continue;
}
if (empty($product->getPrice()) || empty($newPrice)) {
continue;
}
$definition = new QuantityPriceDefinition(
$newPrice,
new TaxRuleCollection([$taxRule]),
$product->getPrice()->getQuantity() ?? $product->getQuantity()
);
$calculated = $this->calculator->calculate($definition, $context);
$product->setPrice($calculated);
$product->setPriceDefinition($definition);
$oCurrentSession->set('isZeroTaxCart', true);
}
if (empty($i)) {
// $oCurrentSession->remove('zero_tax_consent');
// $oCurrentSession->remove('first_checkout_entry');
}
}
}