<?php
/**
* @author Léo BANNHOLTZER (contact@scaledev.fr)
* @copyright 2021 - ScaleDEV SAS, 12 RUE CHARLES MORET, 10120 ST ANDRE LES VERGERS
* @license commercial
*/
declare(strict_types=1);
namespace Bluue\AdelyaBundle\EventSubscriber;
use Bluue\AdelyaBundle\Services\Api;
use Bluue\CashRegisterBundle\Entity\ReceiptLine;
use Bluue\CashRegisterBundle\Event\DiscountCouponEvent;
use Bluue\CashRegisterBundle\Repository\ReceiptLineRepository;
use Doctrine\ORM\EntityManagerInterface;
use NumberFormatter;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Contracts\Translation\TranslatorInterface;
class DiscountCouponSubscriber implements EventSubscriberInterface
{
/**
* @var Api
*/
private Api $api;
/**
* @var TranslatorInterface
*/
private TranslatorInterface $tr;
/**
* @var RequestStack
*/
private RequestStack $requestStack;
/**
* @var ReceiptLineRepository
*/
private ReceiptLineRepository $receiptLineRepo;
/**
* @param Api $api
* @param TranslatorInterface $tr
* @param RequestStack $requestStack
* @param ReceiptLineRepository $receiptLineRepo
*/
public function __construct(
Api $api,
TranslatorInterface $tr,
RequestStack $requestStack,
ReceiptLineRepository $receiptLineRepo
) {
$this->api = $api;
$this->tr = $tr;
$this->requestStack = $requestStack;
$this->receiptLineRepo = $receiptLineRepo;
}
/**
* @return array
*/
public static function getSubscribedEvents(): array
{
return [
DiscountCouponEvent::LIST_COUPONS => 'listCoupons',
DiscountCouponEvent::CHECK_COUPON => 'checkCoupon',
DiscountCouponEvent::APPLY_COUPON => 'applyCoupon'
];
}
/**
* @param DiscountCouponEvent $event
* @return void
*/
public function listCoupons(DiscountCouponEvent $event): void
{
$receipt = $event->getReceipt();
if (!($customer = $receipt->getCustomer())) {
return;
}
$options = $customer->getOptions();
$memberId = $options['adelya_bundle']['id'] ?? null;
if ($memberId) {
$event->addList($this->api->listCoupons($memberId));
}
}
/**
* @param DiscountCouponEvent $event
* @return void
*/
public function checkCoupon(DiscountCouponEvent $event): void
{
if ($coupon = $this->api->checkCoupon($event->getCode())) {
$event->addList([$coupon]);
}
}
/**
* @param DiscountCouponEvent $event
* @return void
*/
public function applyCoupon(DiscountCouponEvent $event): void
{
if ($event->getBundle() !== 'adelya' || !$coupon = $this->api->getCoupon($event->getId())) {
return;
}
$coupon = current($coupon);
$discountType = 'percent';
$amount = (float) $coupon['fvalue'];
if ($campaign = $this->api->getCampaign($coupon['campaign'] ?? '')) {
$campaign = current($campaign);
$discountType = $campaign['couponUnit'] ?? $discountType;
$amount = $amount ?: (float) $campaign['couponValue'];
}
if (!$amount || !in_array($discountType, ['percent', 'discount', 'addCA'])) {
return;
}
$receipt = $event->getReceipt();
if ($discountType == 'percent') {
/** @var ReceiptLine $line */
foreach ($receipt->getLines() as $line) {
if ((int) $line->getQuantity() < 0 || !$line->isEditable()) {
continue;
}
$newPercentage = (float) $line->getDiscountPercentage() + $amount;
$line->setDiscountPercentage((string) $newPercentage);
$line->setTotalDiscountUntaxed(
number_format(
$newPercentage * (float) $line->getTotalAmountUntaxed(true) / 100,
6,
'.',
''
)
);
$line->setTotalDiscount(
number_format(
$newPercentage * (float) $line->getTotalAmount(true) / 100,
6,
'.',
''
)
);
$this->receiptLineRepo->calc($line);
}
$receiptLine = (new ReceiptLine())
->setName($this->tr->trans('Discount coupon', [], 'AdelyaBundle') . ' ' . $coupon['trackCode'])
->setQuantity('-1')
->setUnitPriceUntaxed('0')
->setUnitPrice('0')
->setOptions([
'discountCoupon' => $coupon['id'],
'trackcode' => $coupon['trackCode'],
'adelya_bundle' => true
])
;
} else {
$numberFormatter = NumberFormatter::create(
$this->requestStack->getSession()->get('_locale', 'fr'),
NumberFormatter::CURRENCY
);
$discountValue = $numberFormatter->formatCurrency($amount, $receipt->getCurrency()->getIsoCode());
$amount = (string) ($amount * -1);
$receiptLine = (new ReceiptLine())
->setName($this->tr->trans('value discount', ['value' => $discountValue], 'AdelyaBundle'))
->setQuantity('1')
->setUnitPriceUntaxed($amount)
->setUnitPrice($amount)
->setOptions([
'discountCoupon' => $coupon['id'],
'trackcode' => $coupon['trackCode'],
'adelya_bundle' => true
])
;
}
$receipt->addLine($receiptLine);
$this->receiptLineRepo->calc($receiptLine);
}
}