src/Service/SlotService.php line 229

Open in your IDE?
  1. <?php
  2. namespace App\Service;
  3. use Throwable;
  4. use Exception;
  5. use App\Adapter\AppointmentAdapter;
  6. use App\Mapper\AppointmentMapper;
  7. use App\Model\Appointment;
  8. use App\Model\Slot;
  9. use App\Utils\Date;
  10. use App\Utils\Utils;
  11. use DateInterval;
  12. use DatePeriod;
  13. use DateTime;
  14. use Symfony\Component\HttpFoundation\Request;
  15. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  16. use Symfony\Component\Serializer\SerializerInterface;
  17. use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
  18. use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
  19. use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
  20. use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
  21. use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
  22. class SlotService extends AppointmentService
  23. {
  24.     private AppointmentService $appointmentService;
  25.     public function __construct(AppointmentAdapter  $adapter,
  26.                                 AppointmentMapper   $mapper,
  27.                                 ClientService       $clientService,
  28.                                 SerializerInterface $serializer,
  29.                                 AppointmentService  $appointmentService
  30.     )
  31.     {
  32.         parent::__construct($adapter$mapper$clientService$serializer);
  33.         $this->appointmentService $appointmentService;
  34.     }
  35.     /**
  36.      * @throws Throwable
  37.      * @throws TransportExceptionInterface
  38.      * @throws ServerExceptionInterface
  39.      * @throws RedirectionExceptionInterface
  40.      * @throws DecodingExceptionInterface
  41.      * @throws ClientExceptionInterface
  42.      */
  43.     public function getAvailability(array $dataAppointment $appointment): ?array
  44.     {
  45.         if (!isset($data['serviceIDs']) || !isset($data['garageID'])) {
  46.             throw new BadRequestHttpException('Bad request : serviceIDs or garageID are empty ');
  47.         }
  48.         $availabilities $this->adapter->getServiceAvailability($data);
  49.         $slots $this->getFormatedCalendarDate($availabilities);
  50.         $hours = [];
  51.         foreach ($slots as $day => $slot) {
  52.             $hourSlots $this->getHoursSlots($slots$day$appointment);
  53.             if (!empty($hourSlots)) {
  54.                 $hours[$day] = $hourSlots;
  55.             }
  56.         }
  57.         dump($hours);
  58.         return $hours;
  59.     }
  60.     /**
  61.      * @throws RedirectionExceptionInterface
  62.      * @throws DecodingExceptionInterface
  63.      * @throws ClientExceptionInterface
  64.      * @throws Throwable
  65.      * @throws TransportExceptionInterface
  66.      * @throws ServerExceptionInterface
  67.      */
  68.     public function getOtherAvailabilities(Appointment $appointment): ?array
  69.     {
  70.         $garages $this->getGarages();
  71.         $idCurrent $appointment->getGarage()->getId();
  72.         $otherGarages = [];
  73.         foreach ($garages as $garage) {
  74.             $gid $garage['id'];
  75.             if ($gid !== $idCurrent) {
  76.                 $data = [
  77.                     'serviceIDs' => implode(','$this->getServiceIds($appointment)),
  78.                     'garageID'   => $gid,
  79.                 ];
  80.                 $availabilities $this->getAvailability($data$appointment);
  81.                 if (!empty($availabilities)) {
  82.                     $garage['availabilities'] = $availabilities;
  83.                     $otherGarages[$garage['id']] = $garage;
  84.                 }
  85.             }
  86.         }
  87.         return $this->sortGaragesByAvailabilities($otherGarages);
  88.     }
  89.     /**
  90.      * Sort garages: put the garage with the closest availability in first.
  91.      */
  92.     public function sortGaragesByAvailabilities(array $garages): array
  93.     {
  94.         uasort($garages, function ($a$b) {
  95.             if (empty($a['availabilities']) || empty($b['availabilities'])) {
  96.                 return 0;
  97.             }
  98.             $datea array_keys($a['availabilities'])[0];
  99.             $dateb array_keys($b['availabilities'])[0];
  100.             return $datea <=> $dateb;
  101.         });
  102.         return $garages;
  103.     }
  104.     /**
  105.      * @return array
  106.      *
  107.      * @throws Exception
  108.      */
  109.     public function getDropPickUpSlot(Appointment $appointment, array $selectedDatebool $isReception true)
  110.     {
  111.         // reception slot
  112.         $data = [
  113.             'serviceIDs' => implode(','$this->getServiceIds($appointment)),
  114.             'garageID'   => $appointment->getGarage()->getId(),
  115.             'from' => $selectedDate['from'],
  116.             'to' => $selectedDate['to'],
  117.         ];
  118.         $slots $this->adapter->getDropPickupSlot($data$isReception);
  119.         $formatedSlots $this->getFormatedCalendarDate($slots);
  120.         $reception = [];
  121.         $day $selectedDate['day'];
  122.         if (key_exists($day$formatedSlots)) { // Get all slots time corresponding to the selected day
  123.             $times explode(' - '$selectedDate['hour']);
  124.             foreach ($formatedSlots[$day] as $hour) {
  125.                 if ($isReception) {
  126.                     if ($hour['end'] < $times[0]) {
  127.                         $reception[] = $hour;
  128.                     }
  129.                 } else {
  130.                     if ($hour['start'] > $times[1]) {
  131.                         $reception[] = $hour;
  132.                     }
  133.                 }
  134.             }
  135.         }
  136.         return $reception;
  137.     }
  138.     public function getFormatedCalendarDate(?array $availabilities): ?array
  139.     {
  140.         $slots array_map(
  141.             function ($value) {
  142.                 $date = [];
  143.                 $date['start'] = Utils::getFormatedDate($value['start']);
  144.                 $date['end'] = Utils::getFormatedDate($value['end']);
  145.                 return $date;
  146.             },
  147.             $availabilities
  148.         );
  149.         return Utils::getCalendarFormatedSlots($slots);
  150.     }
  151.     public function saveSlots(Appointment &$appointment, array $timeSlot, array $receptionSlot)
  152.     {
  153.         // slot
  154.         $slot = new Slot();
  155.         $this->hydrateSlot($slot$timeSlot['day'], $timeSlot['time']);
  156.         $appointment->setSlot($slot);
  157.         // reception slot
  158.         $this->setAppointmentDeliverPickSlot($receptionSlot$timeSlot$appointment);
  159.         // delivery slot
  160.         $this->setAppointmentDeliverPickSlot($receptionSlot$timeSlot$appointmentfalse);
  161.     }
  162.     protected function hydrateSlot(Slot $slotstring $day$sTimes)
  163.     {
  164.         $times explode(' - '$sTimes);
  165.         $startTime = new DateTime($day ' ' $times[0]);
  166.         $slot->setStart($startTime->getTimestamp());
  167.         if (count($times) > 1) {
  168.             $endTime = new DateTime($day ' ' $times[1]);
  169.             $slot->setEnd($endTime->getTimestamp());
  170.         }
  171.     }
  172.     public function handleRequest(Request $request, array $timeSlot, array $responseDatas): array
  173.     {
  174.         $receptionTime null;
  175.         $deliveryTime null;
  176.         $garageID null;
  177.         /** @var Appointment $appointment */
  178.         $session $request->getSession();
  179.         $appointment $session->get('appointment');
  180.         if ($appointment->getSlot()) { // update from resume
  181.             $garageID $appointment->getGarage()->getId();
  182.             $slot $appointment->getSlot();
  183.             $timeSlot['day'] = Date::getReadableDayFromSlot($slot);
  184.             $timeSlot['time'] = Date::getReadableTimeFromSlot($slot);
  185.             $receptionTime Date::getReadableTimeFromSlot($appointment->getReceptionSlot());
  186.             $deliveryTime Date::getReadableTimeFromSlot($appointment->getDeliverySlot());
  187.         }
  188.         if ($request->get('garageID')) {
  189.             $garageID $request->get('garageID');
  190.         }
  191.         $responseDatas array_merge([
  192.             'receptionTime' => [],
  193.             'deliveryTime'  => [],
  194.             'hours'         => [],
  195.         ], $responseDatas);
  196.         if ($garageID) { // on change garage
  197.             $responseDatas['day'] = $timeSlot['day'];
  198.             $responseDatas['time'] = $timeSlot['time'];
  199.             $this->appointmentService->changeGarage($garageID$session$responseDatas$this);
  200.         }
  201.         $this->appointmentService->getDatasFromServices($appointment$responseDatas);
  202. //        $otherGarages = $this->getOtherAvailabilities($appointment);
  203.         $otherGarages= [];
  204.         //for timeline
  205.         $serviceHeaderInfo $this->appointmentService->getServiceHeaderInfo($appointment);
  206.         return array_merge([
  207.             'otherSlots'            => $otherGarages,
  208.             'day'                   => $timeSlot['day'],
  209.             'time'                  => $timeSlot['time'],
  210.             'garages'               => array_values($otherGarages),
  211.             'current'               => $appointment->getGarage(),
  212.             'selectedReceptionTime' => $receptionTime,
  213.             'selectedDeliveryTime'  => $deliveryTime,
  214.             'garageID'              => $garageID,
  215.             'appointment'           => $appointment
  216.         ], $responseDatas);
  217.     }
  218.     /**
  219.      * @param array $slots
  220.      * @param array $timeSlot
  221.      * @param Appointment $appointment
  222.      * @param bool $isReception
  223.      */
  224.     public function setAppointmentDeliverPickSlot(array $slots, array $timeSlotAppointment $appointmentbool $isReception true)
  225.     {
  226.         $type $isReception 'reception' 'delivery';
  227.         $reception = new Slot();
  228.         if (!$slots[$type]) {
  229.             $times explode(' - '$timeSlot['time']);
  230.             $slots[$type] = $isReception $times[0] : $times[1];
  231.         }
  232.         $this->hydrateSlot($reception$timeSlot['day'], $slots[$type]);
  233.         $appointment->{'set' $type 'Slot'}($reception);
  234.     }
  235.     /**
  236.      * @param array $slots
  237.      * @param string $day
  238.      * @param Appointment $appointment
  239.      * @return array
  240.      * @throws Exception
  241.      */
  242.     public function getHoursSlots(array $slotsstring $dayAppointment $appointment): array
  243.     {
  244.         $duration $this->appointmentService->getTotalServiceDuration($appointment->getServices());
  245.         $hours = [];
  246.         foreach ($slots[$day] as $date) {
  247.             $start = new DateTime($date['start']);
  248.             $interval = new DateInterval('PT' $duration 'M');
  249.             $end = new DateTime($date['end']);
  250.             $period = new DatePeriod($start$interval$end);
  251.             foreach ($period as $item) {
  252.                 $hour_start $item->format('H:i');
  253.                 $hour_end $item->add($interval)->format('H:i');
  254.                 if (Date::isFutureDate($day ' ' $hour_start) && $hour_end <= $date['end']) {
  255.                     $hours[] = [
  256.                         'start' => $hour_start,
  257.                         'end'   => $hour_end
  258.                     ];
  259.                 }
  260.             }
  261.         }
  262.         return $hours;
  263.     }
  264. }