Deprecated : Constant E_STRICT is deprecated in /home/pastorz/old-espace-client/vendor/symfony/error-handler/ErrorHandler.php on line 58
Deprecated : Constant E_STRICT is deprecated in /home/pastorz/old-espace-client/vendor/symfony/error-handler/ErrorHandler.php on line 76
Symfony Profiler
<?php
namespace App\Service ;
use App\Entity\Booking ;
use App\Entity\BookingConfig ;
use App\Entity\BookingConfigDate ;
use App\Entity\BookingConfigHour ;
use App\Entity\DeliveryNote ;
use DateInterval ;
use DatePeriod ;
use DateTime ;
use DateTimeInterface ;
use Doctrine\Common\Collections\ArrayCollection ;
use Doctrine\ORM\EntityManagerInterface ;
use Exception ;
use GuzzleHttp\Exception\GuzzleException ;
class BookingService
{
private EntityManagerInterface $em ;
private BookingConfig $config ;
private KheopsService $kheopsService ;
private BrandService $brandService ;
private int $slotLength ;
private array $days ;
/**
* @param EntityManagerInterface $em
* @param KheopsService $kheopsService
* @param BrandService $brandService
*/
public function __construct ( EntityManagerInterface $em , KheopsService $kheopsService , BrandService $brandService )
{
$this -> em = $em ;
$this -> kheopsService = $kheopsService ;
$this -> brandService = $brandService ;
$this -> config = $this -> getConfig ();
$this -> slotLength = $this -> config -> getSlotLength ();
$this -> days = array_map (fn( BookingConfigHour $hour ) => $hour -> getDay (), $this -> em -> getRepository ( BookingConfigHour ::class)-> findBy ([ 'bookingConfig' => $this -> config ], [ 'day' => 'ASC' ]));
}
public function getConfig ()
{
return $this -> em -> getRepository ( BookingConfig ::class)-> findOneByType ( 'delivery_note' );
}
public function getDay ( DateTimeInterface $date ): ? BookingConfigHour
{
return $this -> em -> getRepository ( BookingConfigHour ::class)-> findOneBy ([ 'bookingConfig' => $this -> config , 'day' => $date -> format ( 'N' )]);
}
public function check ( Booking $booking ): bool
{
return $this -> getSlots ( $booking -> getDate (), $booking -> getDeliveryNote ())
->filter (fn(array $slot ) => $slot [ 'enable' ])
->map (fn(array $slot ) => $slot [ 'datetime' ]-> format ( 'H:i' ))
->contains ( $booking -> getTime ()-> format ( 'H:i' ));
}
/**
* @param DateTimeInterface $date
* @param DeliveryNote|null $deliveryNote
* @return ArrayCollection
*/
public function getSlots ( DateTimeInterface $date , DeliveryNote $deliveryNote = null ): ArrayCollection
{
$this -> cleanBookings ();
$day = $this -> getDay ( $date );
if (!$day ) {
return new ArrayCollection ();
}
$slots = array();
$now = new DateTime ();
$startMorningHour = (clone $date )-> setTime ( $day -> getMorningStart ()-> format ( 'H' ), $day -> getMorningStart ()-> format ( 'i' ));
$endMorningHour = (clone $date )-> setTime ( $day -> getMorningEnd ()-> format ( 'H' ), $day -> getMorningEnd ()-> format ( 'i' ));
$startAfternoonHour = (clone $date )-> setTime ( $day -> getAfternoonStart ()-> format ( 'H' ), $day -> getAfternoonStart ()-> format ( 'i' ));
$endAfternoonHour = (clone $date )-> setTime ( $day -> getAfternoonEnd ()-> format ( 'H' ), $day -> getAfternoonEnd ()-> format ( 'i' ));
$startHour = max ( $now -> modify ( '+3 hours' ), $startMorningHour );
$period = new DatePeriod ( $startMorningHour , DateInterval :: createFromDateString ( $this -> slotLength . ' minutes' ), $endAfternoonHour );
foreach ($period as $dt ) {
if ($dt > (clone $endMorningHour )-> modify ( '-' . $this -> slotLength . ' minutes' ) && $dt < $startAfternoonHour ) {
continue;
}
$dtEnable = $dt >= $startHour && $this -> isAvailable ( $dt );
if ($deliveryNote && ! $this -> isBooked ( $dt , $deliveryNote ) && $deliveryNote -> getBooking () && $deliveryNote -> getBooking ()-> bookingDateTime ( $dt )) {
$dtEnable = true ;
}
$slots [] = array(
'datetime' => $dt ,
'enable' => $dtEnable
);
}
return new ArrayCollection ( $slots );
}
public function cleanBookings ()
{
$this -> em -> getRepository ( Booking ::class)-> createQueryBuilder ( 'b' )
->delete ()
->where ( 'b.confirmed = 0' )
->andWhere ( 'b.updatedAt < :datetime' )
->setParameter ( 'datetime' , (new DateTime ())-> modify ( '-30 minutes' ))
->getQuery ()-> getResult ();
}
public function isAvailable ( DateTimeInterface $dt ): bool
{
return !$this -> isBooked ( $dt ) && ! $this -> getExcludedSlotsOfDay ( $dt )-> contains ( $dt -> format ( DateTimeInterface :: ATOM ));
}
public function isBooked ( DateTimeInterface $dt , ? DeliveryNote $deliveryNote = null ): bool
{
$qb = $this -> em -> getRepository ( Booking ::class)-> createQueryBuilder ( 'b' )
->where ( 'b.date = :date' )
->andWhere ( 'b.time = :time' )
->andWhere ( 'b.bookingConfig = :bookingConfig' )
->setParameter ( 'date' , $dt -> format ( 'Y-m-d' ))
->setParameter ( 'time' , $dt -> format ( 'H:i:s' ))
->setParameter ( 'bookingConfig' , $this -> config );
if ($deliveryNote ) {
$qb -> andWhere ( 'b.deliveryNote != :deliveryNote' )
->setParameter ( 'deliveryNote' , $deliveryNote -> getId ());
}
return !empty($qb -> getQuery ()-> getResult ());
}
public function getExcludedSlotsOfDay ( DateTimeInterface $date = null ): ArrayCollection
{
$excludedSlots = new ArrayCollection ();
foreach ($this -> config -> getExcludeDates () as $excludedDate ) {
if ($excludedDate -> getDateEnd () && $excludedDate -> getDateStart ()-> format ( 'Y-m-d' ) == $excludedDate -> getDateEnd ()-> format ( 'Y-m-d' )) {
$period = new DatePeriod ( $excludedDate -> getDateStart (), DateInterval :: createFromDateString ( $this -> slotLength . ' minutes' ), $excludedDate -> getDateEnd ());
foreach ($period as $dt ) {
$excludedSlots -> add ( $dt -> format ( DateTimeInterface :: ATOM ));
}
}
}
if ($date ) {
foreach ($this -> config -> getExcludeSlots () as $excludedSlot ) {
if ($excludedSlot -> getDay () == $date -> format ( 'N' )) {
$timeStart = (clone $date )-> setTime ( $excludedSlot -> getTimeStart ()-> format ( 'H' ), $excludedSlot -> getTimeStart ()-> format ( 'i' ));
$timeEnd = (clone $date )-> setTime ( $excludedSlot -> getTimeEnd ()-> format ( 'H' ), $excludedSlot -> getTimeEnd ()-> format ( 'i' ));
$period = new DatePeriod ( $timeStart , DateInterval :: createFromDateString ( $this -> slotLength . ' minutes' ), $timeEnd );
foreach ($period as $dt ) {
$excludedSlots -> add ( $dt -> format ( DateTimeInterface :: ATOM ));
}
}
}
$period = new DatePeriod ( $this -> getClosestsSlot (new DateTime ()), DateInterval :: createFromDateString ( $this -> slotLength . ' minutes' ), (new DateTime ())-> modify ( '+3 hours' ));
foreach ($period as $dt ) {
$excludedSlots -> add ( $dt -> format ( DateTimeInterface :: ATOM ));
}
}
return $excludedSlots ;
}
public function getClosestsSlot ( DateTimeInterface $dt ): DateTimeInterface
{
$minutes = $dt -> format ( 'i' );
$dt -> setTime ( $dt -> format ( 'H' ), $minutes );
$minutes = $minutes - round ( $minutes / 10 ) * 10 ;
return $dt -> modify ( '-' . $minutes . ' minutes' );
}
/**
* @throws Exception
*/
public function getExcludedDates (? DeliveryNote $deliveryNote = null ): ArrayCollection
{
$excludedDates = new ArrayCollection ();
foreach ($this -> config -> getExcludeDates () as $excludedDate ) {
if (!$excludedDate -> getDateEnd ()) {
$excludedDates -> add ( $excludedDate -> getDateStart ()-> format ( DateTimeInterface :: ATOM ));
continue;
}
if ($excludedDate -> getDateStart ()-> format ( 'Y-m-d' ) == $excludedDate -> getDateEnd ()-> format ( 'Y-m-d' )) {
continue;
}
$period = new DatePeriod ( $excludedDate -> getDateStart (), DateInterval :: createFromDateString ( "1 day" ), $excludedDate -> getDateEnd ()-> modify ( '+1 day' ));
foreach ($period as $dt ) {
$excludedDates -> add ( $dt -> format ( DateTimeInterface :: ATOM ));
}
}
if (($firstSlot = new DateTime ( $this -> firstAvailableSlot ( $deliveryNote )))-> setTime ( 0 , 0 )-> format ( 'Y-m-d' ) != ( $now = new DateTime ())-> setTime ( 0 , 0 )-> format ( 'Y-m-d' )) {
$period = new DatePeriod ( $now , DateInterval :: createFromDateString ( "1 day" ), $firstSlot );
foreach ($period as $dt ) {
$excludedDates -> add ( $dt -> format ( DateTimeInterface :: ATOM ));
}
}
return $excludedDates ;
}
/**
* @throws Exception
*/
public function firstAvailableSlot (? DeliveryNote $deliveryNote = null ): ? string
{
$date = (new DateTime ())-> modify ( '+3 hours' );
if ($deliveryNote && $deliveryNote -> getBooking () && ! $deliveryNote -> getBooking ()-> isExpired ()) {
if ($deliveryNote -> getBooking ()-> isConfirmed ()) {
$date = $deliveryNote -> getBooking ()-> getSlot ();
}
if ($history = $deliveryNote -> getBooking ()-> getHistory ()) {
$date = new DateTime ( end ( $history ));
}
}
$periodStart = /*$date->format('Y-m-d') == (new DateTime())->format('Y-m-d') ? $date->modify('+3 hours') :*/
$date ;
$period = new DatePeriod ( $periodStart , DateInterval :: createFromDateString ( "1 day" ), (new DateTime ())-> modify ( '+1 year' ));
$excludedDates = $this -> config -> getExcludeDates ();
$excludedDates = $excludedDates -> filter (fn( BookingConfigDate $configDate ) => ! $configDate -> getDateEnd ())
->map (fn( BookingConfigDate $configDate ) => $configDate -> getDateStart ()-> format ( DateTimeInterface :: ATOM ));
foreach ($period as $dt ) {
$dt -> setTime ( 0 , 0 );
if ($excludedDates -> contains ( $dt -> format ( DateTimeInterface :: ATOM ))) {
continue;
}
$slots = $this -> getSlots ( $dt )-> filter (fn(array $slot ) => $slot [ 'enable' ] === true );
if (!$slots -> isEmpty ()) {
return $slots -> first ()[ 'datetime' ]-> format ( DateTimeInterface :: ATOM );
}
}
return null ;
}
public function getExcludedDays (): array
{
return array_diff ( array_keys ( BookingConfigHour :: DAYS_OF_WEEK ), $this -> days );
}
/**
* @param DeliveryNote $deliveryNote
* @return bool
* @throws GuzzleException
*/
public function canBook ( DeliveryNote $deliveryNote ): bool
{
if (!$this -> brandService -> getBrand ()-> getEnableLocationCheck ()) {
return true ;
}
if ($deliveryNote -> getBooking () && $deliveryNote -> getBooking ()-> isConfirmed ()) {
return $deliveryNote -> getBooking ()-> getDate ()-> format ( 'Y-m-d' ) >= (new DateTime ())-> format ( 'Y-m-d' );
}
$deliveryNoteItems = $this -> kheopsService -> getItems ( $deliveryNote -> getCode ());
$enable = false ;
foreach ($deliveryNoteItems as $item ) {
$matches = preg_match ( '/^A.*$/' , $item -> lieu );
if (!empty($matches )) {
$enable = true ;
break;
}
}
return $enable ;
}
/**
* @param DeliveryNote $deliveryNote
* @return bool
* @throws GuzzleException
*/
public function hasNoDeliveryBatch ( DeliveryNote $deliveryNote ): bool
{
if (!$this -> brandService -> getBrand ()-> getEnableLocationCheck ()) {
return false ;
}
$deliveryNoteItems = $this -> kheopsService -> getItems ( $deliveryNote -> getCode ());
$hasNoDeliveryBatch = false ;
foreach ($deliveryNoteItems as $item ) {
$matches = preg_match ( '/^A.*$/' , $item -> lieu );
if (empty($matches )) {
$hasNoDeliveryBatch = true ;
}
}
return $hasNoDeliveryBatch ;
}
}