<?php
namespace Slivki\Services;
use Doctrine\ORM\EntityManagerInterface;
use Mpdf\Config\ConfigVariables;
use Mpdf\Config\FontVariables;
use Mpdf\Mpdf;
use Slivki\Entity\GeoLocation;
use Slivki\Entity\GiftCertificate;
use Slivki\Entity\GiftCertificateOrder;
use Slivki\Entity\Offer;
use Slivki\Entity\OfferOrderDetails;
use Slivki\Entity\User;
use Slivki\Enum\Order\PaymentType;
use Slivki\Services\QRCodeGenerator\Generators\SosediBarcodeGenerator;
use Slivki\Services\Subscription\SubscriptionService;
use Symfony\Component\HttpKernel\KernelInterface;
use Twig\Environment;
use function array_filter;
use function array_values;
class GiftCertificateService
{
private EntityManagerInterface $entityManager;
private Environment $twig;
private SubscriptionService $subscriptionService;
private ImageService $imageService;
public function __construct(
EntityManagerInterface $entityManager,
Environment $twig,
SubscriptionService $subscriptionService,
ImageService $imageService
) {
$this->entityManager = $entityManager;
$this->twig = $twig;
$this->subscriptionService = $subscriptionService;
$this->imageService = $imageService;
}
// TODO: Refactor this shit
public function getCertificates(Offer $offer, $buyOnlyCodes = false): array
{
$offerID = $offer->getID();
$sql = "select gift_certificate.id, sum(offer_order_details.items_count) as cnt from offer_order_details
inner join offer_order on offer_order.id = offer_order_details.offer_order_id
inner join gift_certificate on gift_certificate.id = offer_order_details.gift_certificate_id
where offer_order.status > 0 and offer_order.type = " . GiftCertificateOrder::TYPE . " and offer_order.offer_id = " . $offerID
. " group by 1 order by 2 desc;";
$crtPurchaseCount = $this->entityManager->getConnection()->executeQuery($sql)->fetchAll(\PDO::FETCH_ASSOC);
$offer->setGiftCertificates($this->entityManager->find(Offer::class, $offerID)->getGiftCertificates());
$certificates = [];
foreach ($offer->getActiveGiftCertificates() as $certificate) {
if ($offerID != 283213 && (!$certificate->getActiveDays() || $certificate->getActiveDays() == 0)) {
continue;
}
$key = array_search($certificate->getID(), array_column($crtPurchaseCount, 'id'));
$purchaseCount = isset($crtPurchaseCount[$key]['cnt']) && $key !== false ? $crtPurchaseCount[$key]['cnt'] : 0;
$certificates[] = $this->getCertificateData($certificate, $purchaseCount);
}
return $buyOnlyCodes
? array_values(array_filter($certificates, static fn (\stdClass $certificate) => $certificate->buyOnlyCode))
: array_values(array_filter($certificates, static fn (\stdClass $certificate) => !$certificate->buyOnlyCode));
}
public function getCertificatePdf(KernelInterface $kernel, OfferOrderDetails $offerOrderDetails) {
$giftCertificate = $offerOrderDetails->getGiftCertificate();
if (!$giftCertificate) {
return null;
}
$customFontDir = $kernel->getProjectDir() . '/public/fonts/crt-fonts/ttf';
$defaultConfig = (new ConfigVariables())->getDefaults();
$defaultFontDir = $defaultConfig['fontDir'];
$defaultFontConfig = (new FontVariables())->getDefaults();
$defaultFontData = $defaultFontConfig['fontdata'];
$mpdf = new Mpdf([
'fontDir' => array_merge($defaultFontDir, [
$customFontDir,
]),
'tempDir' => '/tmp',
'fontdata' => $defaultFontData + [
'sfrounded' => [
'R' => 'SFRounded-Ultralight.ttf',
],
'sf' => [
'R' => 'SFProText-Regular.ttf',
],
],
'mode' => 'utf-8',
'format' => 'A4',
'orientation' => 'P',
'margin_top' => 10,
'margin_bottom' => 0,
'margin_left' => 0,
'margin_right' => 0,
]);
$mpdf->curlAllowUnsafeSslRequests = true;
$template = 'Slivki/gift_certificates/crt_pdf.html.twig';
if (SosediBarcodeGenerator::OFFER_ID === (int) $offerOrderDetails->getOfferOrder()->getOffer()->getID()) {
$template = 'Slivki/gift_certificates/sosedi_pdf.html.twig';
}
$mpdf->WriteHTML($this->twig->render($template, [
'offerOrderDetails' => $offerOrderDetails,
'giftCertificate' => $giftCertificate,
'offer' => $giftCertificate->getOffer(),
]));
$mpdf->Output('crt_' . $offerOrderDetails->getID() . '.pdf', 'D');
}
private function getCertificateData(GiftCertificate $certificate, $purchaseCount): \stdClass
{
$data = new \stdClass();
$data->imageURL = $this->imageService->getImageURLCached($certificate->getMedia(), 540, 0);
$data->name = $certificate->getName();
$data->sizeFull = null;
$data->offerPrice = $certificate->getPriceOffer();
$data->regularPrice = $certificate->getPriceRegular();
$data->id = $certificate->getID();
$data->position = $certificate->getPosition();
$codesPerItem = $certificate->getCodesPerItem();
if (!$codesPerItem) {
$codesPerItem = 1;
}
$data->productsPerCode = 1/$codesPerItem;
$data->purchaseCount = $purchaseCount;
$data->description = $certificate->getDescription();
$giftCertificateCodePool = $certificate->getLastActiveCodePool();
if ($giftCertificateCodePool) {
$data->freeCodesCount = $giftCertificateCodePool->getFreeCodesCount();
}
$geoLocationIds = [];
/** @var GeoLocation $geoLocation */
foreach ($certificate->getGeoLocations() as $geoLocation) {
$geoLocationIds[] = $geoLocation->getID();
}
$data->geoLocationIds = $geoLocationIds;
$tags = [];
foreach ($certificate->getTags() as $key=>$tag) {
$tags[$key]['ID'] = $tag->getID();
$tags[$key]['name'] = $tag->getTag();
}
$data->tags = $tags;
$data->buyOnlyCode = $certificate->isBuyOnlyCode();
return $data;
}
public function createOrder(User $user, int $offerID, $data, $deviceType = null) {
$offer = $this->entityManager->find(Offer::class, $offerID);
$order = new GiftCertificateOrder();
$order->setDeviceType($deviceType);
$order->setUser($user);
$order->setOffer($offer);
$order->setPaymentType($data['paymentType'] ?? PaymentType::ONLINE);
$codesCount = 0;
$totalOfferAmount = 0;
$isFreeStyle = in_array($offerID, Offer::FREESTYLE_OFFER_IDS, true);
$isSosedi = Offer::SOSEDI_OFFER_ID === $offerID;
foreach ($data['items'] as $item) {
$count = $item['amount'];
if ($count == 0) {
continue;
}
$giftCertificate = $this->entityManager->find(GiftCertificate::class, $item['id']);
if (!$giftCertificate) {
continue;
}
for ($i = 0; $i < $count; $i++) {
if ($isFreeStyle || $isSosedi) {
$codeTill = $offer->getCodeActiveTill()->setTime(23,59,59);
} else {
$codeTill = new \DateTime("+" . $giftCertificate->getActiveDays() ." days");
}
$details = new OfferOrderDetails();
$details->setGiftCertificate($giftCertificate);
$details->setItemsCount(1);
$details->setCodeActiveTill($codeTill);
$details->setPurchasePrice($giftCertificate->getPriceOffer());
$order->addOfferOrderDetails($details);
}
$codesCount += $giftCertificate->getCodesPerItem() * $count;
$totalOfferAmount += $giftCertificate->getPriceOffer() * $count;
}
$codesCount = ceil($codesCount);
$codeCost = $this->entityManager->getRepository(Offer::class)->getCodeCost($offer, $codesCount);
if ($this->subscriptionService->isSubscriber($user)
|| $user->getBatchCodesCount() >= $codesCount
|| $user->isBalanceAllowed($codeCost * $codesCount)
) {
$codeCost = 0;
}
$order->setCodeCost($codeCost);
$order->setAmount($totalOfferAmount + $codesCount * $codeCost);
$order->setCodesCount($codesCount);
$order->setComment($data['comment']);
$order->setUserPhone($data['phone']);
$this->entityManager->persist($order);
$this->entityManager->flush();
return $order;
}
public function hasSosediPurchase(User $user = null) {
$offerID = 283793;
if (!$user) {
return false;
}
$sql = "select count(*) from offer_order where offer_id = $offerID and user_id = "
. $user->getID() . " and status > 0";
$sosediPurchasesCount = $this->entityManager->getConnection()->executeQuery($sql)->fetchColumn();
return $sosediPurchasesCount > 0;
}
}