src/Controller/HomeController.php line 382

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Configuration;
  4. use App\Entity\Space;
  5. use App\Entity\User;
  6. use App\Entity\WidgetNotes;
  7. use App\Entity\HtFile;
  8. use App\MDS\AvexpressBundle\Entity\AveFiles;
  9. use App\Form\WidgetNotesType;
  10. use App\MDS\VenuesBundle\Entity\Reservation;
  11. use App\MDS\VenuesBundle\Entity\ReservationLoungeDetails;
  12. use App\MDS\VenuesBundle\Entity\ReservationLoungeSimple;
  13. use App\MDS\VenuesBundle\Entity\ReservationVisit;
  14. use App\Service\CalendarService;
  15. use App\Service\UserNotificationService;
  16. use Doctrine\ORM\EntityManagerInterface;
  17. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  18. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  19. use Symfony\Component\Routing\Annotation\Route;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\HttpFoundation\Response;
  22. use Symfony\Component\HttpFoundation\Session\Session;
  23. use Symfony\Component\HttpFoundation\JsonResponse;
  24. use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
  25. use Symfony\Contracts\Translation\TranslatorInterface;
  26. use Google_Client;
  27. use Google_Service_Calendar;
  28. use Doctrine\ORM\Query;
  29. class HomeController extends AbstractController
  30. {
  31.     private $googleCalendar;
  32.     private $translator;
  33.     private $userNotificationService;
  34.     private SessionInterface $session;
  35.     public function __construct(TranslatorInterface $translatorUserNotificationService $userNotificationServiceSessionInterface $session)
  36.     {
  37.         $redirectUri 'https://' . ($_SERVER['HTTP_HOST'] ?? '') . '/calendar/token';
  38.         $client = new Google_Client();
  39.         $client->setApplicationName('Google Calendar API');
  40.         $client->setClientId('YOUR_GOOGLE_CLIENT_ID');
  41.         $client->setClientSecret('YOUR_GOOGLE_CLIENT_SECRET');
  42.         $client->setRedirectUri($redirectUri);
  43.         $client->addScope(Google_Service_Calendar::CALENDAR);
  44.         $guzzle = new \GuzzleHttp\Client(['curl' => [CURLOPT_SSL_VERIFYPEER => false]]);
  45.         $client->setHttpClient($guzzle);
  46.         $this->googleCalendar $client;
  47.         $this->translator $translator;
  48.         $this->userNotificationService $userNotificationService;
  49.         $this->session $session;
  50.     }
  51.     /**
  52.      * Portal principal con los 3 accesos (ManteVenues, ManteCatering, ManteAV)
  53.      * @Route("/inicio", name="ruta_inicio")
  54.      */
  55.     public function inicioAction(AuthenticationUtils $authenticationUtilsEntityManagerInterface $em): Response
  56.     {
  57.         $configuration $em->getRepository(Configuration::class)->findOneBy([]);
  58.         return $this->render('login/login.html.twig', [
  59.             'last_username' => $authenticationUtils->getLastUsername(),
  60.             'error' => $authenticationUtils->getLastAuthenticationError(),
  61.             'configuration' => $configuration,
  62.         ]);
  63.     }
  64.     /**
  65.      * @Route("/", name="homepage")
  66.      */
  67.     public function index(EntityManagerInterface $emRequest $request): Response
  68.     {
  69.         $user $this->getUser();
  70.         if (!$user) {
  71.             return $this->redirectToRoute('ruta_inicio');
  72.         }
  73.         // Recuperamos el tipo de acceso actual (Venues, Catering o AV) de la sesión
  74.         $accessType $this->session->get('current_access_type') ?? 'venues';
  75.         $tz = new \DateTimeZone('Europe/Madrid');
  76.         $from = (new \DateTimeImmutable('today'$tz))->setTime(000);
  77.         $to $from->setTime(235959);
  78.         $agendaMix = [];
  79.         $formattedReservations = [];
  80.         $formattedVisits = [];
  81.         if ($accessType === 'venues') {
  82.             // 1. FILTRADO POR EQUIPO "LEGENDS VIEW"
  83.             $isLegendTeam = (strtoupper(trim($user->getTeam() ?? '')) === 'LEGENDS VIEW');
  84.             $lSpace null;
  85.             if ($isLegendTeam) {
  86.                 $lSpace $em->getRepository(Space::class)->createQueryBuilder('s')
  87.                     ->where('s.name LIKE :n')->setParameter('n''%LEGEND%')
  88.                     ->setMaxResults(1)->getQuery()->getOneOrNullResult();
  89.             }
  90.             /** --- LÓGICA Módulo VENUES (Reservas y Visitas) --- */
  91.             $qbR $em->createQueryBuilder()
  92.                 ->select('r.id''r.title''r.dateStart''r.dateEnd''lounge.name as loungeName''rls.type')
  93.                 ->from(Reservation::class, 'r')
  94.                 ->leftJoin(ReservationLoungeSimple::class, 'rls''WITH''rls.idReservation = r.id')
  95.                 ->leftJoin(ReservationLoungeDetails::class, 'lounge''WITH''lounge.id = rls.idLounge')
  96.                 ->where('r.dateStart <= :to AND COALESCE(r.dateEnd, r.dateStart) >= :from')
  97.                 ->andWhere('r.status <> :deleted')
  98.                 ->setParameter('from'$from)
  99.                 ->setParameter('to'$to)
  100.                 ->setParameter('deleted''Deleted')
  101.                 ->orderBy('r.dateStart''ASC');
  102.             if ($isLegendTeam && $lSpace) {
  103.                 $qbR->andWhere('lounge.space = :sid')->setParameter('sid'$lSpace->getId());
  104.             }
  105.             $rawRows $qbR->getQuery()->getArrayResult();
  106.             $reservationsMap = [];
  107.             foreach ($rawRows as $row) {
  108.                 $id $row['id'];
  109.                 $type $row['type'];
  110.                 $key $id . ($type '_' $type '');
  111.                 if (!isset($reservationsMap[$key])) {
  112.                     $prefix $type '[' strtoupper($type) . '] ' '';
  113.                     $reservationsMap[$key] = [
  114.                         'id' => $id,
  115.                         'title' => $prefix . ($row['title'] ?? 'Reserva'),
  116.                         'dateStart' => $row['dateStart'],
  117.                         'rooms' => [],
  118.                         'tipo' => 'RESERVA',
  119.                         // URL específica de Venues
  120.                         'url' => $this->generateUrl('reservations_venues_edit_simple', ['id' => $id])
  121.                     ];
  122.                 }
  123.                 if ($row['loungeName']) {
  124.                     $reservationsMap[$key]['rooms'][] = $row['loungeName'];
  125.                 }
  126.             }
  127.             foreach ($reservationsMap as $res) {
  128.                 $res['room'] = implode(', 'array_unique($res['rooms']));
  129.                 $formattedReservations[] = $res;
  130.             }
  131.             // VISITAS
  132.             $qbV $em->getRepository(ReservationVisit::class)->createQueryBuilder('v')
  133.                 ->where('v.dateStart <= :to AND COALESCE(v.dateEnd, v.dateStart) >= :from')
  134.                 ->setParameter('from'$from)
  135.                 ->setParameter('to'$to)
  136.                 ->orderBy('v.dateStart''ASC');
  137.             if ($isLegendTeam && $lSpace) {
  138.                 $qbV->andWhere('v.space = :sid')->setParameter('sid'$lSpace->getId());
  139.             }
  140.             $visitEntities $qbV->getQuery()->getResult();
  141.             $loungeRepo $em->getRepository(ReservationLoungeDetails::class);
  142.             foreach ($visitEntities as $visit) {
  143.                 $lName '-';
  144.                 if ($visit->getIdLoungeDetails()) {
  145.                     $lounge $loungeRepo->find($visit->getIdLoungeDetails());
  146.                     $lName $lounge $lounge->getName() : '-';
  147.                 }
  148.                 $formattedVisits[] = [
  149.                     'id' => $visit->getId(),
  150.                     'title' => ($visit->getTitle() ?? 'Sin título'),
  151.                     'dateStart' => $visit->getDateStart(),
  152.                     'room' => $lName,
  153.                     'tipo' => 'VISITA',
  154.                     // También enviamos la URL correcta para las visitas
  155.                     'url' => $this->generateUrl('venues_edit_visit', ['id' => $visit->getId()])
  156.                 ];
  157.             }
  158.             $agendaMix array_merge($formattedReservations$formattedVisits);
  159.             usort($agendaMix, fn ($a$b) => $a['dateStart'] <=> $b['dateStart']);
  160.         } else if ($accessType === 'catering') {
  161.             /** --- LÓGICA Módulo CATERING (Higo & Trigo + Montajes Venues) --- */
  162.             // 1. Eventos de Catering
  163.             $htFiles $em->getRepository(HtFile::class)->createQueryBuilder('h')
  164.                 ->where('h.dateStart <= :to AND COALESCE(h.dateEnd, h.dateStart) >= :from')
  165.                 ->setParameter('from'$from)
  166.                 ->setParameter('to'$to)
  167.                 ->orderBy('h.dateStart''ASC')
  168.                 ->getQuery()->getResult();
  169.             $htEventsFormatted = [];
  170.             foreach ($htFiles as $ht) {
  171.                 $htEventsFormatted[] = [
  172.                     'id' => $ht->getId(),
  173.                     'title' => '[CATERING] ' . ($ht->getTitle() ?? 'Sin título'),
  174.                     'dateStart' => $ht->getDateStart(),
  175.                     'room' => 'Servicio Catering',
  176.                     'tipo' => 'RESERVA',
  177.                     // URL específica de Catering
  178.                     'url' => $this->generateUrl('app_ht_file_edit', ['id' => $ht->getId()])
  179.                 ];
  180.             }
  181.             // 2. Montajes/Desmontajes de Venues para Catering
  182.             $qbM $em->createQueryBuilder()
  183.                 ->select('r.id''r.title''r.dateStart''lounge.name as loungeName''rls.type')
  184.                 ->from(Reservation::class, 'r')
  185.                 ->leftJoin(ReservationLoungeSimple::class, 'rls''WITH''rls.idReservation = r.id')
  186.                 ->leftJoin(ReservationLoungeDetails::class, 'lounge''WITH''lounge.id = rls.idLounge')
  187.                 ->where('r.dateStart <= :to AND COALESCE(r.dateEnd, r.dateStart) >= :from')
  188.                 ->andWhere('rls.type IN (:types)')
  189.                 ->andWhere('r.status <> :deleted')
  190.                 ->setParameter('from'$from)
  191.                 ->setParameter('to'$to)
  192.                 ->setParameter('types', ['montaje''desmontaje'])
  193.                 ->setParameter('deleted''Deleted');
  194.             $venueRows $qbM->getQuery()->getArrayResult();
  195.             $venueEventsFormatted = [];
  196.             foreach ($venueRows as $row) {
  197.                 $venueEventsFormatted[] = [
  198.                     'id' => $row['id'],
  199.                     'title' => '[' strtoupper($row['type'] ?? 'TRABAJO') . '] ' . ($row['title'] ?? 'Reserva'),
  200.                     'dateStart' => $row['dateStart'],
  201.                     'room' => $row['loungeName'] ?? '-',
  202.                     'tipo' => 'RESERVA',
  203.                     // Mantenemos la ruta de Venues para montajes de salas
  204.                     'url' => $this->generateUrl('reservations_venues_edit_simple', ['id' => $row['id']])
  205.                 ];
  206.             }
  207.             $agendaMix array_merge($htEventsFormatted$venueEventsFormatted);
  208.             usort($agendaMix, fn ($a$b) => $a['dateStart'] <=> $b['dateStart']);
  209.             $formattedReservations $agendaMix;
  210.         } else if ($accessType === 'av') {
  211.             /** --- LÓGICA Módulo AV (Audiovisuales) --- */
  212.             $avFiles $em->getRepository(AveFiles::class)->createQueryBuilder('a')
  213.                 ->where('a.dateStart <= :to AND COALESCE(a.dateEnd, a.dateStart) >= :from')
  214.                 ->andWhere('a.status <> :deleted')
  215.                 ->setParameter('from'$from)
  216.                 ->setParameter('to'$to)
  217.                 ->setParameter('deleted''Deleted')
  218.                 ->orderBy('a.dateStart''ASC')
  219.                 ->getQuery()->getResult();
  220.             foreach ($avFiles as $av) {
  221.                 $formattedReservations[] = [
  222.                     'id' => $av->getId(),
  223.                     'title' => $av->getTitle() ?? 'Servicio AV',
  224.                     'dateStart' => $av->getDateStart(),
  225.                     'room' => 'Equipos AV',
  226.                     'tipo' => 'RESERVA',
  227.                     // URL específica de AV (Verifica que el nombre de ruta sea exacto el de tu controlador AV)
  228.                     'url' => $this->generateUrl('ave_edit_file', ['id' => $av->getId()])
  229.                 ];
  230.             }
  231.             $agendaMix $formattedReservations;
  232.         }
  233.         $this->userNotificationService->checkRecentNotifications($user);
  234.         return $this->render('home/index.html.twig', [
  235.             'accessType'           => $accessType,
  236.             'agenda'               => $agendaMix,
  237.             'upcomingReservations' => $formattedReservations,
  238.             'upcomingVisits'       => $formattedVisits,
  239.             'notifications'        => $this->userNotificationService->getForModal($user)
  240.         ]);
  241.     }
  242.     /**
  243.      * @Route("/calendar/catering/menu-testings", name="calendar_catering_menu_testings", methods={"GET"})
  244.      */
  245.     public function calendarCateringMenuTestings(Request $requestCalendarService $calendar): JsonResponse
  246.     {
  247.         $fromParam $request->query->get('start''first day of this month');
  248.         $toParam $request->query->get('end''last day of next month');
  249.         try {
  250.             $from = new \DateTimeImmutable($fromParam);
  251.             $to = new \DateTimeImmutable($toParam);
  252.         } catch (\Exception $e) {
  253.             return new JsonResponse(['error' => 'Formato de fecha inválido'], 400);
  254.         }
  255.         // Llamamos al método renombrado
  256.         return new JsonResponse($calendar->getMenuTestingsForCalendar($from$to));
  257.     }
  258.     /**
  259.      * @Route("/calendar/global/visits", name="calendar_global_visits", methods={"GET"})
  260.      */
  261.     public function globalVisits(Request $requestCalendarService $calendarEntityManagerInterface $em): JsonResponse
  262.     {
  263.         $user $this->getUser();
  264.         $spaceIds null;
  265.         if ($user && strtoupper(trim($user->getTeam() ?? '')) === 'LEGENDS VIEW') {
  266.             // Buscamos todos los espacios cuyo nombre sea o contenga 'LEGENDS VIEW'
  267.             $spaces $em->getRepository(Space::class)->createQueryBuilder('s')
  268.                 ->where('s.name LIKE :n')
  269.                 ->setParameter('n''%ESPACIO LEGENDS%')
  270.                 ->getQuery()
  271.                 ->getResult();
  272.             if (!empty($spaces)) {
  273.                 $spaceIds array_map(fn($s) => $s->getId(), $spaces);
  274.             } else {
  275.                 // Seguridad: Si no encuentra el espacio, ID inexistente para que no vea nada por error
  276.                 $spaceIds = [99999];
  277.             }
  278.         }
  279.         $from = new \DateTime($request->query->get('start'));
  280.         $to = new \DateTime($request->query->get('end'));
  281.         return new JsonResponse($calendar->getVisitsForCalendar($spaceIdsnull$from$to));
  282.     }
  283.     /**
  284.      * @Route("/calendar/global/reservations", name="calendar_global_reservations", methods={"GET"})
  285.      */
  286.     public function globalReservations(Request $requestCalendarService $calendarEntityManagerInterface $em): JsonResponse
  287.     {
  288.         $user $this->getUser();
  289.         $spaceId null;
  290.         if ($user && strtoupper(trim($user->getTeam() ?? '')) === 'LEGENDS VIEW') {
  291.             $lSpace $em->getRepository(Space::class)->createQueryBuilder('s')
  292.                 ->where('s.name LIKE :n')
  293.                 ->setParameter('n''%LEGEND%')
  294.                 ->setMaxResults(1)
  295.                 ->getQuery()
  296.                 ->getOneOrNullResult();
  297.             $spaceId $lSpace?->getId();
  298.         }
  299.         $from = new \DateTime($request->query->get('start'));
  300.         $to = new \DateTime($request->query->get('end'));
  301.         return new JsonResponse($calendar->getReservationsForCalendar($spaceIdnull$from$to));
  302.     }
  303.     /**
  304.      * Endpoint específico para que el perfil de Catering vea solo montajes y desmontajes.
  305.      * * @Route("/calendar/catering/reservations", name="calendar_catering_reservations", methods={"GET"})
  306.      */
  307.     public function cateringReservations(Request $requestCalendarService $calendar): JsonResponse
  308.     {
  309.         // Validamos las fechas de entrada que envía FullCalendar
  310.         $startParam $request->query->get('start');
  311.         $endParam $request->query->get('end');
  312.         if (!$startParam || !$endParam) {
  313.             return new JsonResponse(['error' => 'Missing date parameters'], 400);
  314.         }
  315.         try {
  316.             $from = new \DateTime($startParam);
  317.             $to = new \DateTime($endParam);
  318.         } catch (\Exception $e) {
  319.             return new JsonResponse(['error' => 'Invalid date format'], 400);
  320.         }
  321.         // Llamamos al nuevo método específico del servicio
  322.         $events $calendar->getCateringSetupsForCalendar($from$to);
  323.         return new JsonResponse($events);
  324.     }
  325.     /**
  326.      * @Route("/calendar/ht/events", name="calendar_ht_events", methods={"GET"})
  327.      */
  328.     public function calendarHtEvents(Request $requestCalendarService $calendar): JsonResponse
  329.     {
  330.         $from = new \DateTimeImmutable($request->query->get('start''first day of this month'));
  331.         $to = new \DateTimeImmutable($request->query->get('end''last day of next month'));
  332.         return new JsonResponse($calendar->getHtEvents($from$to));
  333.     }
  334.     /**
  335.      * @Route("/calendar/av/events", name="calendar_av_events", methods={"GET"})
  336.      */
  337.     public function calendarAvEvents(Request $requestCalendarService $calendar): JsonResponse
  338.     {
  339.         $from = new \DateTimeImmutable($request->query->get('start''first day of this month'));
  340.         $to = new \DateTimeImmutable($request->query->get('end''last day of next month'));
  341.         // 1. Sacamos los eventos propios de Audiovisuales
  342.         $avEvents $calendar->getAvEvents($from$to'av');
  343.         // 2. Sacamos los montajes y desmontajes asociados a Audiovisuales
  344.         $avSetups $calendar->getAvSetupsForCalendar($from$to'av');
  345.         // 3. Los unimos en un solo array
  346.         $allEvents array_merge($avEvents$avSetups);
  347.         return new JsonResponse($allEvents);
  348.     }
  349.     /**
  350.      * @Route("/ChangeLanguage/{lang}", name="change_language")
  351.      */
  352.     public function changeLanguage(Request $requeststring $lang): Response
  353.     {
  354.         $this->translator->setLocale($lang);
  355.         $request->getSession()->set('_locale'$lang);
  356.         return $this->redirect($request->headers->get('referer'));
  357.     }
  358.     /**
  359.      * @Route("/calendar-full", name="calendar_full")
  360.      */
  361.     public function calendarFull(Request $request): Response
  362.     {
  363.         $token $request->request->get('token');
  364.         $em $this->getDoctrine()->getManager();
  365.         $user $em->getRepository(User::class)->findOneByAccessKey($token);
  366.         if (!$user)
  367.             return $this->redirectToRoute('ruta_inicio');
  368.         $userId $user->getId();
  369.         $wnotes = new WidgetNotes();
  370.         $wnotes->setDateAt(new \DateTime());
  371.         $form $this->createForm(WidgetNotesType::class, $wnotes, [
  372.             'action' => $this->generateUrl('widget_notes_create'),
  373.             'method' => 'POST',
  374.         ]);
  375.         return $this->render('home/calendar-fullscreen.html.twig', [
  376.             'form' => $form->createView(),
  377.             'user' => $userId,
  378.             'token' => $token,
  379.         ]);
  380.     }
  381.     /**
  382.      * @Route("/external/calendar-reservation", name="calendar_external_reservation")
  383.      */
  384.     public function externalCalendar(): Response
  385.     {
  386.         return $this->render('home/calendar-reservation.html.twig');
  387.     }
  388. }