src/ApplicationBundle/Modules/BookingDemo/Controller/BookingDemoPublicController.php line 26

Open in your IDE?
  1. <?php
  2. namespace ApplicationBundle\Modules\BookingDemo\Controller;
  3. use ApplicationBundle\Controller\GenericController;
  4. use CompanyGroupBundle\Entity\DemoRequest;
  5. use CompanyGroupBundle\Entity\DemoRequestSlot;
  6. use Symfony\Component\HttpFoundation\JsonResponse;
  7. use Symfony\Component\HttpFoundation\Request;
  8. use Symfony\Component\HttpFoundation\Response;
  9. class BookingDemoPublicController extends GenericController
  10. {
  11.     private static $slotHours = [
  12.         '09:00''09:20''09:40',
  13.         '10:00''10:20''10:40',
  14.         '11:00''11:20''11:40',
  15.         '14:00''14:20''14:40',
  16.         '15:00''15:20''15:40',
  17.         '16:00''16:20''16:40',
  18.     ];
  19.     public function BookingPageAction(Request $request)
  20.     {
  21.         return $this->render('@BookingDemo/pages/book_demo.html.twig', [
  22.             'page_title' => 'Book a Demo — HoneyBee ERP',
  23.         ]);
  24.     }
  25.     public function GetAvailableSlotsAction(Request $request$date '')
  26.     {
  27.         if (!$date || !preg_match('/^\d{4}-\d{2}-\d{2}$/'$date)) {
  28.             return new JsonResponse(['success' => false'slots' => []]);
  29.         }
  30.         $em $this->getDoctrine()->getManager('company_group');
  31.         $dayStart = new \DateTime($date ' 00:00:00');
  32.         $dayEnd   = new \DateTime($date ' 23:59:59');
  33.         $confirmedSlots $em->getRepository('CompanyGroupBundle\Entity\DemoConfirmed')
  34.             ->createQueryBuilder('c')
  35.             ->where('c.confirmedStart >= :dayStart AND c.confirmedStart <= :dayEnd')
  36.             ->setParameter('dayStart'$dayStart)
  37.             ->setParameter('dayEnd'$dayEnd)
  38.             ->getQuery()
  39.             ->getResult();
  40.         $bookedTimes = [];
  41.         foreach ($confirmedSlots as $cs) {
  42.             $bookedTimes[] = $cs->getConfirmedStart()->format('H:i');
  43.         }
  44.         $now   = new \DateTime();
  45.         $slots = [];
  46.         foreach (self::$slotHours as $time) {
  47.             $slotDt = new \DateTime($date ' ' $time ':00');
  48.             if ($slotDt <= $now) continue;
  49.             $slots[] = [
  50.                 'time'      => $time,
  51.                 'available' => !in_array($time$bookedTimes),
  52.             ];
  53.         }
  54.         return new JsonResponse(['success' => true'slots' => $slots]);
  55.     }
  56.     public function SubmitBookingAction(Request $request)
  57.     {
  58.         if (!$request->isMethod('POST')) {
  59.             return $this->redirectToRoute('book_demo_page');
  60.         }
  61.         $name         trim($request->request->get('name'''));
  62.         $email        trim($request->request->get('email'''));
  63.         $phone        trim($request->request->get('phone'''));
  64.         $companyName  trim($request->request->get('company_name'''));
  65.         $businessType trim($request->request->get('business_type'''));
  66.         $slots        $request->request->get('slots', []);
  67.         if (!$name || !filter_var($emailFILTER_VALIDATE_EMAIL) || empty($slots)) {
  68.             return new JsonResponse(['success' => false'message' => 'Please fill all required fields and select at least one slot.']);
  69.         }
  70.         $em $this->getDoctrine()->getManager('company_group');
  71.         $demoRequest = new DemoRequest();
  72.         $demoRequest->setName($name)
  73.             ->setEmail($email)
  74.             ->setPhone($phone)
  75.             ->setCompanyName($companyName)
  76.             ->setBusinessType($businessType)
  77.             ->setStatus('pending')
  78.             ->setMeetingToken(bin2hex(random_bytes(24)));
  79.         $em->persist($demoRequest);
  80.         $em->flush();
  81.         $priority 1;
  82.         foreach (array_slice($slots03) as $slotStr) {
  83.             $parts explode('|'$slotStr);
  84.             if (count($parts) !== 2) continue;
  85.             [$dateStr$timeStr] = $parts;
  86.             if (!preg_match('/^\d{4}-\d{2}-\d{2}$/'$dateStr)) continue;
  87.             if (!preg_match('/^\d{2}:\d{2}$/'$timeStr)) continue;
  88.             $start = new \DateTime($dateStr ' ' $timeStr ':00');
  89.             $end   = clone $start;
  90.             $end->modify('+20 minutes');
  91.             $slot = new DemoRequestSlot();
  92.             $slot->setRequestId($demoRequest->getId())
  93.                 ->setStartTime($start)
  94.                 ->setEndTime($end)
  95.                 ->setPriorityOrder($priority++);
  96.             $em->persist($slot);
  97.         }
  98.         $em->flush();
  99.         $this->sendPendingEmails($demoRequest$em);
  100.         $this->get('app.commercial_journey_service')->captureExistingObject('demo'$demoRequest'demo_booking');
  101.         return new JsonResponse([
  102.             'success' => true,
  103.             'message' => 'Your demo request has been submitted! We will confirm shortly.',
  104.         ]);
  105.     }
  106.     public function MeetingPageAction(Request $request$token '')
  107.     {
  108.         if (!$token) {
  109.             throw $this->createNotFoundException('Invalid meeting link.');
  110.         }
  111.         $em $this->getDoctrine()->getManager('company_group');
  112.         $demoRequest $em->getRepository('CompanyGroupBundle\Entity\DemoRequest')
  113.             ->findOneBy(['meetingToken' => $token'status' => 'confirmed']);
  114.         if (!$demoRequest) {
  115.             throw $this->createNotFoundException('Meeting not found or not yet confirmed.');
  116.         }
  117.         $confirmed $em->getRepository('CompanyGroupBundle\Entity\DemoConfirmed')
  118.             ->findOneBy(['requestId' => $demoRequest->getId()]);
  119.         if (!$confirmed) {
  120.             throw $this->createNotFoundException('Confirmed meeting details not found.');
  121.         }
  122.         $now   = new \DateTime();
  123.         $start $confirmed->getConfirmedStart();
  124.         $end   $confirmed->getConfirmedEnd();
  125.         $phase 'upcoming';
  126.         if ($now >= $start && $now <= $end) {
  127.             $phase 'live';
  128.         } elseif ($now $end) {
  129.             $phase 'expired';
  130.         }
  131.         return $this->render('@BookingDemo/pages/meeting.html.twig', [
  132.             'page_title'  => 'HoneyBee ERP Demo Meeting',
  133.             'demoRequest' => $demoRequest,
  134.             'confirmed'   => $confirmed,
  135.             'phase'       => $phase,
  136.             'startTs'     => $start->getTimestamp() * 1000,
  137.             'endTs'       => $end->getTimestamp() * 1000,
  138.         ]);
  139.     }
  140.     private function getAdminEmails(): array
  141.     {
  142.         $default = ['emrul.hasan@ourhoneybee.eu''mozibul.yasser@ourhoneybee.eu'];
  143.         try {
  144.             $raw $this->getParameter('demo_admin_emails');
  145.             if (!$raw) return $default;
  146.             $parsed array_filter(array_map('trim'explode(','$raw)));
  147.             return $parsed ?: $default;
  148.         } catch (\Exception $e) {
  149.             return $default;
  150.         }
  151.     }
  152.     private function smtpBase(): array
  153.     {
  154.         try {
  155.             return [
  156.                 'senderHash' => '_CUSTOM_',
  157.                 'smtpServer' => $this->getParameter('mailer_host'),
  158.                 'smtpPort'   => (int) $this->getParameter('mailer_port'),
  159.                 'userName'   => $this->getParameter('mailer_user'),
  160.                 'password'   => $this->getParameter('mailer_password'),
  161.                 'fromAddress'=> $this->getParameter('mailer_user'),
  162.             ];
  163.         } catch (\Exception $e) {
  164.             return ['senderHash' => '_DEFAULT_'];
  165.         }
  166.     }
  167.     private function sendPendingEmails(DemoRequest $demoRequest$em)
  168.     {
  169.         try {
  170.             $mailModule $this->get('mail_module');
  171.             $smtp       $this->smtpBase();
  172.             $mailModule->sendMyMail(array_merge($smtp, [
  173.                 'toAddress'    => $demoRequest->getEmail(),
  174.                 'subject'      => 'Your HoneyBee ERP Demo Request — Pending Confirmation',
  175.                 'mailTemplate' => '@BookingDemo/email/booking_pending_user.html.twig',
  176.                 'templateData' => [
  177.                     'name'        => $demoRequest->getName(),
  178.                     'companyName' => $demoRequest->getCompanyName() ?: '',
  179.                 ],
  180.             ]));
  181.             $subject      'New Demo Request — ' $demoRequest->getName() . ' (' . ($demoRequest->getCompanyName() ?: 'N/A') . ')';
  182.             $templateData = [
  183.                 'demoRequest' => [
  184.                     'id'           => $demoRequest->getId(),
  185.                     'name'         => $demoRequest->getName(),
  186.                     'email'        => $demoRequest->getEmail(),
  187.                     'phone'        => $demoRequest->getPhone() ?: '',
  188.                     'companyName'  => $demoRequest->getCompanyName() ?: '',
  189.                     'businessType' => $demoRequest->getBusinessType() ?: '',
  190.                 ],
  191.             ];
  192.             foreach ($this->getAdminEmails() as $adminEmail) {
  193.                 $mailModule->sendMyMail(array_merge($smtp, [
  194.                     'toAddress'    => $adminEmail,
  195.                     'subject'      => $subject,
  196.                     'mailTemplate' => '@BookingDemo/email/booking_pending_admin.html.twig',
  197.                     'templateData' => $templateData,
  198.                 ]));
  199.             }
  200.         } catch (\Exception $e) {
  201.             // Email failure must not break the booking flow
  202.         }
  203.     }
  204. }