<?php
namespace Customize\EventListener;
use Carbon\Carbon;
use Eccube\Event\EventArgs;
use Eccube\Event\EccubeEvents;
use Eccube\Service\MailService;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Eccube\Entity\Order;
use Eccube\Common\EccubeConfig;
use Customize\Entity\ReservationActual;
use Customize\Entity\ReservationInfo;
use Symfony\Component\Mime\Address;
use Eccube\Repository\BaseInfoRepository;
use Symfony\Component\Mailer\MailerInterface;
use Symfony\Component\Mime\Email;
use Customize\Entity\OrderDetailAdditionalInfo;
use Customize\Entity\TimeSlot;
use Symfony\Component\Mailer\Exception\TransportExceptionInterface;
class ReservationListener implements EventSubscriberInterface
{
protected $BaseInfo;
protected $mailer;
protected $mailService;
public function __construct(
public EntityManagerInterface $entityManager,
public SessionInterface $session,
public EccubeConfig $eccubeConfig,
public \Twig\Environment $twig,
BaseInfoRepository $baseInfoRepository,
MailerInterface $mailer,
MailService $mailService
) {
$this->BaseInfo = $baseInfoRepository->get();
$this->mailer = $mailer;
$this->mailService = $mailService;
}
/**
* Update or create reservation actual
*
* @param EventArgs $event
* @return void
*/
public function onUpdateOrCreateReservationActual(EventArgs $event)
{
$reservationInfo = $event->getArgument('reservationInfo');
$reservationActual = $this->entityManager->getRepository(ReservationActual::class)
->findOneBy(
[
'visit_day' => $reservationInfo->getVisitDay(),
'shop' => $reservationInfo->getShop(),
'time_slot_id' => $reservationInfo->getTimeSlotId()
]
);
$usePeople = $reservationInfo->getUsePeople();
if ($reservationActual) {
$quantityReservation = $reservationActual->getQuantity() ? $reservationActual->getQuantity() + 1 : 0;
$quantityCustomerReservation = $reservationActual->getAmountCustomerReservation() ? $reservationActual->getAmountCustomerReservation() + $usePeople : 0;
$reservationActual->setQuantity($quantityReservation);
$reservationActual->setAmountCustomerReservation($quantityCustomerReservation);
} else {
$timeSlot = $this->entityManager->getRepository(TimeSlot::class)->findOneBy(
['id' => $reservationInfo->getTimeSlotId()]
);
$visitDay = $reservationInfo->getVisitDay();
$reservationActual = new ReservationActual();
$reservationActual->setTimeSlotId($timeSlot);
$reservationActual->setShop($reservationInfo->getShop());
$reservationActual->setVisitDay($visitDay);
$reservationActual->setQuantity(1);
$reservationActual->setAmountCustomerReservation($usePeople);
$this->entityManager->persist($reservationActual);
}
$this->entityManager->flush();
}
/**
* Send email after register reservation
*
* @param EventArgs $event
* @return void
*/
public function onSendMailReservationActual(EventArgs $event)
{
log_info('Start sending emails to register for reservations');
$reservationInfo = $event->getArgument('reservationInfo');
$templateFileName = '/Mail/register_reservation.twig';
$arrayParam = [
'visit_day' => $reservationInfo->getVisitDay(),
'time_start' => $reservationInfo->getTimeSlotId()->getStartTime(),
'time_end' => $reservationInfo->getTimeSlotId()->getEndTime(),
'customer_name' => $reservationInfo->getCustomerName01() . ' ' . $reservationInfo->getCustomerName02(),
'customer_kana' => $reservationInfo->getCustomerKana01() . ' ' . $reservationInfo->getCustomerKana02(),
'tel' => $reservationInfo->getTel(),
'email' => $reservationInfo->getEmail(),
'item' => $reservationInfo->getItem(),
'shop' => $reservationInfo->getShop(),
'use_people' => $reservationInfo->getUsePeople(),
'use_day' => $reservationInfo->getUseDay(),
'purpose' => $reservationInfo->getPurpose(),
'height' => $reservationInfo->getHeight(),
'budget' => $reservationInfo->getBudget(),
'characteristic' => $reservationInfo->getCharacteristic(),
'note' => $reservationInfo->getNote(),
'body_type' => $reservationInfo->getBodyType() ? json_decode($reservationInfo->getBodyType()) : $reservationInfo->getBodyType(),
];
$body = $this->twig->render($templateFileName, $arrayParam);
$message = (new Email())
->subject(ReservationInfo::RESERVATION_MAIL_SUBJECT)
->from(new Address($this->BaseInfo->getEmail01(), $this->BaseInfo->getShopName()))
->to($reservationInfo->getEmail())
->replyTo($this->BaseInfo->getEmail03())
->returnPath($this->BaseInfo->getEmail04());
$htmlFileName = $this->mailService->getHtmlTemplate($templateFileName);
if (!is_null($htmlFileName)) {
$htmlBody = $this->twig->render($htmlFileName, $arrayParam);
$message
->text($body)
->html($htmlBody);
} else {
$message->html($body);
}
try {
$this->mailer->send($message);
} catch (TransportExceptionInterface $e) {
log_critical('Show error send email reservation', [$e->getMessage()]);
}
}
/**
* Check date visit is full slot
*
* @param EventArgs $event
* @return void
*/
public function onCheckReservationIsFullSlot(EventArgs $event)
{
$reservationInfo = $event->getArgument('reservationInfo');
$quantityMaxSetting = $event->getArgument('quantity_max_setting');
$timeSlotId = $reservationInfo->getTimeSlotId()->getId();
$shopName = $reservationInfo->getShop();
$timeEnd = Carbon::parse($reservationInfo->getTimeSlotId()->getEndTime())->format('H:i');
$dateVisit = Carbon::parse($reservationInfo->getVisitDay())->format('Y-m-d');
$totalOrderTypeVisit = $this->totalOrderTypeVisit($shopName, $dateVisit, $timeEnd);
$queryBuilder = $this->entityManager->createQueryBuilder();
$queryBuilder->select('COUNT(DISTINCT re.id) as totalReservation')
->from(ReservationInfo::class, 're')
->where('re.time_slot_id = :time_slot_id')
->andWhere('re.visit_day = :visit_day')
->andWhere('re.shop = :shop_name')
->setParameter('time_slot_id', $timeSlotId)
->setParameter('visit_day', $dateVisit)
->setParameter('shop_name', $shopName);
$results = $queryBuilder->getQuery()->getResult();
return $event->setArgument('is_full_slot', $results[0]['totalReservation'] + $totalOrderTypeVisit >= $quantityMaxSetting);
}
/**
* Count order type visit
*
* @param [string] $shopName
* @param [date] $dateVisit
* @param [time] $timeEnd
* @return integer
*/
private function totalOrderTypeVisit($shopName, $dateVisit, $timeEnd): int
{
$queryBuilder = $this->entityManager->createQueryBuilder();
$queryBuilder->select('COUNT(odai.id) as record_count_visit')
->from(OrderDetailAdditionalInfo::class, 'odai')
->leftJoin(Order::class, 'otb', 'WITH', 'odai.order_id = otb.id')
->where('otb.OrderStatus <> 3')
->andWhere('odai.wear_date = :date')
->andWhere('odai.order_type = :order_type')
->andWhere('odai.visit_store = :shop')
->andWhere('SUBSTRING(odai.time_departure, 1, 5) = SUBSTRING(:end_time, 1, 5)')
->setParameter('order_type', 'visit')
->setParameter('end_time', $timeEnd)
->setParameter('shop', $shopName)
->setParameter('date', $dateVisit);
$results = $queryBuilder->getQuery()->getResult();
return $results[0]['record_count_visit'];
}
/**
* Initialize event
*
* @return void
*/
public static function getSubscribedEvents()
{
return [
EccubeEvents::FRONT_UPDATE_RESERVATION_ACTUAL => 'onUpdateOrCreateReservationActual',
EccubeEvents::FRONT_SEND_MAIL_AFTER_REGISTER_RESERVATION => 'onSendMailReservationActual',
EccubeEvents::FRONT_RESERVATION_CHECK_IS_FULL_SLOT => 'onCheckReservationIsFullSlot',
];
}
}