<?php
namespace Twigel\SportLabel\Subscriber;
use Shopware\Core\Checkout\Cart\Event\BeforeLineItemAddedEvent;
use Shopware\Core\Checkout\Cart\LineItem\LineItemCollection;
use Shopware\Core\Checkout\Cart\Price\Struct\CalculatedPrice;
use Shopware\Core\Checkout\Cart\Tax\Struct\CalculatedTaxCollection;
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRuleCollection;
use Shopware\Core\Checkout\Promotion\Cart\PromotionItemBuilder;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class BeforeLineItemSubscriber implements EventSubscriberInterface
{
/**
* @var EntityRepositoryInterface
*/
private EntityRepositoryInterface $groupRepository;
/**
* @var EntityRepositoryInterface
*/
private EntityRepositoryInterface $promotionRepository;
/**
* @var PromotionItemBuilder
*/
private PromotionItemBuilder $promotionItemBuilder;
public function __construct(
EntityRepositoryInterface $groupRepository,
EntityRepositoryInterface $promotionRepository,
PromotionItemBuilder $promotionItemBuilder
)
{
$this->groupRepository = $groupRepository;
$this->promotionRepository = $promotionRepository;
$this->promotionItemBuilder = $promotionItemBuilder;
}
public static function getSubscribedEvents(): array
{
return [
BeforeLineItemAddedEvent::class => 'lineItem'
];
}
public function lineItem(BeforeLineItemAddedEvent $event)
{
if ($event->getSalesChannelContext()->getCustomer()) {
$groupId = $event->getSalesChannelContext()->getCustomer()->getGroupId();
$criteria = new Criteria([$groupId]);
$group = $this->groupRepository->search($criteria, $event->getContext())->first();
if ($group->getCustomFields() && array_key_exists('twigel_customer_group_discount', $group->getCustomFields()) && $group->getCustomFields()['twigel_customer_group_discount']) {
$promotionId = $group->getCustomFields()['twigel_customer_group_discount'];
$criteria = new Criteria([$promotionId]);
$criteria->addAssociations(['discounts']);
$promotion = $this->promotionRepository->search($criteria, $event->getContext())->first();
if (!$promotion) {
return;
}
$total = $event->getCart()->getPrice()->getTotalPrice();
$discount = $promotion->getDiscounts()->first();
if (!empty($discount) && $promotion->isActive()) {
$promotionLineItem = $this->promotionItemBuilder->buildDiscountLineItem(
$promotion->getCode(),
$promotion,
$discount,
$event->getSalesChannelContext()->getCurrencyId()
);
switch ($promotionLineItem->getPayloadValue('discountType')) {
case 'fixed_unit':
$promotionValue = $promotionLineItem->getPayloadValue('value');
break;
default:
$promotionValue = $total / 100 * $promotionLineItem->getPayloadValue('value');
}
$promotionValue = -1 * $promotionValue;
$promotionLineItem->setPrice(
new CalculatedPrice(
$promotionValue,
$promotionValue,
new CalculatedTaxCollection(),
new TaxRuleCollection()
)
);
$promotionLineItem->setStackable(true);
$cartPromotionId = '';
foreach ($event->getCart()->getLineItems()->getElements() as $lineItem){
if ($lineItem->getType() === 'promotion'){
$cartPromotionId = $lineItem->getId();
}
}
if ($cartPromotionId !== $promotionLineItem->getId()){
$event->getCart()->addLineItems(new LineItemCollection([$promotionLineItem]));
}
}
}
}
}
}