src/MDS/VenuesBundle/Controller/ReservationsController.php line 3002

Open in your IDE?
  1. <?php
  2. namespace App\MDS\VenuesBundle\Controller;
  3. use App\Constants\BusinessTypeSettingsCompanyConstants;
  4. use App\Constants\LanguageConstants;
  5. use App\DTO\SyncronizationsAVDTO;
  6. use App\DTO\SyncronizationsCateringDTO;
  7. use App\Entity\DocContract;
  8. use App\MDS\VenuesBundle\Entity\ReservationTracing;
  9. use App\Entity\DocContractModel;
  10. use App\Entity\Client;
  11. use App\Entity\ClientContact;
  12. use App\Entity\InvoiceProformaExtraField;
  13. use App\Entity\Space;
  14. use App\Entity\Supplier;
  15. use App\Entity\User;
  16. use App\Entity\HtFile;
  17. use App\Entity\ReservationLoungeWebDescription;
  18. use App\Entity\SageArticle;
  19. use App\Entity\SageVatRates;
  20. use App\Entity\SettingsCompany;
  21. use App\Entity\WidgetNotes;
  22. use App\Form\InvoiceProformaExtraFieldType;
  23. use App\Form\WidgetNotesType;
  24. use App\MDS\AvexpressBundle\Entity\AveFiles;
  25. use App\MDS\VenuesBundle\Entity\ReservationVisit;
  26. use App\MDS\VenuesBundle\Entity\Reservation;
  27. use App\MDS\VenuesBundle\Entity\ReservationDeposit;
  28. use App\MDS\VenuesBundle\Entity\ReservationLounge;
  29. use App\MDS\VenuesBundle\Entity\ReservationLoungeDescription;
  30. use App\MDS\VenuesBundle\Entity\ReservationLoungeDetails;
  31. use App\MDS\VenuesBundle\Entity\ReservationLoungePicture;
  32. use App\MDS\VenuesBundle\Entity\ReservationLoungeProfile;
  33. use App\MDS\VenuesBundle\Entity\ReservationLoungeSimple;
  34. use App\MDS\VenuesBundle\Entity\ReservationLoungeVideo;
  35. use App\MDS\VenuesBundle\Entity\ReservationMailAlertClient;
  36. use App\MDS\VenuesBundle\Entity\ReservationPeriod;
  37. use App\MDS\VenuesBundle\Entity\ReservationService;
  38. use App\MDS\VenuesBundle\Entity\ReservationAlertStarted;
  39. use App\MDS\VenuesBundle\Entity\ReservationAlertSecondDeposit;
  40. use App\MDS\VenuesBundle\Entity\ReservationInvoice;
  41. use App\MDS\VenuesBundle\Entity\ReservationInvoiceItems;
  42. use App\MDS\VenuesBundle\Entity\ReservationInvoiceRec;
  43. use App\MDS\VenuesBundle\Entity\ReservationPaymentsClient;
  44. use App\MDS\VenuesBundle\Entity\ReservationProforma;
  45. use App\MDS\VenuesBundle\Form\ReservationLoungeDetailsType;
  46. use App\MDS\VenuesBundle\Form\ReservationLoungeProfileType;
  47. use App\MDS\VenuesBundle\Form\ReservationLoungeType;
  48. use App\MDS\VenuesBundle\Form\ReservationPeriodType;
  49. use App\MDS\VenuesBundle\Form\ReservationType;
  50. use App\MDS\VenuesBundle\Form\VisitEditType;
  51. use App\Service\CalendarService;
  52. use App\Service\ReservationService as ReservationServiceAlias;
  53. use App\Service\SincGpHtAvService;
  54. use Symfony\Component\Routing\Annotation\Route;
  55. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  56. use Symfony\Component\HttpFoundation\Request;
  57. use Symfony\Component\HttpFoundation\Session\Session;
  58. use Symfony\Component\HttpFoundation\JsonResponse;
  59. use Symfony\Component\HttpFoundation\Response;
  60. use App\Service\DocContractService;
  61. use App\Service\SyncronizationsAVService;
  62. use App\Service\SyncronizationsCateringService;
  63. use Google_Client;
  64. use Google_Service_Calendar;
  65. use Psr\Log\LoggerInterface;
  66. use DateTime;
  67. use DatePeriod;
  68. use DateInterval;
  69. use Symfony\Contracts\Translation\TranslatorInterface;
  70. use Doctrine\ORM\EntityManagerInterface;
  71. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  72. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  73. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  74. use Symfony\Component\Security\Core\Security;
  75. use Symfony\Component\Serializer\SerializerInterface;
  76. use App\Service\AgendaService;
  77. use App\MDS\VenuesBundle\Repository\ReservationAgendaItemRepository;
  78. use App\MDS\VenuesBundle\Entity\ReservationAgendaItem;
  79. use App\Service\AppConfigManager;
  80. use App\Settings\AppConfig\ReservationWorkflowMode;
  81. use App\Service\VenueService;
  82. class ReservationsController extends AbstractController
  83. {
  84.     private $translator;
  85.     protected $googleCalendar;
  86.     private $docContractService;
  87.     private $em;
  88.     private $session;
  89.     private $syncronizationsCateringService;
  90.     private $syncronizationsAVService;
  91.     private $agendaService;
  92.     private ReservationServiceAlias $reservationService;
  93.     public function __construct(
  94.         TranslatorInterface $translator,
  95.         DocContractService $docContractService,
  96.         EntityManagerInterface $em,
  97.         SessionInterface $session,
  98.         SyncronizationsCateringService $syncronizationsCateringService,
  99.         SyncronizationsAVService $syncronizationsAVService,
  100.         AgendaService $agendaService,
  101.         VenueService $venueService,
  102.         ReservationAgendaItemRepository $repository,
  103.         ReservationServiceAlias $reservationService,
  104.         SincGpHtAvService $sincGpHtAvService
  105.     ) {
  106.         $redirect_uri 'https://' $_SERVER['HTTP_HOST'] . '/calendar/token';
  107.         $googleCalendar = new Google_Client();
  108.         $googleCalendar->setApplicationName('Google Calendar API PHP Quickstart');
  109.         $googleCalendar->setClientId('2790497987-57qc3vu4pr7vb0s8phpub2me58pe34lb.apps.googleusercontent.com');
  110.         $googleCalendar->setClientSecret('nj2C7unaTO68DRhyORsyipSj');
  111.         $googleCalendar->setRedirectUri($redirect_uri);
  112.         $googleCalendar->addScope(Google_Service_Calendar::CALENDAR);
  113.         $guzzleClient = new \GuzzleHttp\Client(['curl' => [CURLOPT_SSL_VERIFYPEER => false]]);
  114.         $googleCalendar->setHttpClient($guzzleClient);
  115.         $this->googleCalendar $googleCalendar;
  116.         $this->translator $translator;
  117.         $this->docContractService $docContractService;
  118.         $this->em $em;
  119.         $this->session $session;
  120.         $this->syncronizationsCateringService $syncronizationsCateringService;
  121.         $this->syncronizationsAVService $syncronizationsAVService;
  122.         $this->agendaService $agendaService;
  123.         $this->repository $repository;
  124.         $this->reservationService $reservationService;
  125.         $this->venueService $venueService;
  126.         $this->sincGpHtAvService $sincGpHtAvService;
  127.     }
  128.     /**
  129.      * @Route("/connectGoogle", name="homepage_Connect_Google")
  130.      */
  131.     public function indexConnectGoogleAction(Request $request)
  132.     {
  133.         $session = new Session();
  134.         $token $session->get('tokenGoogleCalendar');
  135.         if (!is_null($token)) {
  136.             $this->googleCalendar->setAccessToken($token);
  137.         }
  138.         // If there is no previous token or it's expired.
  139.         $data = array();
  140.         if ($this->googleCalendar->isAccessTokenExpired()) {
  141.             // Refresh the token if possible, else fetch a new one.
  142.             if ($this->googleCalendar->getRefreshToken()) {
  143.                 $this->googleCalendar->fetchAccessTokenWithRefreshToken($this->googleCalendar->getRefreshToken());
  144.             } else {
  145.                 // Request authorization from the user.
  146.                 $authUrl $this->googleCalendar->createAuthUrl();
  147.                 return $this->redirect($authUrl);
  148.             }
  149.         }
  150.         return $this->redirectToRoute('homepage');
  151.     }
  152.     /**
  153.      * @Route("/add",  name="reservations_venues_add")
  154.      */
  155.     public function addReservationAction(Request $request)
  156.     {
  157.         return $this->redirectToRoute('reservations_venues_add_simple');
  158.     }
  159.     /**
  160.      * @Route("/create", name="reservations_venues_create")
  161.      */
  162.     public function createAction(EntityManagerInterface $emRequest $request)
  163.     {
  164.         $reserva = new Reservation();
  165.         // // $reserva->setComAvGp(10);                       // Valor por defecto de ComAvGg
  166.         $form $this->createReservationCreateForm($reserva);
  167.         $form->handleRequest($request);
  168.         /* Obtengo usuario logueado */
  169.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  170.         $user_id $user_logueado->getId();
  171.         $hoy = new \DateTime("now"NULL);
  172.         if ($form->isValid()) {
  173.             $reserva->setUpdatedBy($user_id);
  174.             $reserva->setUpdatedAt($hoy);
  175.             //            if (is_null($reserva->getCateringName())){
  176.             //                $reserva->setSupplier(null);
  177.             //                $reserva->setCateringName(null);
  178.             //            } else {
  179.             //                $reserva->setSupplier($reserva->getCateringName()->getId());
  180.             //                $reserva->setCateringName($reserva->getCateringName()->getName());
  181.             //            }
  182.             $clientId $arrayRequest['client'] ?? null;
  183.             $reserva->setClient(
  184.                 $clientId $em->getRepository(\App\Entity\Client::class)->find($clientId) : null
  185.             );
  186.             $reserva->setCreatedAt($hoy);
  187.             $reserva->setCreatedBy($user_id);
  188.             $reserva->setDateStart(new \DateTime('2078-01-01'));
  189.             $reserva->setDateEnd(new \DateTime('2000-01-01'));
  190.             if (is_null($reserva->getStatus())) {
  191.                 $reserva->setStatus('Cotizado');
  192.             }
  193.             if (is_null($reserva->getPriority()) or empty($reserva->getPriority()) or ($reserva->getPriority() == 'Auto')) {
  194.                 $reserva->setPriority(1);
  195.             }
  196.             // Buscamos la menor fecha de sala para el inicio y la mayor para determinar el fin del evento
  197.             $salas $request->request->get('salas');
  198.             // crea una reserva sin sala. que fechas le pongo al evento
  199.             if (!is_null($salas)) {
  200.                 foreach ($salas as $sala) {
  201.                     if (sizeof($sala['mountingHourStart']) != 5) {
  202.                         // Necesitamos la hora en formato HH:mm
  203.                         switch (strlen($sala['mountingHourStart'])) {
  204.                             case 0:
  205.                                 $sala['mountingHourStart'] = '00:00';
  206.                                 break; // Vacio
  207.                             case 1// H  -> 0H:00
  208.                                 if (is_numeric($sala['mountingHourStart'])) {
  209.                                     $sala['mountingHourStart'] = '0' $sala['mountingHourStart'] . ':00';
  210.                                 } else {
  211.                                     $sala['mountingHourStart'] = '00:00';
  212.                                 }
  213.                                 break;
  214.                             case 2:
  215.                                 $sala['mountingHourStart'] = $sala['mountingHourStart'] . ':00';
  216.                                 break;   // HH  -> HH:00
  217.                             case 3:
  218.                                 $sala['mountingHourStart'] = '0' $sala['mountingHourStart'];
  219.                                 break;     // Hmm  -> 0H:mm
  220.                             case 4:
  221.                                 $sala['mountingHourStart'] = substr($sala['mountingHourStart'], 02) . ':' substr($sala['mountingHourStart'], 22);
  222.                                 break;      // HHmm  -> HH:mm
  223.                             default:
  224.                                 $sala['mountingHourStart'] = '00:00';
  225.                                 break;      // XXXXyyy
  226.                         }
  227.                     }
  228.                     if (sizeof($sala['removalHourEnd']) != 5) {
  229.                         // Necesitamos la hora en formato HH:mm
  230.                         switch (strlen($sala['removalHourEnd'])) {
  231.                             case 0:
  232.                                 $sala['removalHourEnd'] = '00:00';
  233.                                 break;      // Vacio
  234.                             case 1:
  235.                                 if (is_numeric($sala['removalHourEnd'])) {
  236.                                     $sala['removalHourEnd'] = '0' $sala['removalHourEnd'] . ':00';
  237.                                 } else {
  238.                                     $sala['removalHourEnd'] = '00:00';
  239.                                 }
  240.                                 break;      // H  -> 0H:00
  241.                             case 2:
  242.                                 $sala['removalHourEnd'] = $sala['removalHourEnd'] . ':00';
  243.                                 break;      // HH  -> HH:00
  244.                             case 3:
  245.                                 $sala['removalHourEnd'] = '0' $sala['removalHourEnd'];
  246.                                 break;      // Hmm  -> 0H:mm
  247.                             case 4:
  248.                                 $sala['removalHourEnd'] = substr($sala['removalHourEnd'], 02) . ':' substr($sala['removalHourEnd'], 22);
  249.                                 break;      // HHmm  -> HH:mm
  250.                             default:
  251.                                 $sala['removalHourEnd'] = '00:00';
  252.                                 break;      // XXXXyyy
  253.                         }
  254.                     }
  255.                     // Verificamos el montaje
  256.                     if ($reserva->getDateStart() > (new \DateTime($sala['mountingDate']))) {
  257.                         $reserva->setDateStart((new \DateTime($sala['mountingDate'] . " " $sala['mountingHourStart'])));
  258.                     }
  259.                     if ($reserva->getDateStart() > (new \DateTime($sala['dateStart']))) {
  260.                         $reserva->setDateStart((new \DateTime($sala['dateStart'] . " " $sala['hourStart'])));
  261.                     }
  262.                     if ($reserva->getDateEnd() < (new \DateTime($sala['dateEnd']))) {
  263.                         $reserva->setDateEnd((new \DateTime($sala['dateEnd'] . " " $sala['hourEnd'])));
  264.                     }
  265.                     //Verificamos el desmontaje
  266.                     if ($reserva->getDateEnd() < (new \DateTime($sala['removalDate']))) {
  267.                         $reserva->setDateEnd((new \DateTime($sala['removalDate'] . " " $sala['removalHourEnd'])));
  268.                     }
  269.                 }
  270.             } else {
  271.                 // No hay salas, se asigna a la reserva la fecha del dia actual
  272.                 $reserva->setDateStart((new \DateTime()));
  273.                 $reserva->setDateEnd((new \DateTime()));
  274.             }
  275.             // INICIO: se determina el numero de opcion o prioridad que tiene el evento
  276.             $salasTemp $request->request->get('salas');
  277.             // Pendiente reunion con Rafa (se determina el numero de opcion o prioridad que tiene el evento)
  278.             // FIN: se determina el numero de opcion o prioridad que tiene el evento
  279.             try {
  280.                 $em->persist($reserva);
  281.                 $em->flush();
  282.                 $event 'The Reservation has been created.';
  283.                 //                $successMessage = $this->translator->trans($event);
  284.                 $successMessage 'La reserva ha sido creada.';
  285.                 $this->addFlash('mensajereservation'$successMessage);
  286.             } catch (\Exception $e) {
  287.                 $event 'An error occurred: ' $e->getMessage();
  288.                 $errorMessage $this->translator->trans($event);
  289.                 $this->addFlash('mensajereservationerror'$errorMessage);
  290.             }
  291.         } else {
  292.             $errorMessagebase $this->translator->trans('Error, some fields are empty');
  293.             $this->addFlash('mensajetracingerror'$errorMessagebase);
  294.             $periods $em->getRepository(ReservationPeriod::class)->findAll();
  295.             return $this->render(
  296.                 'MDS/VenuesBundle/reservations/add-reservations.html.twig',
  297.                 array(
  298.                     'form' => $form->createView(),
  299.                     'periods' => $periods,
  300.                 )
  301.             );
  302.         }
  303.         /* Fin Gestión de eventos en Log */
  304.         $salas $request->request->get('salas');
  305.         // Inicio: Verificamos que hayan metido bien las salas, toda sala para poder facturar debe tener IdLounge, Fecha de inicio y fecha de fin
  306.         for ($i 0$i sizeof($salas); $i++) {
  307.             if (empty($salas[$i]['idLounge']) or empty($salas[$i]['dateStart']) or empty($salas[$i]['dateEnd'])) {
  308.                 unset($salas[$i]);
  309.             }
  310.         }
  311.         // Fin: Verificamos que hayan metido bien las salas, toda sala para poder facturar debe tener IdLounge, Fecha de inicio y fecha de fin
  312.         if (!is_null($reserva->getId())) {
  313.             if (!is_null($salas)) {
  314.                 foreach ($salas as $sala) {
  315.                     // Se guarda una sala si hay una sala seleccionada
  316.                     // IdLounge es el ID en la tabla reservation profile
  317.                     if (!empty(($sala['idLounge']))) {
  318.                         // consulto la tabla de precios para obtener el id de salon desde el id de precios
  319.                         $queryProfile $em->getRepository(ReservationLoungeProfile::class)->findOneById($sala['idLounge']);
  320.                         $reservaLounge = new ReservationLounge();
  321.                         $reservaLounge->setIdLounge($queryProfile->getLoungeId());
  322.                         $reservaLounge->setLoungeName(($em->getRepository(ReservationLoungeDetails::class)->findOneById($queryProfile->getLoungeId()))->getName());
  323.                         $reservaLounge->setCreatedAt($hoy);
  324.                         $reservaLounge->setCreatedBy($user_id);
  325.                         $reservaLounge->setUpdatedAt($hoy);
  326.                         $reservaLounge->setUpdatedBy($user_id);
  327.                         $reservaLounge->setIdReservation($reserva->getId());
  328.                         $reservaLounge->setDateStart(new \DateTime($sala['dateStart'] . " " $sala['hourStart']));
  329.                         $reservaLounge->setDateEnd(new \DateTime($sala['dateEnd'] . " " $sala['hourEnd']));
  330.                         $reservaLounge->setHourStart(substr($sala['hourStart'], 02));
  331.                         $reservaLounge->setMinStart(substr($sala['hourStart'], 32));
  332.                         $reservaLounge->setHourEnd(substr($sala['hourEnd'], 02));
  333.                         $reservaLounge->setMinEnd(substr($sala['hourEnd'], 32));
  334.                         $reservaLounge->setServicePrice($sala['servicePrice']);
  335.                         // el service name es la descripcion
  336.                         $reservaLounge->setServiceName($sala['serviceName']);
  337.                         $reservaLounge->setIdPeriod($sala['idLoungePrice']);
  338.                         if (empty($sala['servicePax'])) {
  339.                             $reservaLounge->setPax(null);
  340.                         } else {
  341.                             $reservaLounge->setPax($sala['servicePax']);
  342.                         }
  343.                         $reservaLounge->setMounting($sala['serviceMounting']);
  344.                         if (empty($sala['mountingPrice'])) {
  345.                             $reservaLounge->setMountingPrice(0);
  346.                         } else {
  347.                             $reservaLounge->setMountingPrice($sala['mountingPrice']);
  348.                         }
  349.                         $reservaLounge->setMountingLapse($sala['mountingLapse']);
  350.                         switch (strlen($sala['mountingHourStart'])) {
  351.                             case 0// Vacio
  352.                                 $reservaLounge->setMountingHourStart('00');
  353.                                 $reservaLounge->setMountingMinStart('00');
  354.                                 break;
  355.                             case 1// H  -> 0H:00
  356.                                 if (is_numeric($sala['mountingHourStart'])) {
  357.                                     $reservaLounge->setMountingHourStart('0' $sala['mountingHourStart']);
  358.                                 } else {
  359.                                     $reservaLounge->setMountingHourStart('00');
  360.                                 }
  361.                                 $reservaLounge->setMountingMinStart('00');
  362.                                 break;
  363.                             case 2// HH  -> HH:00
  364.                                 $reservaLounge->setMountingHourStart($sala['mountingHourStart']);
  365.                                 $reservaLounge->setMountingMinStart('00');
  366.                                 break;
  367.                             case 3// Hmm  -> 0H:mm
  368.                                 $reservaLounge->setMountingHourStart('0' substr($sala['mountingHourStart'], 01));
  369.                                 $reservaLounge->setMountingMinStart(substr($sala['mountingHourStart'], 12));
  370.                                 break;
  371.                             case 4// HHmm  -> HH:mm
  372.                                 $reservaLounge->setMountingHourStart(substr($sala['mountingHourStart'], 02));
  373.                                 $reservaLounge->setMountingMinStart(substr($sala['mountingHourStart'], 22));
  374.                                 break;
  375.                             case 5// HH:mm  -> HH:mm
  376.                                 $reservaLounge->setMountingHourStart(substr($sala['mountingHourStart'], 02));
  377.                                 $reservaLounge->setMountingMinStart(substr($sala['mountingHourStart'], 32));
  378.                                 break;
  379.                             default: // XXXXyyy
  380.                                 $reservaLounge->setMountingHourStart('00');
  381.                                 $reservaLounge->setMountingMinStart('00');
  382.                                 break;
  383.                         }
  384.                         switch (strlen($sala['mountingHourEnd'])) {
  385.                             case 0// Vacio
  386.                                 $reservaLounge->setMountingHourEnd('00');
  387.                                 $reservaLounge->setMountingMinEnd('00');
  388.                                 break;
  389.                             case 1// H  -> 0H:00
  390.                                 if (is_numeric($sala['mountingHourEnd'])) {
  391.                                     $reservaLounge->setMountingHourEnd('0' $sala['mountingHourEnd']);
  392.                                 } else {
  393.                                     $reservaLounge->setMountingHourEnd('00');
  394.                                 }
  395.                                 $reservaLounge->setMountingMinEnd('00');
  396.                                 break;
  397.                             case 2// HH  -> HH:00
  398.                                 $reservaLounge->setMountingHourEnd($sala['mountingHourEnd']);
  399.                                 $reservaLounge->setMountingMinEnd('00');
  400.                                 break;
  401.                             case 3// Hmm  -> 0H:mm
  402.                                 $reservaLounge->setMountingHourEnd('0' substr($sala['mountingHourEnd'], 01));
  403.                                 $reservaLounge->setMountingMinEnd(substr($sala['mountingHourEnd'], 12));
  404.                                 break;
  405.                             case 4// HHmm  -> HH:mm
  406.                                 $reservaLounge->setMountingHourEnd(substr($sala['mountingHourEnd'], 02));
  407.                                 $reservaLounge->setMountingMinEnd(substr($sala['mountingHourEnd'], 22));
  408.                                 break;
  409.                             case 5// HH:mm  -> HH:mm
  410.                                 $reservaLounge->setMountingHourEnd(substr($sala['mountingHourEnd'], 02));
  411.                                 $reservaLounge->setMountingMinEnd(substr($sala['mountingHourEnd'], 32));
  412.                                 break;
  413.                             default: // XXXXyyy
  414.                                 $reservaLounge->setMountingHourEnd('00');
  415.                                 $reservaLounge->setMountingMinEnd('00');
  416.                                 break;
  417.                         }
  418.                         $reservaLounge->setMountingDate(new \DateTime($sala['mountingDate'] . ' ' $reservaLounge->getMountingHourStart() . ':' $reservaLounge->getMountingMinStart()));
  419.                         $reservaLounge->setRemovalLapse($sala['removalLapse']);
  420.                         $reservaLounge->setRemovalDate(new \DateTime($sala['removalDate']));
  421.                         switch (strlen($sala['removalHourStart'])) {
  422.                             case 0// Vacio
  423.                                 $reservaLounge->setRemovalHourStart('00');
  424.                                 $reservaLounge->setRemovalMinStart('00');
  425.                                 break;
  426.                             case 1// H  -> 0H:00
  427.                                 if (is_numeric($sala['removalHourStart'])) {
  428.                                     $reservaLounge->setRemovalHourStart('0' $sala['removalHourStart']);
  429.                                 } else {
  430.                                     $reservaLounge->setRemovalHourStart('00');
  431.                                 }
  432.                                 $reservaLounge->setRemovalMinStart('00');
  433.                                 break;
  434.                             case 2// HH  -> HH:00
  435.                                 $reservaLounge->setRemovalHourStart($sala['removalHourStart']);
  436.                                 $reservaLounge->setRemovalMinStart('00');
  437.                                 break;
  438.                             case 3// Hmm  -> 0H:mm
  439.                                 $reservaLounge->setRemovalHourStart('0' substr($sala['removalHourStart'], 01));
  440.                                 $reservaLounge->setRemovalMinStart(substr($sala['removalHourStart'], 12));
  441.                                 break;
  442.                             case 4// HHmm  -> HH:mm
  443.                                 $reservaLounge->setRemovalHourStart(substr($sala['removalHourStart'], 02));
  444.                                 $reservaLounge->setRemovalMinStart(substr($sala['removalHourStart'], 22));
  445.                                 break;
  446.                             case 5// HH:mm  -> HH:mm
  447.                                 $reservaLounge->setRemovalHourStart(substr($sala['removalHourStart'], 02));
  448.                                 $reservaLounge->setRemovalMinStart(substr($sala['removalHourStart'], 32));
  449.                                 break;
  450.                             default: // XXXXyyy
  451.                                 $reservaLounge->setRemovalHourStart('00');
  452.                                 $reservaLounge->setRemovalMinStart('00');
  453.                                 break;
  454.                         }
  455.                         switch (strlen($sala['removalHourEnd'])) {
  456.                             case 0// Vacio
  457.                                 $reservaLounge->setRemovalHourEnd('00');
  458.                                 $reservaLounge->setRemovalMinEnd('00');
  459.                                 break;
  460.                             case 1// H  -> 0H:00
  461.                                 if (is_numeric($sala['removalHourEnd'])) {
  462.                                     $reservaLounge->setRemovalHourEnd('0' $sala['removalHourEnd']);
  463.                                 } else {
  464.                                     $reservaLounge->setRemovalHourEnd('00');
  465.                                 }
  466.                                 $reservaLounge->setRemovalMinEnd('00');
  467.                                 break;
  468.                             case 2// HH  -> HH:00
  469.                                 $reservaLounge->setRemovalHourEnd($sala['removalHourEnd']);
  470.                                 $reservaLounge->setRemovalMinEnd('00');
  471.                                 break;
  472.                             case 3// Hmm  -> 0H:mm
  473.                                 $reservaLounge->setRemovalHourEnd('0' substr($sala['removalHourEnd'], 01));
  474.                                 $reservaLounge->setRemovalMinEnd(substr($sala['removalHourEnd'], 12));
  475.                                 break;
  476.                             case 4// HHmm  -> HH:mm
  477.                                 $reservaLounge->setRemovalHourEnd(substr($sala['removalHourEnd'], 02));
  478.                                 $reservaLounge->setRemovalMinEnd(substr($sala['removalHourEnd'], 22));
  479.                                 break;
  480.                             case 5// HH:mm  -> HH:mm
  481.                                 $reservaLounge->setRemovalHourEnd(substr($sala['removalHourEnd'], 02));
  482.                                 $reservaLounge->setRemovalMinEnd(substr($sala['removalHourEnd'], 32));
  483.                                 break;
  484.                             default: // XXXXyyy
  485.                                 $reservaLounge->setRemovalHourEnd('00');
  486.                                 $reservaLounge->setRemovalMinEnd('00');
  487.                                 break;
  488.                         }
  489.                         if (empty($sala['removalPrice'])) {
  490.                             $reservaLounge->setRemovalPrice(0);
  491.                         } else {
  492.                             $reservaLounge->setRemovalPrice($sala['removalPrice']);
  493.                         }
  494.                         // INICIO: Verificamos si choca con otra reserva
  495.                         // Si sucede se usara el booleano OtherPriceSave para indicarlo
  496.                         $resFun $this->VerificarCoflictosEnSalas($reservaLounge);
  497.                         $tempBool $resFun['bool'];
  498.                         if ($tempBool) {
  499.                             $reservaLounge->setOtherPriceSave(true);
  500.                             $reserva->setPriority($resFun['priority']);
  501.                             // Se debe modificar la prioridad de la nueva reserva, que ya se habia guardado previamente
  502.                             try {
  503.                                 $em->persist($reserva);
  504.                                 $em->flush();
  505.                             } catch (\Exception $e) {
  506.                                 $event 'Error al actualizar la prioridad del evento ' $e->getMessage();
  507.                                 /* Para el usuario */
  508.                                 $errorMessage $this->translator->trans($event);
  509.                                 $this->addFlash('mensajereservationerror'$errorMessage);
  510.                             }
  511.                         } else {
  512.                             $reservaLounge->setOtherPriceSave(false);
  513.                         }
  514.                         // FIN: Verificamos si choca con otra reserva
  515.                         // INICIO: Si es necesario se actualizan fechas de inicio y fin usando dia de montaje y desmontaje
  516.                         if (($reservaLounge->getMountingDate() < $reserva->getDateStart()) or ($reserva->getDateEnd() < $reservaLounge->getRemovalDate())) {
  517.                             if ($reservaLounge->getMountingDate() < $reserva->getDateStart()) {
  518.                                 $reserva->setDateStart($reservaLounge->getMountingDate());
  519.                             }
  520.                             if ($reserva->getDateEnd() < $reservaLounge->getRemovalDate()) {
  521.                                 $reserva->setDateEnd($reservaLounge->getRemovalDate());
  522.                             }
  523.                             try {
  524.                                 $em->persist($reserva);
  525.                                 $em->flush();
  526.                             } catch (\Exception $e) {
  527.                                 $event 'Error al actualizar fechas de inicio y fin, por montaje y desmontaje de sala: ' $e->getMessage();
  528.                                 $errorMessage $this->translator->trans($event);
  529.                                 $this->addFlash('mensajereservationerror'$errorMessage);
  530.                             }
  531.                         }
  532.                         // FIN: Si es necesario se actualizan fechas de inicio y fin usando dia de montaje y desmontaje
  533.                         try {
  534.                             $em->persist($reservaLounge);
  535.                             $em->flush();
  536.                         } catch (\Exception $e) {
  537.                             $event 'Al agregar la sala ha ocurrido un error: ' $e->getMessage();
  538.                             /* Para el usuario */
  539.                             $errorMessage $this->translator->trans($event);
  540.                             $this->addFlash('mensajereservationerror'$errorMessage);
  541.                         }
  542.                     }
  543.                 }
  544.                 // INICIO: Verificamos la prioridad
  545.                 $numeroPriority 1;
  546.                 //INICIO: Buscamos las salas que coincidan en tiempo de reserva
  547.                 foreach ($salas as $sala) {
  548.                     $newdateStar $sala['dateStart'] . ' ' $sala['hourStart'];
  549.                     $newdateEnd $sala['dateEnd'] . ' ' $sala['hourEnd'];
  550.                     $reservaProfile $em->getRepository(ReservationLoungeProfile::class)->findOneById($sala['idLounge']);
  551.                     $parameters = array(
  552.                         'dateStar' => $newdateStar,
  553.                         'dateEnd' => $newdateEnd,
  554.                         'idLounge' => $reservaProfile->getLoungeId(),
  555.                         'idRes' => $reserva->getId(),
  556.                     );
  557.                     $dql 'SELECT i
  558.                             FROM VenuesBundle:ReservationLounge i
  559.                             WHERE  (i.dateStart >= :dateStar
  560.                               and i.dateStart <= :dateEnd
  561.                               and i.idLounge = :idLounge
  562.                               and i.idReservation != :idRes)
  563.                               or 
  564.                               (i.dateStart <= :dateStar
  565.                               and i.dateStart >= :dateEnd
  566.                               and i.idLounge = :idLounge
  567.                               and i.idReservation != :idRes)
  568.                               ';
  569.                     $query $em->createQuery($dql)->setParameters($parameters);
  570.                     $reservationLounge $query->getResult();
  571.                 }
  572.                 //FIN: Buscamos las salas que coincidan en tiempo de reserva
  573.                 // INICIO: Buscamos el numero de opcion a asignar
  574.                 $modificarPrior false;
  575.                 if (!empty($reservaLounge)) {
  576.                     foreach ($reservationLounge as $resLoung) {
  577.                         $reservaClash $em->getRepository(Reservation::class)->findOneById($resLoung->getIdReservation());
  578.                         $tempPrior $reservaClash->getPriority();
  579.                         if ($numeroPriority <= $tempPrior) {
  580.                             // Ya tenemos una reserva con opcion de mayor relevancia (un numero de opción inferior)
  581.                             $numeroPriority $tempPrior 1;
  582.                             $modificarPrior true;
  583.                         }
  584.                     }
  585.                     if ($modificarPrior) {
  586.                         // Se debe modificar la prioridad
  587.                         $reserva->setPriority($numeroPriority);
  588.                         try {
  589.                             $em->persist($reserva);
  590.                             $em->flush();
  591.                             $event 'The Reservation has been created.';
  592.                             //                            $successMessage = $this->translator->trans($event);
  593.                             $successMessage 'La reserva ha sido creada.';
  594.                             $this->addFlash('mensajereservation'$successMessage);
  595.                         } catch (\Exception $e) {
  596.                             $event 'An error occurred: ' $e->getMessage();
  597.                             $errorMessage $this->translator->trans($event);
  598.                             $this->addFlash('mensajereservationerror'$errorMessage);
  599.                         }
  600.                     }
  601.                 } else {
  602.                     // El numero de opción asignada fue el correcto
  603.                 }
  604.                 // FIN: Buscamos el numero de opcion a asignar
  605.                 // FIN: Verificamos la prioridad
  606.             }
  607.         } else {
  608.             $reservationsLounges null;    // Si fallo la reserva no habrá salas
  609.         }
  610.         return $this->redirectToRoute('reservations_venues_index');
  611.     }
  612.     public function VerificarCoflictosEnSalas(EntityManagerInterface $em$nuevaSala)
  613.     {
  614.         $allSalas $em->getRepository(ReservationLounge::class)->findAll();
  615.         $tempBool false;  //Aun no se ha detectado un conflicto
  616.         $prioridad 1;
  617.         foreach ($allSalas as $sala) {
  618.             if ($sala->getIdReservation() == $nuevaSala->getIdReservation()) {
  619.                 // No hay conflicto son de la misma reserva
  620.                 $tempBool = ($tempBool or false);
  621.             } else {
  622.                 if (!($sala->getIdLounge() == $nuevaSala->getIdLounge())) {
  623.                     // No hay conflicto no son la misma sala
  624.                     $tempBool = ($tempBool or false);
  625.                 } else {
  626.                     // Caso 1: F. inicio de $nuevaSala entre las feachas de $sala
  627.                     if (($nuevaSala->getDateStart() > $sala->getDateStart()) and ($nuevaSala->getDateStart() < $sala->getDateEnd())) {
  628.                         $tempBool true;
  629.                         // Buscamos la prioridad que tiene el evento de la sala que colisiona para determinar la nueva prioridad del evento que se está creando
  630.                         $resTemp $em->getRepository(Reservation::class)->findOneById($sala->getIdReservation());
  631.                         if (($prioridad $resTemp->getPriority()) or ($prioridad == $resTemp->getPriority())) {
  632.                             $prioridad $resTemp->getPriority() + 1;
  633.                         }
  634.                     }
  635.                     // Caso 2: F. fin de $nuevaSala entre las feachas de $sala
  636.                     if (($nuevaSala->getDateEnd() > $sala->getDateStart()) and ($nuevaSala->getDateEnd() < $sala->getDateEnd())) {
  637.                         $tempBool true;
  638.                         // Buscamos la prioridad que tiene el evento de la sala que colisiona para determinar la nueva prioridad del evento que se está creando
  639.                         $resTemp $em->getRepository(Reservation::class)->findOneById($sala->getIdReservation());
  640.                         if (($prioridad <= $resTemp->getPriority()) or ($prioridad == $resTemp->getPriority())) {
  641.                             $prioridad $resTemp->getPriority() + 1;
  642.                         }
  643.                     }
  644.                     // Caso 3: F. inicio de $sala entre las feachas de $nuevaSala
  645.                     if (($sala->getDateStart() > $nuevaSala->getDateStart()) and ($sala->getDateStart() < $nuevaSala->getDateEnd())) {
  646.                         $tempBool true;
  647.                         // Buscamos la prioridad que tiene el evento de la sala que colisiona para determinar la nueva prioridad del evento que se está creando
  648.                         $resTemp $em->getRepository(Reservation::class)->findOneById($sala->getIdReservation());
  649.                         if (($prioridad <= $resTemp->getPriority()) or ($prioridad == $resTemp->getPriority())) {
  650.                             $prioridad $resTemp->getPriority() + 1;
  651.                         }
  652.                     }
  653.                     // Caso 4: F. fin de $sala entre las feachas de $nuevaSala
  654.                     if (($sala->getDateEnd() > $nuevaSala->getDateStart()) and ($sala->getDateEnd() < $nuevaSala->getDateEnd())) {
  655.                         $tempBool true;
  656.                         // Buscamos la prioridad que tiene el evento de la sala que colisiona para determinar la nueva prioridad del evento que se está creando
  657.                         $resTemp $em->getRepository(Reservation::class)->findOneById($sala->getIdReservation());
  658.                         if (($prioridad <= $resTemp->getPriority()) or ($prioridad == $resTemp->getPriority())) {
  659.                             $prioridad $resTemp->getPriority() + 1;
  660.                         }
  661.                     }
  662.                     // Caso 5: fechas iguales
  663.                     if (
  664.                         ($nuevaSala->getDateStart() == $sala->getDateStart()) or
  665.                         ($nuevaSala->getDateStart() == $sala->getDateEnd()) or
  666.                         ($nuevaSala->getDateEnd() == $sala->getDateStart()) or
  667.                         ($nuevaSala->getDateEnd() == $sala->getDateEnd())
  668.                     ) {
  669.                         $tempBool true;
  670.                     }
  671.                 }
  672.             }
  673.         }
  674.         $res = array('bool' => $tempBool'priority' => $prioridad);
  675.         return ($res);
  676.     }
  677.     public function CalculoPrioridad(EntityManagerInterface $em$reserva)
  678.     {
  679.         $listAllReservas $em->getRepository(Reservation::class)->findAll();
  680.         // logico para controlar el conflicto entre salas
  681.         $logSalasError false;
  682.         // valor original de la prioridad
  683.         $oldPriority $reserva->getPriority();
  684.         foreach ($listAllReservas as $resv) {
  685.             $reservaSala explode(","$reserva->getSalas());          // Arreglo de salas para agregar
  686.             $resSala explode(","$resv->getSalas());                  // Arreglo de salas que ya estan en
  687.             foreach ($reservaSala as $item) {
  688.                 if (in_array($item$resSala)) {
  689.                     $logSalasError = ($logSalasError or true);          // Este logico indica si hay conflicto entre las salas
  690.                 }
  691.             }
  692.             if (
  693.                 (($reserva->getDateStart() == $resv->getDateStart()) or ($reserva->getDateStart() < $resv->getDateStart())) and
  694.                 ($resv->getDateStart() < $reserva->getDateEnd()) and ($resv->getStatus() == 'Confirmed')
  695.             ) {
  696.                 if ($resv->getPriority() == $reserva->getPriority()) {
  697.                     $reserva->setPriority($reserva->getPriority() - 1);
  698.                 } else {
  699.                     if ($resv->getPriority() < $reserva->getPriority()) {
  700.                         $reserva->setPriority($resv->getPriority() - 1);
  701.                     } else {
  702.                         // ($resv->getPriority() > $reserva->getPriority())
  703.                         // No se debe cambiar la prioridad ya que esta por debajo de la reserva ya creada
  704.                     }
  705.                 }
  706.             }
  707.             if (
  708.                 (($resv->getDateStart() == $reserva->getDateStart()) or ($resv->getDateStart() < $reserva->getDateStart())) and
  709.                 ($reserva->getDateEnd() < $resv->getDateEnd()) and ($resv->getStatus() == 'Confirmed')
  710.             ) {
  711.                 if ($resv->getPriority() == $reserva->getPriority()) {
  712.                     $reserva->setPriority($reserva->getPriority() - 1);
  713.                 } else {
  714.                     if ($resv->getPriority() < $reserva->getPriority()) {
  715.                         $reserva->setPriority($resv->getPriority() - 1);
  716.                     } else {
  717.                         // ($resv->getPriority() > $reserva->getPriority())
  718.                         // No se debe cambiar la prioridad ya que esta por debajo de la reserva ya creada
  719.                     }
  720.                 }
  721.             }
  722.             if (
  723.                 (($reserva->getDateStart() == $resv->getDateStart()) or ($reserva->getDateStart() < $resv->getDateStart())) and
  724.                 (($resv->getDateEnd() == $reserva->getDateEnd()) or ($resv->getDateEnd() < $reserva->getDateEnd())) and
  725.                 ($resv->getStatus() == 'Confirmed')
  726.             ) {
  727.                 if ($resv->getPriority() == $reserva->getPriority()) {
  728.                     $reserva->setPriority($reserva->getPriority() - 1);
  729.                 } else {
  730.                     if ($resv->getPriority() < $reserva->getPriority()) {
  731.                         $reserva->setPriority($resv->getPriority() - 1);
  732.                     } else {
  733.                         // ($resv->getPriority() > $reserva->getPriority())
  734.                         // No se debe cambiar la prioridad ya que esta por debajo de la reserva ya creada
  735.                     }
  736.                 }
  737.             }
  738.             if (
  739.                 (($resv->getDateStart() == $reserva->getDateStart()) or ($resv->getDateStart() < $reserva->getDateStart())) and
  740.                 (($resv->getDateEnd() == $reserva->getDateEnd()) or ($resv->getDateEnd() < $reserva->getDateEnd())) and
  741.                 ($resv->getStatus() == 'Confirmed')
  742.             ) {
  743.                 if ($resv->getPriority() == $reserva->getPriority()) {
  744.                     $reserva->setPriority($reserva->getPriority() - 1);
  745.                 } else {
  746.                     if ($resv->getPriority() < $reserva->getPriority()) {
  747.                         $reserva->setPriority($resv->getPriority() - 1);
  748.                     } else {
  749.                         // ($resv->getPriority() > $reserva->getPriority())
  750.                         // No se debe cambiar la prioridad ya que esta por debajo de la reserva ya creada
  751.                     }
  752.                 }
  753.             }
  754.         }
  755.         $priority $reserva->getPriority();
  756.         $reserva->setPriority($oldPriority);    // Se restablece el valor de origen de la prioridad
  757.         $data = array('prioridad' => $priority);
  758.         return $data;
  759.     }
  760.     public function NombreSalasPrecios(EntityManagerInterface $em)
  761.     {
  762.         $reservaLoungeDetails $em->getRepository(ReservationLoungeDetails::class)->findAll();
  763.         $data = array();
  764.         foreach ($reservaLoungeDetails as $res) {
  765.             if (!empty($data['salas'])) {
  766.                 $data['salas'] = $data['salas'] . ',' $res->getName();
  767.             } else {
  768.                 $data['salas'] = $res->getName();
  769.             }
  770.         }
  771.         $dataArray = array('-1');
  772.         foreach ($reservaLoungeDetails as $res) {
  773.             array_push($dataArray, array($res->getId(), $res->getName()));
  774.         }
  775.         unset($dataArray[0]);
  776.         $data['arraySalas'] = $dataArray;
  777.         $parameters = array();
  778.         $dql 'SELECT p
  779.                 FROM VenuesBundle:ReservationGpPrice p                         
  780.                 ORDER BY p.idService ASC ';
  781.         $query $em->createQuery($dql)->setParameters($parameters);
  782.         $reservaGpPrice $query->getResult();
  783.         foreach ($reservaGpPrice as $res) {
  784.             if (!empty($data['precios'])) {
  785.                 $data['precios'] = $data['precios'] . ',' $res->getNameAndPrice();
  786.             } else {
  787.                 $data['precios'] = $res->getNameAndPrice();
  788.             }
  789.         }
  790.         $dataArray = array('-1');
  791.         foreach ($reservaGpPrice as $res) {
  792.             array_push($dataArray, array($res->getIdService(), $res->getNameAndPrice()));
  793.         }
  794.         unset($dataArray[0]);
  795.         $data['arrayPrecios'] = $dataArray;
  796.         return $data;
  797.     }
  798.     private function CalculosTotalesEditSimple($id, ?array $overrideLounges null, ?array $overrideServices null)
  799.     {
  800.         $em $this->getDoctrine()->getManager();
  801.         $reservaLounges $overrideLounges ?? $em->getRepository(ReservationLoungeSimple::class)->findByIdReservation($id);
  802.         $reservaServices $overrideServices ?? $em->getRepository(ReservationService::class)->findByReservationId($id);
  803.         $reserva $em->getRepository(Reservation::class)->find($id);
  804.         $reservaSucoe $reserva && $reserva->isSucoe();
  805.         $totales_neto_all 0;
  806.         $data_iva = [
  807.             'ivaMontoVeintiUno' => 0,
  808.             'ivaMontoDiez' => 0,
  809.             'ivaMontoCero' => 0,
  810.         ];
  811.         $loungeAcc = ['neto' => 0'sumSubT' => 0];
  812.         $serviceAcc = ['neto' => 0'sumSubT' => 0];
  813.         
  814.         $loungeLines = [];
  815.         $serviceLines = [];
  816.         // 1. SALAS (Lounge)
  817.         foreach ($reservaLounges as $item) {
  818.             $price = (float)$item->getServicePrice();
  819.             
  820.             $ivaRate $item->getSageIva() ? (float)$item->getSageIva()->getIva() : 21.0;
  821.             
  822.             $neto $price;
  823.             $subtotalLine $reservaSucoe $price : ($price * (+ ($ivaRate 100)));
  824.             $neto round($neto2PHP_ROUND_HALF_UP);
  825.             $subtotalLine round($subtotalLine2PHP_ROUND_HALF_UP);
  826.             if ($price 0) {
  827.                 $totales_neto_all += $neto;
  828.                 if (!$reservaSucoe) {
  829.                     if ($ivaRate == 21) {
  830.                         $data_iva['ivaMontoVeintiUno'] += ($neto 0.21);
  831.                     } elseif ($ivaRate == 10) {
  832.                         $data_iva['ivaMontoDiez'] += ($neto 0.10);
  833.                     }
  834.                 }
  835.                 $loungeAcc['neto'] += $neto;
  836.                 $loungeAcc['sumSubT'] += $subtotalLine;
  837.             }
  838.             $loungeLines[] = [
  839.                 'item' => $item,
  840.                 'neto' => $neto,
  841.                 'subtotal' => $subtotalLine
  842.             ];
  843.         }
  844.         // 2. SERVICIOS
  845.         foreach ($reservaServices as $item) {
  846.             $priceRaw = (float)$item->getPrice();
  847.             // Comisión y Over en precio unitario (Sincronizado con baseInvoiceReservation)
  848.             $commission = (float)$item->getCommission();
  849.             $unitPrice = ($item->getOpCommission() == '1')
  850.                 ? ($priceRaw + ($priceRaw $commission 100))
  851.                 : ($priceRaw - ($priceRaw $commission 100));
  852.             $over = (float)$item->getOver();
  853.             $unitPrice = ($item->getOpOver() == '1') ? ($unitPrice $over) : ($unitPrice $over);
  854.             $subneto $unitPrice;
  855.             $subtotalLine $unitPrice;
  856.             // Multiplicadores
  857.             $pax max(1, (int)$item->getPax());
  858.             $units max(1, (int)$item->getUnits());
  859.             $dateIn $item->getDateInAt();
  860.             $dateOut $item->getDateOutAt();
  861.             $catId $item->getServiceCatId();
  862.             // Lógica de días exacta de baseInvoiceReservation / baseInvoiceDoneReservation
  863.             $days = ($catId == 5) ? $dateIn->diff($dateOut)->days : ($dateIn->diff($dateOut)->days 1);
  864.             switch ($catId) {
  865.                 case 1// Alojamiento
  866.                     $numNoches $dateIn->diff($dateOut)->days;
  867.                     $subtotalLine *= $numNoches $units;
  868.                     $subneto *= $numNoches $units;
  869.                     $displayUnits $units;
  870.                     break;
  871.                 case 2// Actividades
  872.                     $subtotalLine *= $days $units;
  873.                     $subneto *= $days $units;
  874.                     $displayUnits $units;
  875.                     break;
  876.                 default: // Resto
  877.                     $subtotalLine *= $days $units $pax;
  878.                     $subneto *= $days $units $pax;
  879.                     $displayUnits $units;
  880.                     break;
  881.             }
  882.             // IVA (Sincronizado: si opIva != 1, el precio ya incluía IVA)
  883.             $ivaRate $item->getSageIva() ? (float)$item->getSageIva()->getIva() : 21.0;
  884.             if ($item->getOpIva() == '1') {
  885.                 if (!$reservaSucoe) {
  886.                     $subtotalLine *= (+ ($ivaRate 100));
  887.                 }
  888.             } else {
  889.                 // BUG/Lógica heredada: si opIva es 0, extraemos la base
  890.                 $subtotalLine = ($priceRaw 100) / (100 $ivaRate); 
  891.                 $subneto = ($subneto 100) / (100 $ivaRate);
  892.             }
  893.             $neto round($subneto2PHP_ROUND_HALF_UP);
  894.             $subtotalLine round($subtotalLine2PHP_ROUND_HALF_UP);
  895.             if ($priceRaw 0) {
  896.                 $totales_neto_all += $neto;
  897.                 if (!$reservaSucoe) {
  898.                     if ($ivaRate == 21) {
  899.                         $data_iva['ivaMontoVeintiUno'] += ($neto 0.21);
  900.                     } elseif ($ivaRate == 10) {
  901.                         $data_iva['ivaMontoDiez'] += ($neto 0.10);
  902.                     }
  903.                 }
  904.                 $serviceAcc['neto'] += $neto;
  905.                 $serviceAcc['sumSubT'] += $subtotalLine;
  906.             }
  907.             $serviceLines[] = [
  908.                 'item' => $item,
  909.                 'neto' => $neto,
  910.                 'subtotal' => $subtotalLine,
  911.                 'units' => $displayUnits,
  912.                 'days' => $days,
  913.                 'pax' => $pax
  914.             ];
  915.         }
  916.         // Redondeos finales de buckets de IVA
  917.         $data_iva['ivaMontoVeintiUno'] = round($data_iva['ivaMontoVeintiUno'], 2PHP_ROUND_HALF_UP);
  918.         $data_iva['ivaMontoDiez'] = round($data_iva['ivaMontoDiez'], 2PHP_ROUND_HALF_UP);
  919.         $totalIVA $data_iva['ivaMontoVeintiUno'] + $data_iva['ivaMontoDiez'];
  920.         $totalGeneralConIva round($totales_neto_all $totalIVA2);
  921.         return [
  922.             'totales_global_con_iva' => round($loungeAcc['sumSubT'], 2),
  923.             'totales_global_iva' => round($loungeAcc['sumSubT'] - $loungeAcc['neto'], 2),
  924.             'totales_global_neto' => round($loungeAcc['neto'], 2),
  925.             'totales_global_servicios_neto' => round($serviceAcc['neto'], 2),
  926.             'totales_global_servicios_con_iva' => round($serviceAcc['sumSubT'], 2),
  927.             'totales_global_servicios_iva' => round($serviceAcc['sumSubT'] - $serviceAcc['neto'], 2),
  928.             'sumatoria_totales_global_con_iva' => $totalGeneralConIva,
  929.             'sumatoria_totales_global_neto' => round($totales_neto_all2),
  930.             'sumatoria_totales_global_iva' => round($totalIVA2),
  931.             'loungeLines' => $loungeLines,
  932.             'serviceLines' => $serviceLines
  933.         ];
  934.     }
  935.     /**
  936.      * @Route("/calendar/space/{id}", name="calendar_by_space")
  937.      */
  938.     public function calendarBySpaceAction(int $idRequest $requestEntityManagerInterface $em): Response
  939.     {
  940.         $space $em->getRepository(Space::class)->find($id);
  941.         if (!$space) {
  942.             throw $this->createNotFoundException('Espacio no encontrado');
  943.         }
  944.         $session = new Session();
  945.         $token $session->get('tokenGoogleCalendar');
  946.         $connectGoogle $token "1" "0";
  947.         if ($token) {
  948.             $this->googleCalendar->setAccessToken($token);
  949.         }
  950.         $user $this->get('security.token_storage')->getToken()->getUser();
  951.         return $this->render(
  952.             'MDS/VenuesBundle/calendar/calendar-space.html.twig',
  953.             [
  954.                 'user' => $user->getId(),
  955.                 'connectGoogle' => $connectGoogle,
  956.                 'space' => $space,
  957.             ]
  958.         );
  959.     }
  960.     /**
  961.      * Devuelve las RESERVAS (no visitas) para FullCalendar por espacio.
  962.      *
  963.      * FullCalendar le pasa ?start=...&end=... en ISO 8601.
  964.      *
  965.      * @Route("/calendar/space/{id}/reservations", name="calendar_reservations_by_space", methods={"GET"})
  966.      */
  967.     public function calendarReservationsBySpace(int $idRequest $requestCalendarService $calendar): JsonResponse
  968.     {
  969.         $start $request->query->get('start');
  970.         $end $request->query->get('end');
  971.         $from $start ? new \DateTimeImmutable($start) : new \DateTimeImmutable('first day of this month 00:00');
  972.         $to $end ? new \DateTimeImmutable($end) : new \DateTimeImmutable('last day of next month 23:59');
  973.         $events $calendar->getReservationsForCalendar(spaceId$idloungeIdnullfrom$fromto$to);
  974.         return new JsonResponse($events);
  975.     }
  976.     /**
  977.      * @Route("/calendar/events/space/{id}", name="calendar_events_by_space", methods={"GET"})
  978.      */
  979.     public function calendarEventsBySpace(int $idRequest $requestCalendarService $calendar): JsonResponse
  980.     {
  981.         $start $request->query->get('start');
  982.         $end $request->query->get('end');
  983.         $from $start ? new \DateTimeImmutable($start) : new \DateTimeImmutable('first day of this month 00:00');
  984.         $to $end ? new \DateTimeImmutable($end) : new \DateTimeImmutable('last day of next month 23:59');
  985.         $events $calendar->getVisitsForCalendar(spaceId$idloungeIdnullfrom$fromto$to);
  986.         return new JsonResponse($events);
  987.     }
  988.     /**
  989.      * @Route("/calendar/lounge/{id}", name="calendar_by_lounge", methods={"GET"})
  990.      */
  991.     public function calendarByLoungeAction(int $idRequest $requestEntityManagerInterface $em): Response
  992.     { {
  993.             $lounge $em->getRepository(\App\MDS\VenuesBundle\Entity\ReservationLoungeDetails::class)->find($id);
  994.             if (!$lounge) {
  995.                 $this->addFlash('danger''No se ha podido encontrar el calendario para esa sala.');
  996.                 // Volver a la pantalla anterior si es del mismo host (evita open redirect)
  997.                 $referer $request->headers->get('referer');
  998.                 if ($referer && parse_url($refererPHP_URL_HOST) === $request->getHost()) {
  999.                     return $this->redirect($referer);
  1000.                 }
  1001.                 // Fallback razonable (ajusta la ruta que prefieras)
  1002.                 return $this->redirectToRoute('app_space_index');
  1003.             }
  1004.             return $this->render('MDS/VenuesBundle/calendar/calendar-lounge.html.twig', [
  1005.                 'lounge' => $lounge,
  1006.                 'currentSpaceId' => $lounge->getSpace() ? $lounge->getSpace()->getId() : null,
  1007.             ]);
  1008.         }
  1009.     }
  1010.     /**
  1011.      * RESERVAS por sala (lounge)
  1012.      * FullCalendar envía ?start=...&end=...
  1013.      * Ojo con el prefijo /venues si tu controlador lo tiene a nivel de clase.
  1014.      *
  1015.      * @Route("/calendar/lounge/{id}/reservations", name="calendar_reservations_by_lounge", methods={"GET"})
  1016.      */
  1017.     public function calendarReservationsByLounge(int $idRequest $requestCalendarService $calendar): JsonResponse
  1018.     {
  1019.         $start $request->query->get('start');
  1020.         $end $request->query->get('end');
  1021.         $from $start ? new \DateTimeImmutable($start) : new \DateTimeImmutable('first day of this month 00:00');
  1022.         $to $end ? new \DateTimeImmutable($end) : new \DateTimeImmutable('last day of next month 23:59');
  1023.         $events $calendar->getReservationsForCalendar(spaceIdnullloungeId$idfrom$fromto$to);
  1024.         return new JsonResponse($events);
  1025.     }
  1026.     /**
  1027.      * @Route("/calendar/lounge/{id}/visits", name="calendar_visits_by_lounge", methods={"GET"})
  1028.      */
  1029.     public function calendarEventsByLounge(int $idRequest $requestCalendarService $calendar): JsonResponse
  1030.     {
  1031.         $start $request->query->get('start');
  1032.         $end $request->query->get('end');
  1033.         $from $start ? new \DateTimeImmutable($start) : new \DateTimeImmutable('first day of this month 00:00');
  1034.         $to $end ? new \DateTimeImmutable($end) : new \DateTimeImmutable('last day of next month 23:59');
  1035.         $events $calendar->getVisitsForCalendar(spaceIdnullloungeId$idfrom$fromto$to);
  1036.         return new JsonResponse($events);
  1037.     }
  1038.     /**
  1039.      * @Route("/calendar/events/all", name="calendar_events_all")
  1040.      */
  1041.     public function allEvents(): Response
  1042.     {
  1043.         return $this->render('MDS/VenuesBundle/calendar/calendar-all.html.twig');
  1044.     }
  1045.     /**
  1046.      * @Route("/calendar/events/visits", name="calendar_events_visits")
  1047.      */
  1048.     public function visitsEventsAction(): Response
  1049.     {
  1050.         return $this->render('MDS/VenuesBundle/calendar/calendar-visits.html.twig');
  1051.     }
  1052.     /**
  1053.      * @Route("/", name="reservations_venues")
  1054.      */
  1055.     public function calendarReservationAction(Request $request)
  1056.     {
  1057.         // Enviar correos a los agentes de las reservas que se deban Cotizar
  1058.         $this->notificacionReservasPorCotizar();
  1059.         // Enviar correos a los agentes de las reservas que tienen depósitos pendientes por recibir
  1060.         $this->notificacionReservasPendientesDelSegundoDepósito();
  1061.         $session = new Session();
  1062.         $token $session->get('tokenGoogleCalendar');
  1063.         if (!is_null($token)) {
  1064.             $this->googleCalendar->setAccessToken($token);
  1065.             $connectGoogle "1";
  1066.         } else {
  1067.             $connectGoogle "0";
  1068.         }
  1069.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  1070.         $user_id $user_logueado->getId();
  1071.         $wnotes = new WidgetNotes();
  1072.         $wnotes->setDateAt(new \DateTime("now"));
  1073.         $form $this->createWidgetNotesCreateForm($wnotes);
  1074.         return $this->render(
  1075.             'MDS/VenuesBundle/reservations/calendar-reservations.html.twig',
  1076.             array(
  1077.                 'form' => $form->createView(),
  1078.                 'user' => $user_id,
  1079.                 'connectGoogle' => $connectGoogle,
  1080.             )
  1081.         );
  1082.     }
  1083.     private function createWidgetNotesCreateForm(WidgetNotes $entity)
  1084.     {
  1085.         $form $this->createForm(WidgetNotesType::class, $entity, array(
  1086.             'action' => $this->generateUrl('widget_notes_calendar_create'),
  1087.             'method' => 'POST'
  1088.         ));
  1089.         return $form;
  1090.     }
  1091.     /**
  1092.      * @Route("/widget/notes/calendar/create/", name="widget_notes_calendar_create")
  1093.      */
  1094.     public function addNotesAction(EntityManagerInterface $emRequest $requestLoggerInterface $logger)
  1095.     {
  1096.         $notes $em->getRepository(WidgetNotes::class)->findAll();
  1097.         $wnotes = new WidgetNotes();
  1098.         $form $this->createWidgetNotesCreateForm($wnotes);
  1099.         $form->handleRequest($request);
  1100.         $forAgent $form->get('forAgent')->getData();
  1101.         if (!is_null($forAgent)) {
  1102.             $wnotes->setForAgent($forAgent->getId());
  1103.         }
  1104.         if ($form->isValid()) {
  1105.             /* Obtengo usuario logueado */
  1106.             $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  1107.             $user_id $user_logueado->getId();
  1108.             $wnotes->setCreatedId($user_id);
  1109.             $wnotes->setUpdatedId($user_id);
  1110.             /* Gestión de eventos en Log */
  1111.             $user_lastname $user_logueado->getLastname();
  1112.             $user_name $user_logueado->getName();
  1113.             $user_email $user_logueado->getEmail();
  1114.             $user_rol $user_logueado->getRoles();
  1115.             $event_url $request->getPathInfo();
  1116.             $event_complete $user_name ' ' $user_lastname ' - ' $user_email ' - ' $user_rol[0] . ' | ' $event_url;
  1117.             try {
  1118.                 $em->persist($wnotes);
  1119.                 $em->flush();
  1120.                 $event 'The Note has been created succesfully.';
  1121.                 $successMessage $this->translator->trans($event);
  1122.                 $this->addFlash('mensaje'$successMessage);
  1123.                 $logger->info($event_complete ' | ' $event);
  1124.             } catch (\Exception $e) {
  1125.                 $event 'An error occurred: ' $e->getMessage();
  1126.                 /* Para el log */
  1127.                 $logger->error($event_complete ' | ' $event);
  1128.                 /* Para el usuario */
  1129.                 $errorMessage $this->translator->trans($event);
  1130.                 $this->addFlash('mensajeerror'$errorMessage);
  1131.             }
  1132.             /* Fin Gestión de eventos en Log */
  1133.         } else {
  1134.             $errorMessage $this->translator->trans('Error, some fields are empty');
  1135.             $this->addFlash('mensajeerror'$errorMessage);
  1136.         }
  1137.         return $this->redirectToRoute('homepage');
  1138.     }
  1139.     /**
  1140.      * @Route("/list/", defaults={"idgroup" = 0}, name="reservations_venues_index")
  1141.      */
  1142.     public function indexAction($idgroupEntityManagerInterface $emRequest $request)
  1143.     {
  1144.         return $this->render('MDS/VenuesBundle/reservations/list-reservations.html.twig', [
  1145.             'groups' => null,
  1146.             'type' => 'list',
  1147.             'titleView' => '',
  1148.             'reservations' => [], // DataTables will load data
  1149.             'dataUrl' => $this->generateUrl('reservations_venues_data', ['idgroup' => $idgroup]),
  1150.         ]);
  1151.     }
  1152.     /**
  1153.      * @Route("/list/space/{idspace}", name="reservations_venues_space_index")
  1154.      */
  1155.     public function indexSpaceAction(int $idspaceEntityManagerInterface $em)
  1156.     {
  1157.         $space $em->getRepository(Space::class)->find($idspace);
  1158.         if (!$space) {
  1159.             throw $this->createNotFoundException('Espacio no encontrado');
  1160.         }
  1161.         return $this->render('MDS/VenuesBundle/reservations/list-reservations.html.twig', [
  1162.             'groups' => null,
  1163.             'type' => 'space',
  1164.             'titleView' => ' de ' $space->getName(),
  1165.             'reservations' => [], // DataTables will load data
  1166.             'dataUrl' => $this->generateUrl('reservations_venues_space_data', ['idspace' => $idspace]),
  1167.         ]);
  1168.     }
  1169.     /**
  1170.      * @Route("/list/data/{idgroup}", defaults={"idgroup" = 0}, name="reservations_venues_data", methods={"POST", "GET"})
  1171.      */
  1172.     public function dataAction($idgroupRequest $requestEntityManagerInterface $em): JsonResponse
  1173.     {
  1174.         /** @var \App\MDS\VenuesBundle\Repository\ReservationRepository $repo */
  1175.         $repo $em->getRepository(Reservation::class);
  1176.         // Fetch ALL data
  1177.         $result $repo->findDataTablesData();
  1178.         return new JsonResponse(['data' => $this->formatDataTablesData($result)]);
  1179.     }
  1180.     /**
  1181.      * @Route("/list/space/data/{idspace}", name="reservations_venues_space_data", methods={"POST", "GET"})
  1182.      */
  1183.     public function dataSpaceAction(int $idspaceRequest $requestEntityManagerInterface $em): JsonResponse
  1184.     {
  1185.         /** @var \App\MDS\VenuesBundle\Repository\ReservationRepository $repo */
  1186.         $repo $em->getRepository(Reservation::class);
  1187.         // Fetch data filtered by Space
  1188.         $result $repo->findDataTablesData($idspace);
  1189.         return new JsonResponse(['data' => $this->formatDataTablesData($result)]);
  1190.     }
  1191.     /**
  1192.      * Auxiliar para formatear datos de DataTables (DRY)
  1193.      */
  1194.     private function formatDataTablesData(array $result): array
  1195.     {
  1196.         $data = [];
  1197.         foreach ($result as $row) {
  1198.             // Helper for Date formatting
  1199.             $fmtDate = function ($d) {
  1200.                 return $d instanceof \DateTimeInterface $d->format('d/m/Y') : '';
  1201.             };
  1202.             $fmtYMD = function ($d) {
  1203.                 return $d instanceof \DateTimeInterface $d->format('Y/m/d') : '';
  1204.             };
  1205.             $getTimestamp = function ($d) {
  1206.                 return $d instanceof \DateTimeInterface $d->getTimestamp() : 0;
  1207.             };
  1208.             // Date Start Logic
  1209.             $dateStartDisplay $fmtDate($row['dateStart']);
  1210.             $dateStartTimestamp $getTimestamp($row['dateStart']);
  1211.             if ($row['dateStart'] instanceof \DateTimeInterface && $fmtYMD($row['dateStart']) === '2078/01/01') {
  1212.                 $dateStartDisplay 'SIN ASIGNAR';
  1213.                 $dateStartTimestamp 0;
  1214.             }
  1215.             // Date End Logic
  1216.             $dateEndDisplay $fmtDate($row['dateEnd']);
  1217.             $dateEndTimestamp $getTimestamp($row['dateEnd']);
  1218.             if ($row['dateEnd'] instanceof \DateTimeInterface && $fmtYMD($row['dateEnd']) === '2000/01/01') {
  1219.                 $dateEndDisplay 'SIN ASIGNAR';
  1220.                 $dateEndTimestamp 0;
  1221.             }
  1222.             $statusLabel = match ($row['status']) {
  1223.                 'Bloqueo' => 'BLOQUEO',
  1224.                 'Confirmed' => 'CONFIRMADO',
  1225.                 'Invoiced' => 'FACTURADO',
  1226.                 'Cotizado' => 'COTIZADO',
  1227.                 'Deleted' => 'CANCELADO',
  1228.                 default => 'INICIADO',
  1229.             };
  1230.             $actions '<div class="btn-group">
  1231.                             <a href="/venues/edit/' $row['id'] . '" class="btn btn-sm bg-btn-vivid_sky_blue">
  1232.                                 <i class="glyphicon glyphicon-pencil"></i>
  1233.                             </a>
  1234.                             <a href="/venues/delete/' $row['id'] . '" class="btn btn-sm bg-btn-trash">
  1235.                                 <i class="glyphicon glyphicon-trash"></i>
  1236.                             </a>
  1237.                         </div>';
  1238.             $data[] = [
  1239.                 'createdAt' => [
  1240.                     'display' => $fmtDate($row['createdAt']),
  1241.                     'timestamp' => $getTimestamp($row['createdAt'])
  1242.                 ],
  1243.                 'id' => $row['id'],
  1244.                 'dateStart' => [
  1245.                     'display' => $dateStartDisplay,
  1246.                     'timestamp' => $dateStartTimestamp
  1247.                 ],
  1248.                 'dateEnd' => [
  1249.                     'display' => $dateEndDisplay,
  1250.                     'timestamp' => $dateEndTimestamp
  1251.                 ],
  1252.                 'title' => $row['title'],
  1253.                 'client' => $row['clientName'],
  1254.                 'createdBy' => $row['creatorName'],
  1255.                 'status' => $statusLabel,
  1256.                 'actions' => $actions
  1257.             ];
  1258.         }
  1259.         return $data;
  1260.     }
  1261.     /**
  1262.      * @Route("/listcanceled/{idgroup}", defaults={"idgroup" = 0}, name="reservations_canceled")
  1263.      */
  1264.     public function indexCanceledAction(EntityManagerInterface $em$idgroupRequest $request)
  1265.     {
  1266.         return $this->render(
  1267.             'MDS/VenuesBundle/reservations/list-reservations.html.twig',
  1268.             array(
  1269.                 'groups' => null,
  1270.                 'type' => 'canceled',
  1271.                 'titleView' => ' Canceladas',
  1272.                 'reservations' => [],
  1273.                 'dataUrl' => $this->generateUrl('reservations_canceled_data', ['idgroup' => $idgroup])
  1274.             )
  1275.         );
  1276.     }
  1277.     /**
  1278.      * @Route("/list/canceled/data/{idgroup}", defaults={"idgroup" = 0}, name="reservations_canceled_data", methods={"POST", "GET"})
  1279.      */
  1280.     public function canceledDataAction($idgroupRequest $requestEntityManagerInterface $em): JsonResponse
  1281.     {
  1282.         /** @var \App\MDS\VenuesBundle\Repository\ReservationRepository $repo */
  1283.         $repo $em->getRepository(Reservation::class);
  1284.         // Fetch ALL data (Client-side handling)
  1285.         $result $repo->findDataTablesCanceledData();
  1286.         $data = [];
  1287.         foreach ($result as $row) {
  1288.             // Helper for Date formatting
  1289.             $fmtDate = function ($d) {
  1290.                 return $d instanceof \DateTimeInterface $d->format('d/m/Y') : '';
  1291.             };
  1292.             $fmtYMD = function ($d) {
  1293.                 return $d instanceof \DateTimeInterface $d->format('Y/m/d') : '';
  1294.             };
  1295.             $getTimestamp = function ($d) {
  1296.                 return $d instanceof \DateTimeInterface $d->getTimestamp() : 0;
  1297.             };
  1298.             // Date Start Logic
  1299.             $dateStartDisplay $fmtDate($row['dateStart']);
  1300.             $dateStartTimestamp $getTimestamp($row['dateStart']);
  1301.             if ($row['dateStart'] instanceof \DateTimeInterface && $fmtYMD($row['dateStart']) === '2078/01/01') {
  1302.                 $dateStartDisplay 'SIN ASIGNAR';
  1303.                 $dateStartTimestamp 0;
  1304.             }
  1305.             // Date End Logic
  1306.             $dateEndDisplay $fmtDate($row['dateEnd']);
  1307.             $dateEndTimestamp $getTimestamp($row['dateEnd']);
  1308.             if ($row['dateEnd'] instanceof \DateTimeInterface && $fmtYMD($row['dateEnd']) === '2000/01/01') {
  1309.                 $dateEndDisplay 'SIN ASIGNAR';
  1310.                 $dateEndTimestamp 0;
  1311.             }
  1312.             // Status is always Deleted
  1313.             $statusLabel 'CANCELADO';
  1314.             $actions '<div class="btn-group">
  1315.                             <a href="/venues/edit/' $row['id'] . '" class="btn btn-sm bg-btn-vivid_sky_blue">
  1316.                                 <i class="glyphicon glyphicon-pencil"></i>
  1317.                             </a>
  1318.                             <a href="/venues/delete/' $row['id'] . '" class="btn btn-sm bg-btn-trash">
  1319.                                 <i class="glyphicon glyphicon-trash"></i>
  1320.                             </a>
  1321.                         </div>';
  1322.             $data[] = [
  1323.                 'createdAt' => [
  1324.                     'display' => $fmtDate($row['createdAt']),
  1325.                     'timestamp' => $getTimestamp($row['createdAt'])
  1326.                 ],
  1327.                 'id' => $row['id'],
  1328.                 'dateStart' => [
  1329.                     'display' => $dateStartDisplay,
  1330.                     'timestamp' => $dateStartTimestamp
  1331.                 ],
  1332.                 'dateEnd' => [
  1333.                     'display' => $dateEndDisplay,
  1334.                     'timestamp' => $dateEndTimestamp
  1335.                 ],
  1336.                 'title' => $row['title'],
  1337.                 'client' => $row['clientName'],
  1338.                 'createdBy' => $row['creatorName'],
  1339.                 'status' => $statusLabel,
  1340.                 'actions' => $actions
  1341.             ];
  1342.         }
  1343.         return new JsonResponse(['data' => $data]);
  1344.     }
  1345.     /**
  1346.      * @Route("/listquoted/{idgroup}", defaults={"idgroup" = 0}, name="reservations_quoted")
  1347.      */
  1348.     public function indexQuotedAction(EntityManagerInterface $em$idgroupRequest $request)
  1349.     {
  1350.         $parameters = array('status' => 'Cotizado');
  1351.         $dql 'SELECT i
  1352.                 FROM VenuesBundle:Reservation i
  1353.                 WHERE i.status = :status
  1354.                 ORDER BY i.createdAt ASC';
  1355.         $query $em->createQuery($dql)->setParameters($parameters);
  1356.         $ref = array();
  1357.         $reservas $query->getResult();
  1358.         foreach ($reservas as $res) {
  1359.             $client $em->getRepository(Client::class)->findOneById($res->getClient());
  1360.             if (!empty($client)) {
  1361.                 $res->setClient($client->getName());
  1362.             } else {
  1363.                 $res->setClient(null);
  1364.             }
  1365.             $res->setCreatedBy(
  1366.                 ($em->getRepository(User::class)->findOneById($res->getCreatedBy()))->getName() . ' ' .
  1367.                 ($em->getRepository(User::class)->findOneById($res->getCreatedBy()))->getLastName()
  1368.             );
  1369.             $ref[$res->getId()] = '#' . ($res->getCreatedAt())->format('ymdHi');
  1370.         }
  1371.         $reservasZero = array();
  1372.         foreach ($reservas as $res) {
  1373.             $data $this->CalculosTotalesEditSimple($res->getId());
  1374.             $reservasZero[] = array(
  1375.                 'dateStart' => $res->getDateStart(),
  1376.                 'dateEnd' => $res->getDateEnd(),
  1377.                 'id' => $res->getId(),
  1378.                 'title' => $res->getTitle(),
  1379.                 'client' => $res->getClient(),
  1380.                 'sales' => $data['sumatoria_totales_global_con_iva'],
  1381.                 'ref' => $ref[$res->getId()],
  1382.                 'createdAt' => $res->getCreatedAt(),
  1383.             );
  1384.         }
  1385.         $reservas $reservasZero;
  1386.         return $this->render(
  1387.             'MDS/VenuesBundle/reservations/list-reservations-quotation.html.twig',
  1388.             array(
  1389.                 'groups' => null,
  1390.                 'titleView' => ' Cotizadas',
  1391.                 'reservations' => $reservas
  1392.             )
  1393.         );
  1394.     }
  1395.     /**
  1396.      * @Route("/edit/{id}", name="reservations_venues_edit")
  1397.      */
  1398.     public function editAction($id)
  1399.     {
  1400.         return $this->redirectToRoute('reservations_venues_edit_simple', array('id' => $id'token' => null));
  1401.     }
  1402.     private function createEditReservationsForm(Reservation $entity$id)
  1403.     {
  1404.         $form $this->createForm(ReservationType::class, $entity, array('action' => $this->generateUrl('reservations_update', array('id' => $id)), 'method' => 'PUT'));
  1405.         return $form;
  1406.     }
  1407.     /**
  1408.      * @Route("/update/{id}", name="reservations_update")
  1409.      */
  1410.     public function update(int $idRequest $requestEntityManagerInterface $emSecurity $securityTranslatorInterface $translatorDocContractService $docContractService): Response
  1411.     {
  1412.         $reserva $em->getRepository(Reservation::class)->find($id);
  1413.         // --- 1. ELIMINADO EL DD($request) PARA QUE EJECUTE EL GUARDADO ---
  1414.         if (!$reserva) {
  1415.             throw $this->createNotFoundException('Reserva no encontrada');
  1416.         }
  1417.         // 1. Guardar estados previos necesarios para lógica de negocio
  1418.         $oldPriority $reserva->getPriority();
  1419.         $oldStatus $reserva->getStatus();
  1420.         $user $security->getUser();
  1421.         // 2. Crear formulario pasando las opciones necesarias
  1422.         $invoiceRepository $em->getRepository(ReservationInvoice::class);
  1423.         $invoiceRecRepository $em->getRepository(ReservationInvoiceRec::class);
  1424.         $hasInvoices = !empty($invoiceRepository->findByReservationId($id)) || !empty($invoiceRecRepository->findByReservationId($id));
  1425.         $form $this->createForm(ReservationType::class, $reserva, [
  1426.             'confirmable' => $this->laReservaEsConfirmable($id),
  1427.             'cotizable' => $this->laReservaEsCotizable($id),
  1428.             'invoiced' => $hasInvoices,
  1429.         ]);
  1430.         $dateStart = clone ($reserva->getDateStart());
  1431.         $dateEnd = clone ($reserva->getDateEnd());
  1432.         $form->handleRequest($request);
  1433.         $reserva->setDateStart($dateStart);
  1434.         $reserva->setDateEnd($dateEnd);
  1435.         if ($form->isSubmitted() && $form->isValid()) {
  1436.             /** @var Reservation $reserva */
  1437.             $reserva $form->getData();
  1438.             $now = new \DateTime();
  1439.             // 3. Auditoría básica
  1440.             $reserva->setUpdatedBy($user->getId());
  1441.             $reserva->setUpdatedAt($now);
  1442.             // 4. Lógica de Prioridad
  1443.             if ($this->isGranted('ROLE_USER') && !$this->isGranted('ROLE_ADMIN')) {
  1444.                 $reserva->setPriority($oldPriority);
  1445.             }
  1446.             if (!$reserva->getPriority()) {
  1447.                 $reserva->setPriority(1);
  1448.             }
  1449.             // 5. Manejo de Contacto No Registrado
  1450.             // ESTA FUNCIÓN ES LA QUE GUARDA EN BASE DE DATOS EL CONTACTO NUEVO
  1451.             $this->handleUnregisteredContact($form$reserva$user$em);
  1452.             // 6. Manejo de Status "Bloqueo"
  1453.             $newStatusFromForm $reserva->getStatus();
  1454.             $this->handleBlockStatus($form$reserva$user$em);
  1455.             // 7. Verificación final de Status
  1456.             $verifiedStatus $this->verificarStatusInicialyFinal($id$user->getId(), $oldStatus$newStatusFromForm);
  1457.             $reserva->setStatus($verifiedStatus);
  1458.             // 8. Lógica de Cancelación
  1459.             if ($verifiedStatus === 'Deleted' && $verifiedStatus !== 'Bloqueo') {
  1460.                 $this->handleCancellationAlert($id$reserva$em);
  1461.             }
  1462.             // 9. Recalcular fechas
  1463.             $this->reservationService->updateReservationDates($reserva);
  1464.             // 10. Valores por defecto
  1465.             if (!$reserva->getStatus()) {
  1466.                 $reserva->setStatus('Cotizado');
  1467.             }
  1468.             try {
  1469.                 $em->persist($reserva);
  1470.                 $em->flush();
  1471.                 $data $this->sincGpHtAvService->sincGlobalGpHtAv($id);
  1472.                 $this->addFlash('mensajereservation''La reserva ha sido actualizada.');
  1473.                 // --- ACTUALIZACIÓN DE LA AGENDA ---
  1474.                 $agendaLineTitle $em->getRepository(ReservationAgendaItem::class)->findBy(array('reservationId' => $reserva->getId(), 'sourceType' => 'Reservation'));
  1475.                 $user $this->getUser();
  1476.                 if (empty($agendaLineTitle)) {
  1477.                     // Creamos la linea
  1478.                     $newItem = new ReservationAgendaItem();
  1479.                     $newItem->setReservationId($id);
  1480.                     $newItem->setRankListing(1);
  1481.                     $newItem->setTitleOne('EVENTO: ' $reserva->getTitle());
  1482.                     $newItem->setTitleTwo(null);
  1483.                     $newItem->setTitleThree(null);
  1484.                     $newItem->setDescription('.');
  1485.                     $newItem->setSourceId($id);
  1486.                     $newItem->setSourceType('Reservation');
  1487.                     $newItem->setCreatedId($user->getId());
  1488.                     $newItem->setUpdatedId($user->getId());
  1489.                     $newItem->setCreatedAt(new \DateTime());
  1490.                     $newItem->setUpdatedAt(new \DateTime());
  1491.                     $this->repository->add($newItemtrue);
  1492.                 } else {
  1493.                     // Actualizamos la linea
  1494.                     $agendaLineTitle[0]->setTitleOne('EVENTO: ' $reserva->getTitle());
  1495.                     $agendaLineTitle[0]->setUpdatedId($user->getId());
  1496.                     $agendaLineTitle[0]->setUpdatedAt(new \DateTime());
  1497.                     $this->repository->add($agendaLineTitle[0], true);
  1498.                 }
  1499.                 // --- CORRECCIÓN IMPORTANTE AQUÍ ---
  1500.                 // Leemos los datos DEL FORMULARIO, no de la entidad reserva,
  1501.                 // porque son campos mapped => false
  1502.                 $nameUnreg $form->get('nameContactUnregistered')->getData();
  1503.                 $phoneUnreg $form->get('phoneContactUnregistered')->getData();
  1504.                 $emailUnreg $form->get('contactUnregistered')->getData();
  1505.                 $contactString '';
  1506.                 if (!empty($nameUnreg)) {
  1507.                     $contactString .= $nameUnreg;
  1508.                 } else {
  1509.                     $contactString .= 'No se pudo determinar el nombre';
  1510.                 }
  1511.                 if (!empty($phoneUnreg)) {
  1512.                     $contactString .= ' / ' $phoneUnreg;
  1513.                 } else {
  1514.                     $contactString .= ' / No se pudo determinar el teléfono';
  1515.                 }
  1516.                 if (!empty($emailUnreg)) {
  1517.                     $contactString .= ' / ' $emailUnreg;
  1518.                 } else {
  1519.                     $contactString .= ' / No se pudo determinar el email';
  1520.                 }
  1521.                 $agenda $this->agendaService->updateClientContactLine($reserva->getId(), $contactString$user->getId());
  1522.                 // ----------------------------------
  1523.                 // 11. Redirecciones especiales post-guardado
  1524.                 if ($verifiedStatus === 'Confirmed') {
  1525.                     $this->_actualizarSalasYServicios($reserva);
  1526.                     // Asignación automática de contratos
  1527.                     $docContractService->autoAssignContracts($reserva$user);
  1528.                     
  1529.                     if ($verifiedStatus !== $oldStatus) {
  1530.                         return $this->redirectToRoute('reservations_venues_send_confirmation_request_mail', ['id' => $id]);
  1531.                     }
  1532.                 }
  1533.                 $this->_actualizarSalasYServicios($reserva);
  1534.                 return $this->redirectToRoute('reservations_venues_edit_simple', ['id' => $id'token' => null]);
  1535.             } catch (\Exception $e) {
  1536.                 $this->addFlash('mensajereservationerror'$translator->trans('An error occurred: ' $e->getMessage()));
  1537.             }
  1538.         }
  1539.         return $this->redirectToRoute('reservations_venues_edit_simple', ['id' => $id'token' => null]);
  1540.     }
  1541.     /**
  1542.      * @Route("/delete/{id}", name="reservations_delete")
  1543.      */
  1544.     public function deleteAction($idEntityManagerInterface $emRequest $request)
  1545.     {
  1546.         $reserva $em->getRepository(Reservation::class)->findOneById($id);
  1547.         $hoy = new \DateTime("now"NULL);
  1548.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  1549.         $user_id $user_logueado->getId();
  1550.         $reserva->setUpdatedBy($user_id);
  1551.         $reserva->setUpdatedAt($hoy);
  1552.         $reserva->setStatus('Deleted');
  1553.         try {
  1554.             $em->persist($reserva);
  1555.             $em->flush();
  1556.             $data $this->sincGpHtAvService->sincGlobalGpHtAv($id);
  1557.             $successMessage 'La reserva ha sido actualizada.';
  1558.             $this->addFlash('mensajereservation'$successMessage);
  1559.         } catch (\Exception $e) {
  1560.             $event 'An error occurred: ' $e->getMessage();
  1561.             $errorMessage $this->translator->trans($event);
  1562.             $this->addFlash('mensajereservationerror'$errorMessage);
  1563.         }
  1564. //        return $this->redirectToRoute('reservations_venues_index');
  1565.         return $this->redirectToRoute('reservations_venues_edit_simple', ['id' => $id'token' => null]);
  1566.     }
  1567.     /**
  1568.      * @Route("/listgpprices", name="reservations_venues_prices")
  1569.      */
  1570.     public function indexPricesAction(EntityManagerInterface $emRequest $request)
  1571.     {
  1572.         $prices $em->getRepository(ReservationLoungeProfile::class)->findBy(
  1573.             array(),
  1574.             array('id' => 'ASC')
  1575.         );
  1576.         $data = [];
  1577.         foreach ($prices as $price) {
  1578.             $periodSql $em->getRepository(ReservationPeriod::class)->findOneById($price->getPeriodId());
  1579.             $price->setPeriodId($periodSql->getName());
  1580.             $reservationsLoungeTemp $em->getRepository(ReservationLoungeDetails::class)->findOneById($price->getLoungeId());
  1581.             if (!is_null($reservationsLoungeTemp)) {
  1582.                 $price->setLoungeId($reservationsLoungeTemp->getName());
  1583.             }
  1584.             $data[] = $price;
  1585.         }
  1586.         $reserv = new ReservationLoungeProfile();
  1587.         $form $this->createReservationLoungeProfileCreateForm($reserv);
  1588.         return $this->render(
  1589.             'MDS/VenuesBundle/reservations/list-reservations-gp-prices.html.twig',
  1590.             array(
  1591.                 'groups' => null,
  1592.                 'prices' => $data,
  1593.                 'form' => $form->createView()
  1594.             )
  1595.         );
  1596.     }
  1597.     /**
  1598.      * @Route("/deletegpprice/{id}", name="reservations_price_delete")
  1599.      */
  1600.     public function deletePriceAction($idEntityManagerInterface $emRequest $request)
  1601.     {
  1602.         $price $em->getRepository(ReservationLoungeProfile::class)->findOneById($id);
  1603.         try {
  1604.             $em->remove($price);
  1605.             $em->flush();
  1606.             $event 'The Item has been Deleted.';
  1607.             $successMessage $this->translator->trans($event);
  1608.             $this->addFlash('mensajereservation'$successMessage);
  1609.         } catch (\Exception $e) {
  1610.             $event 'An error occurred: ' $e->getMessage();
  1611.             /* Para el usuario */
  1612.             $errorMessage $this->translator->trans($event);
  1613.             $this->addFlash('mensajereservationerror'$errorMessage);
  1614.         }
  1615.         return $this->redirectToRoute('reservations_venues_prices');
  1616.     }
  1617.     /**
  1618.      * @Route("/addgpprice/",  name="reservations_venues_addgpprice")
  1619.      */
  1620.     public function addReservationGpPriceAction(EntityManagerInterface $emRequest $request)
  1621.     {
  1622.         $reserv = new ReservationLoungeProfile();
  1623.         $form $this->createReservationLoungeProfileCreateForm($reserv);
  1624.         $gpPrices $em->getRepository(ReservationLoungeProfile::class)->findAll();
  1625.         return $this->render('MDS/VenuesBundle/reservations/add-reservations-gp-price.html.twig', array('form' => $form->createView(), 'gpPrices' => $gpPrices));
  1626.     }
  1627.     private function createReservationLoungeProfileCreateForm(ReservationLoungeProfile $entity)
  1628.     {
  1629.         $form $this->createForm(ReservationLoungeProfileType::class, $entity, array(
  1630.             'action' => $this->generateUrl('reservations_venues_price_create'),
  1631.             'method' => 'POST'
  1632.         ));
  1633.         return $form;
  1634.     }
  1635.     /**
  1636.      * @Route("/creategpprice", name="reservations_venues_price_create")
  1637.      */
  1638.     public function createGpPriceAction(EntityManagerInterface $emRequest $request)
  1639.     {
  1640.         $reservaGpPrice = new ReservationLoungeProfile();
  1641.         $form $this->createReservationLoungeProfileCreateForm($reservaGpPrice);
  1642.         $form->handleRequest($request);
  1643.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  1644.         $user_id $user_logueado->getId();
  1645.         $hoy = new \DateTime("now"NULL);
  1646.         $reservaGpPrice->setCreatedAt($hoy);
  1647.         $reservaGpPrice->setCreatedId($user_id);
  1648.         $reservaGpPrice->setUpdatedAt($hoy);
  1649.         $reservaGpPrice->setUpdatedId($user_id);
  1650.         $periodSql $em->getRepository(ReservationPeriod::class)->findOneById($form->get('periodId')->getData());
  1651.         if (!empty($periodSql)) {
  1652.             $descTemp $periodSql->getName();
  1653.         } else {
  1654.             $descTemp null;
  1655.         }
  1656.         $reservaGpPrice->setPeriodId($reservaGpPrice->getPeriodId()->getId());
  1657.         $reservaGpPrice->setLoungeId($reservaGpPrice->getLoungeId()->getId());
  1658.         if ((!is_null($reservaGpPrice->getLoungeId())) and (!is_null($descTemp))) {
  1659.             $descriptionSql $em->getRepository(ReservationLoungeDetails::class)->findOneById($form->get('loungeId')->getData());
  1660.             $description $descriptionSql->getName() . ' - ' $descTemp;
  1661.             $reservaGpPrice->setDescription($description);
  1662.         } else {
  1663.             $reservaGpPrice->setDescription(null);
  1664.         }
  1665.         if ($form->isValid()) {
  1666.             try {
  1667.                 $em->persist($reservaGpPrice);
  1668.                 $em->flush();
  1669.                 $event 'The Item Price has been created.';
  1670.                 $successMessage $this->translator->trans($event);
  1671.                 $this->addFlash('mensajereservation'$successMessage);
  1672.             } catch (\Exception $e) {
  1673.                 $event 'An error occurred: ' $e->getMessage();
  1674.                 $errorMessage $this->translator->trans($event);
  1675.                 $this->addFlash('mensajereservationerror'$errorMessage);
  1676.             }
  1677.         } else {
  1678.             $errorMessage $this->translator->trans('Error, some fields are empty');
  1679.             $this->addFlash('mensajereservationerror'$errorMessage);
  1680.         }
  1681.         return $this->redirectToRoute('reservations_venues_prices');
  1682.     }
  1683.     /**
  1684.      * @Route("/getReservationLoungeProfile", name="get_reservation_lounge_profile")
  1685.      */
  1686.     public function getReservationLoungeProfileAction(EntityManagerInterface $emRequest $request)
  1687.     {
  1688.         $codProfile $_POST['idprofile'];
  1689.         $salasPorPerfil $em->getRepository(ReservationLoungeProfile::class)->findBy(array('periodId' => $codProfile));
  1690.         $datos = [];
  1691.         if (!empty($salasPorPerfil)) {
  1692.             foreach ($salasPorPerfil as $sala) {
  1693.                 $datos[] = array(
  1694.                     "id" => $sala->getId(),
  1695.                     "idlounge" => $sala->getLoungeId(),
  1696.                     "nameDescription" => $sala->getDescription(),
  1697.                     "price" => $sala->getPrice(),
  1698.                 );
  1699.             }
  1700.         }
  1701.         $return = array('salasPerfil' => $datos'id' => $codProfile, );
  1702.         $response = new JsonResponse($return);
  1703.         return $response;
  1704.     }
  1705.     /**
  1706.      * @Route("/getReservationPeriod", name="get_reservation_Period")
  1707.      */
  1708.     public function getReservationPeriodAction(EntityManagerInterface $emRequest $request)
  1709.     {
  1710.         $id $_POST['id'];
  1711.         $period $em->getRepository(ReservationPeriod::class)->findOneById($id);
  1712.         $datos = array();
  1713.         if (!empty($period)) {
  1714.             $datos = array(
  1715.                 "id" => $period->getId(),
  1716.                 "hourStart" => is_null($period->getHourStart()) ? "" $period->getHourStart()->format('H:i'),
  1717.                 "hourEnd" => is_null($period->getHourEnd()) ? "" $period->getHourEnd()->format('H:i'),
  1718.             );
  1719.         }
  1720.         $return $datos;
  1721.         $response = new JsonResponse($return);
  1722.         return $response;
  1723.     }
  1724.     /**
  1725.      * @Route("/getReservationLoungePrice", name="get_reservation_lounge_price")
  1726.      */
  1727.     public function getReservationLoungePriceAction(EntityManagerInterface $emRequest $request)
  1728.     {
  1729.         $id $_POST['id'];
  1730.         $precio $em->getRepository(ReservationLoungeProfile::class)->findOneById($id);
  1731.         $datos = array();
  1732.         if (!empty($precio)) {
  1733.             $datos = array("id" => $precio->getId(), "price" => $precio->getPrice());
  1734.         }
  1735.         $return $datos;
  1736.         $response = new JsonResponse($return);
  1737.         return $response;
  1738.     }
  1739.     /**
  1740.      * @Route("/addloungedetails/",  name="reservations_venues_addloungedetails")
  1741.      */
  1742.     public function addReservationLoungeDetailsAction(Request $request)
  1743.     {
  1744.         $reservationsLounge = new ReservationLoungeDetails();
  1745.         $form $this->createReservationLoungeDetailsCreateForm($reservationsLounge);
  1746.         return $this->render('MDS/VenuesBundle/reservations/add-reservations-lounge-details.html.twig', array('form' => $form->createView()));
  1747.     }
  1748.     private function createReservationLoungeDetailsCreateForm(ReservationLoungeDetails $entity)
  1749.     {
  1750.         $form $this->createForm(ReservationLoungeDetailsType::class, $entity, array(
  1751.             'action' => $this->generateUrl('reservations_venues_lounge_details_create'),
  1752.             'method' => 'POST'
  1753.         ));
  1754.         return $form;
  1755.     }
  1756.     /**
  1757.      * @Route("/createloungedetails", name="reservations_venues_lounge_details_create")
  1758.      */
  1759.     public function createLoungeDetailsAction(EntityManagerInterface $emRequest $request)
  1760.     {
  1761.         $reservationsLounge = new ReservationLoungeDetails();
  1762.         $form $this->createReservationLoungeDetailsCreateForm($reservationsLounge);
  1763.         $form->handleRequest($request);
  1764.         /* Obtengo usuario logueado */
  1765.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  1766.         $user_id $user_logueado->getId();
  1767.         $hoy = new \DateTime("now"NULL);
  1768.         $reservationsLounge->setCreatedAt($hoy);
  1769.         $reservationsLounge->setCreatedId($user_id);
  1770.         $reservationsLounge->setUpdatedAt($hoy);
  1771.         $reservationsLounge->setUpdatedId($user_id);
  1772.         if ($form->isValid()) {
  1773.             try {
  1774.                 $em->persist($reservationsLounge);
  1775.                 $em->flush();
  1776.                 $event 'The Lounge has been created.';
  1777.                 $successMessage $this->translator->trans($event);
  1778.                 $this->addFlash('mensajereservation'$successMessage);
  1779.                 $this->reordenarSalas($reservationsLounge->getRankLounge(), $reservationsLounge->getId());
  1780.             } catch (\Exception $e) {
  1781.                 $event 'An error occurred: ' $e->getMessage();
  1782.                 /* Para el usuario */
  1783.                 $errorMessage $this->translator->trans($event);
  1784.                 $this->addFlash('mensajereservationerror'$errorMessage);
  1785.             }
  1786.         } else {
  1787.             $errorMessage $this->translator->trans('Error, some fields are empty');
  1788.             $this->addFlash('mensajereservationerror'$errorMessage);
  1789.         }
  1790.         return $this->redirectToRoute('reservations_venues_list_lounges');
  1791.     }
  1792.     /**
  1793.      * @Route("/listloungedetails", name="reservations_venues_list_lounges")
  1794.      */
  1795.     public function indexLoungesAction(EntityManagerInterface $emRequest $request)
  1796.     {
  1797.         $salas $em->getRepository(ReservationLoungeDetails::class)->findAll();
  1798.         $reservationsLounge = new ReservationLoungeDetails();
  1799.         $form $this->createReservationLoungeDetailsCreateForm($reservationsLounge);
  1800.         return $this->render(
  1801.             'MDS/VenuesBundle/reservations/list-reservations-lounges-details.html.twig',
  1802.             array(
  1803.                 'groups' => null,
  1804.                 'salas' => $salas,
  1805.                 'form' => $form->createView()
  1806.             )
  1807.         );
  1808.     }
  1809.     /**
  1810.      * @Route("/editloungedetails/{id}", name="reservations_lounge_details")
  1811.      */
  1812.     public function editLoungeDetailsAction($idEntityManagerInterface $emRequest $request)
  1813.     {
  1814.         $reservationsLounge $em->getRepository(ReservationLoungeDetails::class)->findOneById($id);
  1815.         $reservationsLoungePictures $em->getRepository(ReservationLoungePicture::class)->findBy(array('loungeId' => $id'title' => null, ));
  1816.         $reservationsLoungeVideos $em->getRepository(ReservationLoungeVideo::class)->findByLoungeId($id);
  1817.         $reservationsLoungeDescriptions $em->getRepository(ReservationLoungeDescription::class)->findByLoungeId($id);
  1818.         $reservationsLoungeWebDescriptions $em->getRepository(ReservationLoungeWebDescription::class)->findByLounge($reservationsLounge);
  1819.         $descriptionsByLanguage = [];
  1820.         foreach ($reservationsLoungeWebDescriptions as $description) {
  1821.             $descriptionsByLanguage[$description->getLanguage()] = $description;
  1822.         }
  1823.         /* Obtengo usuario logueado */
  1824.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  1825.         $user_id $user_logueado->getId();
  1826.         /* Gestión de eventos en Log */
  1827.         $user_lastname $user_logueado->getLastname();
  1828.         $user_name $user_logueado->getName();
  1829.         $user_email $user_logueado->getEmail();
  1830.         $user_rol $user_logueado->getRoles();
  1831.         $event_url $request->getPathInfo();
  1832.         $event_complete $user_name ' ' $user_lastname ' - ' $user_email ' - ' $user_rol[0] . ' | ' $event_url;
  1833.         $hoy = new \DateTime("now"NULL);
  1834.         $form $this->createEditReservationLoungeDetailsForm($reservationsLounge$id);
  1835.         // Para evitar le duplicidad de idiomas en las descripciones
  1836.         $reservationsLoungeDescriptionsPreexistentes $em->getRepository(ReservationLoungeDescription::class)->findByLoungeId($id);
  1837.         $idiomasPreexistentes = array();
  1838.         foreach ($reservationsLoungeDescriptionsPreexistentes as $item) {
  1839.             $idiomasPreexistentes[] = $item->getLanguage();
  1840.         }
  1841.         $datos_videos = array();
  1842.         foreach ($reservationsLoungeVideos as $video) {
  1843.             $urvideo_final '<iframe class="embed-responsive-item" src="' $video->getVideo() . '"></iframe>';
  1844.             $datos_videos[] = array(
  1845.                 'id' => $video->getId(),
  1846.                 'urlvideo' => $urvideo_final
  1847.             );
  1848.         }
  1849.         $blueprints $em->getRepository(ReservationLoungePicture::class)->findBy(array('loungeId' => $id'title' => 'Blueprint', ));
  1850.         $pictTeatro $em->getRepository(ReservationLoungePicture::class)->findBy(array('loungeId' => $id'title' => 'Teatro', ));
  1851.         if (sizeof($pictTeatro) == 0) {
  1852.             $pictTeatro null;
  1853.         }
  1854.         $pictCoctel $em->getRepository(ReservationLoungePicture::class)->findBy(array('loungeId' => $id'title' => 'Coctel', ));
  1855.         if (sizeof($pictCoctel) == 0) {
  1856.             $pictCoctel null;
  1857.         }
  1858.         $pictEscuela $em->getRepository(ReservationLoungePicture::class)->findBy(array('loungeId' => $id'title' => 'Escuela', ));
  1859.         if (sizeof($pictEscuela) == 0) {
  1860.             $pictEscuela null;
  1861.         }
  1862.         $picsMontaje = array(
  1863.             'pictTeatro' => $pictTeatro,
  1864.             'pictCoctel' => $pictCoctel,
  1865.             'pictEscuela' => $pictEscuela
  1866.         );
  1867.         if (empty($picsMontaje['pictTeatro']) and empty($picsMontaje['pictCoctel']) and empty($picsMontaje['pictEscuela'])) {
  1868.             $picsMontaje null;
  1869.         }
  1870.         $reservationsLoungedimmensions $em->getRepository(ReservationLoungeDetails::class)->findOneById($id);
  1871.         return $this->render(
  1872.             'MDS/VenuesBundle/reservations/edit-reservations-lounge-details.html.twig',
  1873.             array(
  1874.                 'id' => $id,
  1875.                 'hoy' => $hoy,
  1876.                 'lounge' => $reservationsLounge,
  1877.                 'descriptions' => $reservationsLoungeDescriptions,
  1878.                 'loungeWebDesctiptions' => $descriptionsByLanguage,
  1879.                 'languagesWeb' => LanguageConstants::getAvailableLanguages(),
  1880.                 'pictures' => $reservationsLoungePictures,
  1881.                 'blueprints' => $blueprints,
  1882.                 'picsMontaje' => $picsMontaje,
  1883.                 'loungedimmensions' => $reservationsLoungedimmensions,
  1884.                 'videos' => $datos_videos,
  1885.                 'idiomasPreexistentes' => $idiomasPreexistentes,
  1886.                 'form' => $form->createView()
  1887.             )
  1888.         );
  1889.     }
  1890.     private function createEditReservationLoungeDetailsForm(ReservationLoungeDetails $entity$id)
  1891.     {
  1892.         $form $this->createForm(
  1893.             ReservationLoungeDetailsType::class,
  1894.             $entity,
  1895.             array(
  1896.                 'action' => $this->generateUrl(
  1897.                     'reservations_lounge_details_update',
  1898.                     array(
  1899.                         'id' => $id,
  1900.                         'price' => $entity
  1901.                     )
  1902.                 ),
  1903.                 'method' => 'PUT'
  1904.             )
  1905.         );
  1906.         return $form;
  1907.     }
  1908.     /**
  1909.      * @Route("/updateloungedetails/{id}", name="reservations_lounge_details_update")
  1910.      */
  1911.     public function updateLoungeDetailsAction($idRequest $request)
  1912.     {
  1913.         $em $this->getDoctrine()->getManager();
  1914.         $reservationsLounge $em->getRepository(ReservationLoungeDetails::class)->findOneById($id);
  1915.         $reservationsLounge->setName($request->request->get('mds_venuesbundle_reservationloungedetails')['name']);
  1916.         $preNumber $reservationsLounge->getRankLounge();
  1917.         $postNumber $request->request->get('mds_venuesbundle_reservationloungedetails')['rankLounge'];
  1918.         $hoy = new \DateTime("now"NULL);
  1919.         $form $this->createEditReservationLoungeDetailsForm($reservationsLounge$id);
  1920.         $form->handleRequest($request);
  1921.         if ($form->isValid()) {
  1922.             /* Obtengo usuario logueado */
  1923.             $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  1924.             $user_id $user_logueado->getId();
  1925.             /* Gestión de eventos en Log */
  1926.             $user_lastname $user_logueado->getLastname();
  1927.             $user_name $user_logueado->getName();
  1928.             $user_email $user_logueado->getEmail();
  1929.             $user_rol $user_logueado->getRoles();
  1930.             $event_url $request->getPathInfo();
  1931.             $event_complete $user_name ' ' $user_lastname ' - ' $user_email ' - ' $user_rol[0] . ' | ' $event_url;
  1932.             $reservationsLounge->setUpdatedId($user_id);
  1933.             $reservationsLounge->setUpdatedAt($hoy);
  1934.             try {
  1935.                 // Reordenar salas si se ha cambiado el rank number de la sala
  1936.                 if (!($preNumber == $postNumber)) {
  1937.                     $this->reordenarSalas($postNumber$reservationsLounge->getId());
  1938.                 }
  1939.                 $em->persist($reservationsLounge);
  1940.                 $em->flush();
  1941.                 $event 'The lounge has been Updated. Now';
  1942.                 $successMessage $this->translator->trans($event);
  1943.                 $this->addFlash('mensajereservation'$successMessage);
  1944.             } catch (\Exception $e) {
  1945.                 $event 'An error occurred: ' $e->getMessage();
  1946.                 /* Para el usuario */
  1947.                 $errorMessage $this->translator->trans($event);
  1948.                 $this->addFlash('mensajereservationerror'$errorMessage);
  1949.             }
  1950.             /* Fin Gestión de eventos en Log */
  1951.             return $this->redirectToRoute('reservations_venues_list_lounges');
  1952.         } else {
  1953.             $errorMessage $this->translator->trans('Error, some fields are empty');
  1954.             $this->addFlash('mensajereservationerror'$errorMessage);
  1955.         }
  1956.         return $this->render(
  1957.             'MDS/VenuesBundle/reservations/edit-reservations-lounge-details.html.twig',
  1958.             array(
  1959.                 'id' => $reservationsLounge->getId(),
  1960.                 'lounge' => $reservationsLounge,
  1961.                 'form' => $form->createView()
  1962.             )
  1963.         );
  1964.     }
  1965.     /**
  1966.      * @Route("/deleteloungedetails/{id}", name="reservations_lounge_details_delete")
  1967.      */
  1968.     public function deleteLoungeDetailsAction($idEntityManagerInterface $emRequest $request)
  1969.     {
  1970.         $reservationsLounge $em->getRepository(ReservationLoungeDetails::class)->findOneById($id);
  1971.         try {
  1972.             $em->remove($reservationsLounge);
  1973.             $em->flush();
  1974.             // INICIO: Eliminamos los precios asociados a la sala
  1975.             $profiles $em->getRepository(ReservationLoungeProfile::class)->findByLoungeId($id);
  1976.             foreach ($profiles as $item) {
  1977.                 $em->remove($item);
  1978.                 $em->flush();
  1979.             }
  1980.             // FIN: Eliminamos los precios asociados a la sala
  1981.             $event 'The Reservation has been Deleted. Now';
  1982.             $successMessage $this->translator->trans($event);
  1983.             $this->addFlash('mensajereservation'$successMessage);
  1984.         } catch (\Exception $e) {
  1985.             $event 'An error occurred: ' $e->getMessage();
  1986.             /* Para el usuario */
  1987.             $errorMessage $this->translator->trans($event);
  1988.             $this->addFlash('mensajereservationerror'$errorMessage);
  1989.         }
  1990.         /* Fin Gestión de eventos en Log */
  1991.         return $this->redirectToRoute('reservations_venues_list_lounges');
  1992.     }
  1993.     /**
  1994.      * @Route("/deleteloungeelement/{idlounge}/{idtype}/{idelement}", name="reservations_lounge_element_delete")
  1995.      */
  1996.     public function deleteLoungeElementAction($idlounge$idtype$idelementEntityManagerInterface $emRequest $request)
  1997.     {
  1998.         switch ($idtype) {
  1999.             case 1:
  2000.                 $item $em->getRepository(ReservationLoungeDescription::class)->findOneById($idelement);
  2001.                 break;      //Descripcion
  2002.             case 2:
  2003.                 $item $em->getRepository(ReservationLoungePicture::class)->findOneById($idelement);
  2004.                 break;      //Imagenes
  2005.             case 3:
  2006.                 $item $em->getRepository(ReservationLoungeVideo::class)->findOneById($idelement);
  2007.                 break;      //Videos
  2008.             default:
  2009.                 $item null;
  2010.                 break;
  2011.         }
  2012.         try {
  2013.             $em->remove($item);
  2014.             $em->flush();
  2015.             $event 'The Item has been Deleted. Now';
  2016.             $successMessage $this->translator->trans($event);
  2017.             $this->addFlash('mensajereservation'$successMessage);
  2018.         } catch (\Exception $e) {
  2019.             $event 'An error occurred: ' $e->getMessage();
  2020.             /* Para el usuario */
  2021.             $errorMessage $this->translator->trans($event);
  2022.             $this->addFlash('mensajereservationerror'$errorMessage);
  2023.         }
  2024.         /* Fin Gestión de eventos en Log */
  2025.         return $this->redirectToRoute('reservations_lounge_details', array('id' => $idlounge));
  2026.     }
  2027.     /**
  2028.      *@Route("/exclamation", name="get_exclamation")
  2029.      */
  2030.     public function exclamationAction(EntityManagerInterface $emRequest $request)
  2031.     {
  2032.         $dateStar $request->request->get('dateStar');
  2033.         $dateEnd $request->request->get('dateEnd');
  2034.         $hourStar $request->request->get('hourStar');
  2035.         $hourEnd $request->request->get('hourEnd');
  2036.         $profileId $request->request->get('profileId');
  2037.         $mountingDate $request->request->get('mountingDate');
  2038.         $mountingHourStart $request->request->get('mountingHourStart');
  2039.         $removalDate $request->request->get('removalDate');
  2040.         $removalHourEnd $request->request->get('removalHourEnd');
  2041.         // INICIO: Si hay montaje o desmontaje  en el evento nuevo las fechas a utilizar son estas y no las del evento
  2042.         if (!empty($mountingDate)) {
  2043.             $dateStar $mountingDate;
  2044.             if (!empty($mountingHourStart)) {
  2045.                 $hourStar $mountingHourStart;
  2046.             }
  2047.         }
  2048.         if (!empty($removalDate)) {
  2049.             $dateEnd $removalDate;
  2050.             if (!empty($removalHourEnd)) {
  2051.                 $hourEnd $removalHourEnd;
  2052.             }
  2053.         }
  2054.         // FIN: Si hay montaje o desmontaje  en el evento nuevo las fechas a utilizar son estas y no las del evento
  2055.         $reservationsLoungeId $em->getRepository(ReservationLoungeProfile::class)->findOneById($profileId);
  2056.         $newdateStar $dateStar ' ' $hourStar ':00';
  2057.         $newdateEnd $dateEnd ' ' $hourEnd ':00';
  2058.         $parameters = array(
  2059.             'dateStar' => $newdateStar,
  2060.             'dateEnd' => $newdateEnd,
  2061.             'idLounge' => $reservationsLoungeId->getLoungeId(),
  2062.         );
  2063.         $dql 'SELECT i
  2064.                     FROM VenuesBundle:ReservationLounge i
  2065.                     WHERE  i.dateStart >= :dateStar
  2066.                       and i.dateStart <= :dateEnd
  2067.                       and i.idLounge = :idLounge';
  2068.         $query $em->createQuery($dql)->setParameters($parameters);
  2069.         $reservationLounge1 $query->getResult();
  2070.         $dql 'SELECT i
  2071.                     FROM VenuesBundle:ReservationLounge i
  2072.                     WHERE  i.dateEnd >= :dateStar
  2073.                       and i.dateEnd <= :dateEnd
  2074.                       and i.idLounge = :idLounge';
  2075.         $query $em->createQuery($dql)->setParameters($parameters);
  2076.         $reservationLounge2 $query->getResult();
  2077.         $parameters = array(
  2078.             'dateStar' => $newdateStar,
  2079.             'idLounge' => $reservationsLoungeId->getLoungeId()
  2080.         );
  2081.         $dql 'SELECT i
  2082.                     FROM VenuesBundle:ReservationLounge i
  2083.                     WHERE  :dateStar >= i.dateStart
  2084.                       and :dateStar <= i.dateEnd
  2085.                       and i.idLounge = :idLounge';
  2086.         $query $em->createQuery($dql)->setParameters($parameters);
  2087.         $reservationLounge3 $query->getResult();
  2088.         $parameters = array(
  2089.             'dateEnd' => $newdateEnd,
  2090.             'idLounge' => $reservationsLoungeId->getLoungeId(),
  2091.         );
  2092.         $dql 'SELECT i
  2093.                     FROM VenuesBundle:ReservationLounge i
  2094.                     WHERE  :dateEnd >= i.dateStart
  2095.                       and :dateEnd <= i.dateEnd
  2096.                       and i.idLounge = :idLounge';
  2097.         $query $em->createQuery($dql)->setParameters($parameters);
  2098.         $reservationLounge4 $query->getResult();
  2099.         // INICIO: Si hay montaje o desmontaje  en los eventos de la BD, las fechas a utilizar son estas y no las del evento
  2100.         $parameters = array(
  2101.             'dateStar' => $newdateStar,
  2102.             'dateEnd' => $newdateEnd,
  2103.             'idLounge' => $reservationsLoungeId->getLoungeId(),
  2104.         );
  2105.         $dql 'SELECT i
  2106.                     FROM VenuesBundle:ReservationLounge i
  2107.                     WHERE  i.mountingDate >= :dateStar
  2108.                       and i.mountingDate <= :dateEnd
  2109.                       and i.idLounge = :idLounge';
  2110.         $query $em->createQuery($dql)->setParameters($parameters);
  2111.         $reservationLounge5 $query->getResult();
  2112.         // FIN: Si hay montaje o desmontaje  en los eventos de la BD, las fechas a utilizar son estas y no las del evento
  2113.         $reservationLounge array_merge($reservationLounge1$reservationLounge2$reservationLounge3$reservationLounge4);
  2114.         $data = array();
  2115.         foreach ($reservationLounge as $res) {
  2116.             $reservation $em->getRepository(Reservation::class)->findOneById($res->getIdReservation());
  2117.             $user $em->getRepository(User::class)->findOneById($reservation->getCreatedBy());
  2118.             $data[] = array(
  2119.                 'name' => 'Id Venues',
  2120.                 'idproposal' => $reservation->getId(),
  2121.                 'title' => $reservation->getTitle(),
  2122.                 'Agent' => $user->getName() . ' ' $user->getLastname(),
  2123.             );
  2124.         }
  2125.         $return = array('reservation' => $data, );
  2126.         $response = new JsonResponse($return);
  2127.         return $response;
  2128.     }
  2129.     /**
  2130.      * @Route("/addperiod/",  name="reservations_venues_addperiod")
  2131.      */
  2132.     public function addReservationPeriodAction(Request $request)
  2133.     {
  2134.         $period = new ReservationPeriod();
  2135.         $form $this->createReservationperiodCreateForm($period);
  2136.         return $this->render('MDS/VenuesBundle/reservations/list-reservations-period.html.twig', array('form' => $form->createView()));
  2137.     }
  2138.     private function createReservationperiodCreateForm(Reservationperiod $entity)
  2139.     {
  2140.         $form $this->createForm(ReservationPeriodType::class, $entity, array(
  2141.             'action' => $this->generateUrl('reservations_venues_period_create'),
  2142.             'method' => 'POST'
  2143.         ));
  2144.         return $form;
  2145.     }
  2146.     /**
  2147.      * @Route("/createperiod", name="reservations_venues_period_create")
  2148.      */
  2149.     public function createPeriodAction(EntityManagerInterface $emRequest $request)
  2150.     {
  2151.         $period = new ReservationPeriod();
  2152.         $form $this->createReservationPeriodCreateForm($period);
  2153.         $form->handleRequest($request);
  2154.         /* Obtengo usuario logueado */
  2155.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  2156.         $user_id $user_logueado->getId();
  2157.         $hoy = new \DateTime("now"NULL);
  2158.         $period->setCreatedAt($hoy);
  2159.         $period->setCreatedId($user_id);
  2160.         $period->setUpdatedAt($hoy);
  2161.         $period->setUpdatedId($user_id);
  2162.         if ($form->isValid()) {
  2163.             try {
  2164.                 $em->persist($period);
  2165.                 $em->flush();
  2166.                 $event 'The Period has been created.';
  2167.                 $successMessage $this->translator->trans($event);
  2168.                 $this->addFlash('mensajereservation'$successMessage);
  2169.             } catch (\Exception $e) {
  2170.                 $event 'An error occurred: ' $e->getMessage();
  2171.                 /* Para el usuario */
  2172.                 $errorMessage $this->translator->trans($event);
  2173.                 $this->addFlash('mensajereservationerror'$errorMessage);
  2174.             }
  2175.         } else {
  2176.             $errorMessage $this->translator->trans('Error, some fields are empty');
  2177.             $this->addFlash('mensajereservationerror'$errorMessage);
  2178.         }
  2179.         return $this->redirectToRoute('reservations_venues_list_period');
  2180.     }
  2181.     /**
  2182.      * @Route("/listperiod", name="reservations_venues_list_period")
  2183.      */
  2184.     public function indexPeriodAction(EntityManagerInterface $emRequest $request)
  2185.     {
  2186.         $periods $em->getRepository(ReservationPeriod::class)->findAll();
  2187.         $period = new ReservationPeriod();
  2188.         $form $this->createReservationPeriodCreateForm($period);
  2189.         return $this->render(
  2190.             'MDS/VenuesBundle/reservations/list-reservations-period.html.twig',
  2191.             array(
  2192.                 'groups' => null,
  2193.                 'form' => $form->createView(),
  2194.                 'periods' => $periods
  2195.             )
  2196.         );
  2197.     }
  2198.     /**
  2199.      * @Route("/deleteperiod/{id}", name="reservations_period_delete")
  2200.      */
  2201.     public function deletePeriodAction(EntityManagerInterface $em$idRequest $request)
  2202.     {
  2203.         $period $em->getRepository(ReservationPeriod::class)->findOneById($id);
  2204.         try {
  2205.             $em->remove($period);
  2206.             $em->flush();
  2207.             $event 'The Reservation has been Deleted. Now';
  2208.             $successMessage $this->translator->trans($event);
  2209.             $this->addFlash('mensajereservation'$successMessage);
  2210.         } catch (\Exception $e) {
  2211.             $event 'An error occurred: ' $e->getMessage();
  2212.             /* Para el usuario */
  2213.             $errorMessage $this->translator->trans($event);
  2214.             $this->addFlash('mensajereservationerror'$errorMessage);
  2215.         }
  2216.         /* Fin Gestión de eventos en Log */
  2217.         return $this->redirectToRoute('reservations_venues_list_period');
  2218.     }
  2219.     /**
  2220.      * @Route("/editperiod/{id}", name="reservations_edit_period")
  2221.      */
  2222.     public function editPeriodAction($idEntityManagerInterface $emRequest $request)
  2223.     {
  2224.         $period $em->getRepository(ReservationPeriod::class)->findOneById($id);
  2225.         /* Obtengo usuario logueado */
  2226.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  2227.         /* Gestión de eventos en Log */
  2228.         $user_lastname $user_logueado->getLastname();
  2229.         $user_name $user_logueado->getName();
  2230.         $user_email $user_logueado->getEmail();
  2231.         $user_rol $user_logueado->getRoles();
  2232.         $event_url $request->getPathInfo();
  2233.         $event_complete $user_name ' ' $user_lastname ' - ' $user_email ' - ' $user_rol[0] . ' | ' $event_url;
  2234.         $hoy = new \DateTime("now"NULL);
  2235.         $form $this->createEditPeriodForm($period$id);
  2236.         return $this->render(
  2237.             'MDS/VenuesBundle/reservations/edit-reservations-period.html.twig',
  2238.             array(
  2239.                 'id' => $id,
  2240.                 'hoy' => $hoy,
  2241.                 'period' => $period,
  2242.                 'form' => $form->createView()
  2243.             )
  2244.         );
  2245.     }
  2246.     private function createEditPeriodForm(ReservationPeriod $entity$id)
  2247.     {
  2248.         $form $this->createForm(
  2249.             ReservationPeriodType::class,
  2250.             $entity,
  2251.             array(
  2252.                 'action' => $this->generateUrl(
  2253.                     'reservations_period_update',
  2254.                     array(
  2255.                         'id' => $id,
  2256.                         'period' => $entity
  2257.                     )
  2258.                 ),
  2259.                 'method' => 'PUT'
  2260.             )
  2261.         );
  2262.         return $form;
  2263.     }
  2264.     /**
  2265.      * @Route("/updateperiod/{id}", name="reservations_period_update")
  2266.      */
  2267.     public function updatePeriodAction($idEntityManagerInterface $emRequest $request)
  2268.     {
  2269.         $period $em->getRepository(ReservationPeriod::class)->findOneById($id);
  2270.         $newName $request->request->get('mds_venuesbundle_reservationperiod')['name'];
  2271.         $period->setName($newName);
  2272.         $hoy = new \DateTime("now"NULL);
  2273.         $form $this->createEditPeriodForm($period$id);
  2274.         $form->handleRequest($request);
  2275.         if ($form->isValid()) {
  2276.             /* Obtengo usuario logueado */
  2277.             $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  2278.             $user_id $user_logueado->getId();
  2279.             /* Gestión de eventos en Log */
  2280.             $user_lastname $user_logueado->getLastname();
  2281.             $user_name $user_logueado->getName();
  2282.             $user_email $user_logueado->getEmail();
  2283.             $user_rol $user_logueado->getRoles();
  2284.             $event_url $request->getPathInfo();
  2285.             $event_complete $user_name ' ' $user_lastname ' - ' $user_email ' - ' $user_rol[0] . ' | ' $event_url;
  2286.             $period->setUpdatedId($user_id);
  2287.             $period->setUpdatedAt($hoy);
  2288.             try {
  2289.                 $em->persist($period);
  2290.                 $em->flush();
  2291.                 $event 'The period has been Updated. Now';
  2292.                 $successMessage $this->translator->trans($event);
  2293.                 $this->addFlash('mensajereservation'$successMessage);
  2294.             } catch (\Exception $e) {
  2295.                 $event 'An error occurred: ' $e->getMessage();
  2296.                 /* Para el usuario */
  2297.                 $errorMessage $this->translator->trans($event);
  2298.                 $this->addFlash('mensajereservationerror'$errorMessage);
  2299.             }
  2300.             /* Fin Gestión de eventos en Log */
  2301.             return $this->redirectToRoute('reservations_venues_list_period');
  2302.         } else {
  2303.             $errorMessage $this->translator->trans('Error, some fields are empty');
  2304.             $this->addFlash('mensajereservationerror'$errorMessage);
  2305.         }
  2306.         return $this->render(
  2307.             'MDS/VenuesBundle/reservations/edit-reservations-period.html.twig',
  2308.             array(
  2309.                 'id' => $id,
  2310.                 'hoy' => $hoy,
  2311.                 'period' => $period,
  2312.                 'form' => $form->createView()
  2313.             )
  2314.         );
  2315.     }
  2316.     /**
  2317.      * @Route("/getperiodos/",  name="reservations_venues_get_periods")
  2318.      */
  2319.     public function addReservationPeriodsAction(EntityManagerInterface $emRequest $request)
  2320.     {
  2321.         $periods $em->getRepository(ReservationPeriod::class)->findAll();
  2322.         $data = array();
  2323.         foreach ($periods as $items) {
  2324.             $data[] = array('id' => $items->getId(), 'name' => $items->getName(), );
  2325.         }
  2326.         $return = array('periods' => $data, );
  2327.         $response = new JsonResponse($return);
  2328.         return $response;
  2329.     }
  2330.     /**
  2331.      * @Route("/addsimple/",  name="reservations_venues_add_simple")
  2332.      */
  2333.     public function addReservationSimpleAction(EntityManagerInterface $emRequest $request)
  2334.     {
  2335.         $reserv = new Reservation();
  2336.         $form $this->createReservationCreateForm($reserv, ['cotizable' => true]);
  2337.         return $this->render(
  2338.             'MDS/VenuesBundle/reservations/add-reservations-simple.html.twig',
  2339.             array(
  2340.                 'form' => $form->createView(),
  2341.                 'clientsContact' => '',
  2342.             )
  2343.         );
  2344.     }
  2345.     private function createReservationCreateForm(Reservation $entity, array $options = [])
  2346.     {
  2347.         $id $entity->getId();
  2348.         $hasInvoices false;
  2349.         if ($id) {
  2350.             $invoiceRepository $this->em->getRepository(ReservationInvoice::class);
  2351.             $invoiceRecRepository $this->em->getRepository(ReservationInvoiceRec::class);
  2352.             $hasInvoices = !empty($invoiceRepository->findByReservationId($id)) || !empty($invoiceRecRepository->findByReservationId($id));
  2353.         }
  2354.         $form $this->createForm(ReservationType::class, $entity, array(
  2355.             'action' => $this->generateUrl('reservations_venues_create_simple'),
  2356.             'method' => 'POST',
  2357.             'confirmable' => $options['confirmable'] ?? false,
  2358.             'cotizable' => $options['cotizable'] ?? false,
  2359.             'invoiced' => $hasInvoices,
  2360.         ));
  2361.         return $form;
  2362.     }
  2363.     /**
  2364.      * @Route("/createsimple", name="reservations_venues_create_simple")
  2365.      */
  2366.     public function createSimpleAction(EntityManagerInterface $emRequest $request)
  2367.     {
  2368.         $clientContact $request->request->get('clientContact');
  2369.         $contactUnregistered trim((string) $request->request->get('contactUnregistered'));
  2370.         $nameContactUnregistered trim((string) $request->request->get('nameContactUnregistered'));
  2371.         $phoneContactUnregistered trim((string) $request->request->get('phoneContactUnregistered'));
  2372.         $reserva = new Reservation();
  2373.         $form $this->createReservationCreateForm($reserva);
  2374.         $form->handleRequest($request);
  2375.         /* Obtengo usuario logueado */
  2376.         $user_logueado $this->getUser();
  2377.         $user_id $user_logueado->getId();
  2378.         $hoy = new \DateTime("now"NULL);
  2379.         if ($form->isValid()) {
  2380.             $clientId $request->request->get('mds_venuesbundle_reservation')['client'] ?? null;
  2381.             if ($clientId) {
  2382.                 $client $em->getRepository(Client::class)->find($clientId);
  2383.             }
  2384.             $reserva->setClient(
  2385.                 $clientId $client null
  2386.             );
  2387.             $reserva->setCreatedAt($hoy);
  2388.             $reserva->setCreatedBy($user_id);
  2389.             if (empty($reserva->getDaysBlock()) or !(is_numeric($reserva->getDaysBlock()))) {
  2390.                 $reserva->setDaysBlock(7);
  2391.             }
  2392.             if (is_null($reserva->getPriority()) or empty($reserva->getPriority()) or ($reserva->getPriority() == 'Auto')) {
  2393.                 $reserva->setPriority(1);
  2394.             } else {
  2395.                 // Se ha establecido una prioridad y todas las prioridades que coincidan con este evento deben ser alteradas
  2396.                 // PENDIENTE A HABLAR CON RAFA
  2397.             }
  2398.             // No hay salas, se asigna a la reserva la fecha del dia actual. Por indicaciones de Rafa se debe agregar fechas al formulario
  2399.             // Si solo agrega una fecha, pone ambas fechas igual, si no pone fecha se ponen las fechas de control
  2400.             $dateStart $reserva->getDateStart(); $dateEnd   $reserva->getDateEnd();
  2401.             if ($dateStart === null && $dateEnd === null) {
  2402.                 $reserva->setDateStart(new \DateTime('2078-01-01'));
  2403.                 $reserva->setDateEnd(new \DateTime('2000-01-01'));
  2404.             } elseif ($dateStart === null) {
  2405.                 $reserva->setDateStart((clone $dateEnd)->setTime(00000));
  2406.                 $reserva->setDateEnd((clone $dateEnd)->setTime(23590));
  2407.             } elseif ($dateEnd === null) {
  2408.                 // El dateStart con hora 00:00 es lo deseado
  2409.                 $reserva->setDateEnd((clone $dateStart)->setTime(23590));
  2410.             }
  2411.             // Si viene información de un contacto no registrado, creamos el contrato y lo vinculamos al cliente y luego al expediente
  2412.             if ($clientId && $contactUnregistered !== '' && $nameContactUnregistered !== '' && $phoneContactUnregistered !== '') {
  2413.                 $existClientContact $em->getRepository(ClientContact::class)->findOneBy(['email' => $contactUnregistered]);
  2414.                 if ($existClientContact) {
  2415.                     // Si ya existe un contacto con ese email, lo vinculamos al expediente
  2416.                     $reserva->setClientContact($existClientContact->getId());
  2417.                 } else {
  2418.                     $newClientContact = new ClientContact();
  2419.                     $newClientContact->setClientId($client->getId());
  2420.                     $newClientContact->setTypeclient('Business Travel');
  2421.                     $newClientContact->setAssignedAgent($user_id);
  2422.                     $newClientContact->setName($nameContactUnregistered);
  2423.                     $newClientContact->setLastName('');
  2424.                     $newClientContact->setPosition('');
  2425.                     $newClientContact->setSituation('CLIENT');
  2426.                     $newClientContact->setStatus('');
  2427.                     $newClientContact->setEmail($contactUnregistered);
  2428.                     $newClientContact->setPhone($phoneContactUnregistered);
  2429.                     $newClientContact->setCreatedId($user_id);
  2430.                     $newClientContact->setUpdatedId($user_id);
  2431.                     $em->persist($newClientContact);
  2432.                     $em->flush();
  2433.                     $reserva->setClientContact($newClientContact->getId());
  2434.                 }
  2435.             }
  2436.             if (!empty($clientContact) && $clientContact != '0') {
  2437.                 $reserva->setClientContact($clientContact);
  2438.             }
  2439.             if (empty($reserva->getStatus())) {
  2440.                 $reserva->setStatus('Iniciado');
  2441.             } else {
  2442.                 //No se debe crear un evento con estado confirmado. Salva y Rafa seran quienes confirmen los eventos
  2443.                 if (($reserva->getStatus() == 'Confirmed')) {
  2444.                     //                    $reserva->setStatus('Cotizado');              //Ya no es necesario que Rafa o Salva confirmen
  2445.                 }
  2446.             }
  2447.             // Genera un token único utilizando la función uniqid() de PHP
  2448.             $token uniqid();
  2449.             $reserva->setToken($token);
  2450.             $reserva->setCreatedBy($user_id);
  2451.             $reserva->setUpdatedBy($user_id);
  2452.             try {
  2453.                 $em->persist($reserva);
  2454.                 $em->flush();
  2455.                 $event 'The Reservation has been created.';
  2456.                 $successMessage $this->translator->trans($event);
  2457.                 $this->addFlash('mensajereservation'$successMessage);
  2458.             } catch (\Exception $e) {
  2459.                 dd($e);
  2460.                 $event 'An error occurred: ' $e->getMessage();
  2461.                 $errorMessage $this->translator->trans($event);
  2462.                 $this->addFlash('mensajereservationerror'$errorMessage);
  2463.             }
  2464.             //Envio de correo al cliente y al agente si es un bloqueo
  2465.             if (is_null($reserva->getStatus())) {
  2466.                 $reserva->setStatus('Cotizado');
  2467.                 $em->persist($reserva);
  2468.                 $em->flush();
  2469.             } else {
  2470.                 if (($reserva->getStatus() == 'Bloqueo')) {
  2471.                     if (empty($reserva->getDays())) {
  2472.                         $now = new \DateTime("now");
  2473.                         $dateLimit date("Y-m-d H:i"strtotime($now->format('Y-m-d H:i') . "+" $reserva->getDaysBlock() . " days"));
  2474.                         $dateLimit = new \DateTime($dateLimit);
  2475.                         $reserva->setDays($dateLimit);
  2476.                     }
  2477.                     if ((!empty($reserva->getClient())) or (!empty($reserva->getClientContact())) or (!empty($reserva->getContactUnregistered()))) {
  2478.                         //Solo se envia correo de notificacion del correo si hay cliente o contacto o contacto no registrado
  2479.                         $client $reserva->getClient();
  2480.                         $mailAddressTo null;
  2481.                         // if (!empty($client) and (!empty($client->getEmail()))){ $mailAddressTo = $client->getEmail(); }         // Si hay cliente con correo se le envia a este
  2482.                         // if (!empty($reserva->getClientContact())){
  2483.                         //     $contacto = $em->getRepository(ClientContact::class)->findOneById($reserva->getClientContact());
  2484.                         //     if (!empty($contacto) and (!empty($contacto->getEmail()))){ $mailAddressTo = $contacto->getEmail(); }   // Si hay un contacto seleccionado tiene prioridad sobre el contacto de cliente
  2485.                         // }
  2486.                         // if (!empty($reserva->getContactUnregistered())){ $mailAddressTo = $reserva->getContactUnregistered(); }     // Si hay correo de contacto no registrado este tiene prioridad sobre todos
  2487.                         if (!empty($mailAddressTo)) {
  2488.                             $agente $em->getRepository(User::class)->findOneById($user_id);
  2489.                             $mailAddressFrom $agente->getEmail();
  2490.                             $mailSubject 'Notificación de Bloqueo - Reserva de espacio en Venues';
  2491.                             $mailBody 'Estimado cliente,' .
  2492.                                 '<br><br> Nos ponemos en contacto con usted para confirmarle que su reserva ha quedado registrada en Venues para la realización de su próximo evento.' .
  2493.                                 '<br>Le recordamos que esta reserva tiene una validez de ' $reserva->getDaysBlock() . ' días. Si pasado este tiempo no hemos recibido confirmación de vuestra parte, procederemos a la cancelación de la misma.' .
  2494.                                 '<br><br>Reserva: ' $reserva->getId() . ' - ' $reserva->getTitle();
  2495.                             $mailBody $mailBody '<br><br><br>Muchas gracias por su colaboración.<br><br><br>';
  2496.                             //Se envia el correo al cliente y al agente
  2497.                             $this->sendMail($mailAddressFrom$mailAddressTo$mailSubject$mailBody);
  2498.                             //Se genera el control de la alerta
  2499.                             $this->makeAlert($reserva->getId(), $client?->getId(), $mailAddressTo$agente->getId(), $agente->getEmail());
  2500.                         }
  2501.                     }
  2502.                 }
  2503.             }
  2504.         } else {
  2505.             $errorMessagebase $this->translator->trans('Error, some fields are empty');
  2506.             $this->addFlash('mensajetracingerror'$errorMessagebase);
  2507.             $periods $em->getRepository(ReservationPeriod::class)->findAll();
  2508.             return $this->render(
  2509.                 'MDS/VenuesBundle/reservations/add-reservations.html.twig',
  2510.                 array(
  2511.                     'form' => $form->createView(),
  2512.                     'periods' => $periods,
  2513.                 )
  2514.             );
  2515.         }
  2516.         $id $reserva->getId();
  2517.         // Actualizamos la agenda
  2518.         $newItem = new ReservationAgendaItem();
  2519.         $newItem->setReservationId($id);
  2520.         $newItem->setRankListing(1);
  2521.         $newItem->setTitleOne('EVENTO: ' $reserva->getTitle());
  2522.         $newItem->setTitleTwo(null);
  2523.         $newItem->setTitleThree(null);
  2524.         $newItem->setDescription('.');
  2525.         $newItem->setDateStart(null);
  2526.         $newItem->setDateEnd(null);
  2527.         $newItem->setPicture(null);
  2528.         $newItem->setSourceId($id);
  2529.         $newItem->setSourceType('Reservation');
  2530.         $user $this->getUser();
  2531.         $newItem->setCreatedId($user->getId());
  2532.         $newItem->setUpdatedId($user->getId());
  2533.         $newItem->setCreatedAt(new \DateTime());
  2534.         $newItem->setUpdatedAt(new \DateTime());
  2535.         $this->repository->add($newItemtrue);
  2536.         //Actualizamos el contacto de la Agenda
  2537.         $contactString null;
  2538.         if (!empty($reserva->getNameContactUnregistered())) {
  2539.             $contactString .= $reserva->getNameContactUnregistered();
  2540.         } else {
  2541.             $contactString .= 'No se pudo determinar el nombre';
  2542.         }
  2543.         if (!empty($reserva->getPhoneContactUnregistered())) {
  2544.             $contactString .= ' / ' $reserva->getPhoneContactUnregistered();
  2545.         } else {
  2546.             $contactString .= ' / No se pudo determinar el teléfono';
  2547.         }
  2548.         if (!empty($reserva->getContactUnregistered())) {
  2549.             $contactString .= ' / ' $reserva->getContactUnregistered();
  2550.         } else {
  2551.             $contactString .= ' / No se pudo determinar el email';
  2552.         }
  2553.         $agenda $this->agendaService->updateClientContactLine($reserva->getId(), $contactString$user->getId());
  2554.         // Sincronización con Av Express
  2555.         $cotizable $this->laReservaEsCotizable($reserva->getId());
  2556.         if ($cotizable) {
  2557.             // Rafa indico que siempre se sincronice al abrir un expediente de GP
  2558.             //    if (in_array($reserva->getStatus(), ['Confirmed', 'Invoiced', 'Iniciado', 'Cotizado', 'Bloqueo'])) {
  2559.             //        $AveFile = $em->getRepository(AveFiles::class)->findByReservation($reserva);
  2560.             //        if (empty($AveFile)) {
  2561.             //            // Si no se ha creado aun el expediente de Av Express debemos crearlo
  2562.             //            return $this->redirectToRoute('sinc_gp_ave', array('id' => $id,));
  2563.             //        }
  2564.             //    }
  2565.         }
  2566.         return $this->redirectToRoute('reservations_venues_edit_simple', array('id' => $id'token' => null));
  2567.     }
  2568.     /**
  2569.      * @Route("/editsimple/{id}",  name="reservations_venues_edit_simple")
  2570.      */
  2571.     public function editReservationSimpleItemsAction(int $idEntityManagerInterface $emTokenStorageInterface $tokenStorage): Response
  2572.     {
  2573.         // 1. Carga inicial de datos críticos (Fail Fast)
  2574.         $reserva $em->getRepository(Reservation::class)->find($id);
  2575.         if (!$reserva) {
  2576.             throw new NotFoundHttpException('Reserva no encontrada.');
  2577.         }
  2578.         $client $reserva->getClient();
  2579.         $clientId $client?->getId() ?? 0;
  2580.         // Settings Company
  2581.         $settingsCompany $em->getRepository(SettingsCompany::class)->findOneBy([
  2582.             'businessType' => BusinessTypeSettingsCompanyConstants::VENUE
  2583.         ]);
  2584.         // 2. Preparación de Formularios (Objetos vacíos para crear)
  2585.         $reservationsLounge = new ReservationLounge();
  2586.         $reservationsLounge->setIdReservation($id);
  2587.         $monDesmon = new ReservationLounge();
  2588.         $monDesmon->setIdReservation($id);
  2589.         $options['confirmable'] = $this->laReservaEsConfirmable($id);
  2590.         $options['cotizable'] = $this->laReservaEsCotizable($id);
  2591.         $form1 $this->createReservationCreateForm($reserva$options);
  2592.         // =================================================================================
  2593.         // CORRECCIÓN: Rellenar los campos "mapped => false" si ya existe un contacto guardado
  2594.         // =================================================================================
  2595.         $savedContactId $reserva->getClientContact();
  2596.         if ($savedContactId) {
  2597.             // Buscamos la entidad del contacto real
  2598.             $savedContact $em->getRepository(ClientContact::class)->find($savedContactId);
  2599.             if ($savedContact) {
  2600.                 // 1. Rellenamos el Email
  2601.                 $form1->get('contactUnregistered')->setData($savedContact->getEmail());
  2602.                 // 2. Rellenamos el Nombre (concatenando apellido si lo hubiera)
  2603.                 $fullName $savedContact->getName();
  2604.                 if (!empty($savedContact->getLastName())) {
  2605.                     $fullName .= ' ' $savedContact->getLastName();
  2606.                 }
  2607.                 $form1->get('nameContactUnregistered')->setData($fullName);
  2608.                 // 3. Rellenamos el Teléfono
  2609.                 $form1->get('phoneContactUnregistered')->setData($savedContact->getPhone());
  2610.                 // 4. Aseguramos que el selector (campo hidden) tenga el valor correcto
  2611.                 // para que la lógica de JavaScript y el controlador funcionen bien al volver a guardar.
  2612.                 $form1->get('clientContact')->setData($savedContactId);
  2613.             }
  2614.         }
  2615.         // =================================================================================
  2616.         $form2 $this->createReservationLoungeCreateForm($reservationsLounge);
  2617.         $form3 $this->createReservationLoungeMonDesCreateForm($monDesmon);
  2618.         // 3. Procesamiento de Salas (Lounges)
  2619.         $reservationsLoungesSimple $em->getRepository(ReservationLoungeSimple::class)->findByIdReservation($id);
  2620.         $loungesData $this->processLounges($reservationsLoungesSimple);
  2621.         // 4. Cálculos Totales (Método existente en tu controlador)
  2622.         $data $this->CalculosTotalesEditSimple($id);
  2623.         // 5. Proveedores y Catering
  2624.         $caterings $this->getCateringSuppliers($em);
  2625.         // 6. Usuarios y Creador
  2626.         $userCreatedBy $em->getRepository(User::class)->find($reserva->getCreatedBy());
  2627.         $createdBy $userCreatedBy ? ($userCreatedBy->getName() . ' ' $userCreatedBy->getLastName()) : '';
  2628.         // 7. Facturación y Finanzas (Lógica compleja refactorizada)
  2629.         $invoicesData $this->calculateInvoicesData($id$reserva$client$em);
  2630.         // 8. Pagos
  2631.         $paymentsAll $em->getRepository(ReservationPaymentsClient::class)->findByReservationId($id);
  2632.         $paymentNotIvoiced $this->filterUninvoicedPayments($id$paymentsAll$em);
  2633.         // 9. Contactos y Usuarios Activos
  2634.         $userLogueado $tokenStorage->getToken()?->getUser();
  2635.         $userId $userLogueado instanceof User $userLogueado->getId() : null;
  2636.         $clientsContact $em->getRepository(ClientContact::class)->findBy(
  2637.             ['clientId' => $clientId],
  2638.             ['name' => 'ASC']
  2639.         );
  2640.         $allUsersActive $this->getAllActiveUsersAndFreelancers($em);
  2641.         // 10. Alertas de Correo
  2642.         $nextMailAlert $this->getNextMailAlertDate($id$em);
  2643.         // 11. Datos Adicionales (Servicios, Clientes Venues, Depósitos)
  2644.         $reservationsLounges $em->getRepository(ReservationLounge::class)->findByIdReservation($id);
  2645.         $services $em->getRepository(ReservationService::class)->findByReservationId($id);
  2646.         $datax $this->benefitForReservation($id); // Método existente
  2647.         // Clientes filtrados por SettingsCompany
  2648.         $clients $em->getRepository(Client::class)
  2649.             ->createQueryBuilder('c')
  2650.             ->innerJoin('c.settingsCompany''sc')
  2651.             ->where('sc.id = :settingsCompanyId')
  2652.             ->setParameter('settingsCompanyId'$settingsCompany?->getId())
  2653.             ->orderBy('c.name''ASC')
  2654.             ->getQuery()
  2655.             ->getResult();
  2656.         // Depósitos y Proformas
  2657.         $depositsData $this->getDepositsAndProformas($id$em);
  2658.         // Todas las proformas de la reserva (Evita N+1 ya que se consultan de golpe sin relaciones pesadas)
  2659.         $allReservationProformas $em->getRepository(ReservationProforma::class)->findBy(
  2660.             ['reservationId' => $id],
  2661.             ['id' => 'DESC']
  2662.         );
  2663.         // Salas Predefinidas y Nombres
  2664.         $reservationsLoungesPre $em->createQueryBuilder()
  2665.             ->select('p')
  2666.             ->from('VenuesBundle:ReservationLoungeDetails''p'// Ajustar si el bundle name es distinto
  2667.             ->orderBy('p.rankLounge''ASC')
  2668.             ->getQuery()
  2669.             ->getResult();
  2670.         $reservationsLoungesNames $em->getRepository(ReservationLoungeDetails::class)->findAll();
  2671.         $listSupplier $em->getRepository(Supplier::class)->findAll();
  2672.         // Flags finales
  2673.         $urlCotizacion "https://cotizacion.greenpatio.es/index.php?token=" $reserva->getToken();
  2674.         $languagesWeb LanguageConstants::getAvailableLanguages();
  2675.         $agenda $this->agendaService->getAgendaForView($id);
  2676.         // Obtener el HtFile asociado
  2677.         $htFile $reserva->getHtFile();
  2678.         // Obtener el AveFile asociado
  2679.         $aveFile $reserva->getAveFile();
  2680.         // Obtener historial de seguimientos
  2681.         $tracings $em->getRepository(ReservationTracing::class)->findBy(
  2682.             ['reservationId' => $id],
  2683.             ['createdAt' => 'DESC']
  2684.         );
  2685.         return $this->render('MDS/VenuesBundle/reservations/edit-reservations-simple.html.twig', [
  2686.             'form' => $form1->createView(),
  2687.             'form2' => $form2->createView(),
  2688.             'form3' => $form3->createView(),
  2689.             'id' => $id,
  2690.             'clients' => $clients,
  2691.             'clientId' => $clientId,
  2692.             'caterings' => $caterings,
  2693.             'loungesPre' => $reservationsLoungesPre,
  2694.             'loungesNames' => $reservationsLoungesNames,
  2695.             'arrayLoungesInFile' => $loungesData['arrayLoungesInFile'],
  2696.             'facturas' => $invoicesData['allInvoiced'],
  2697.             'numeroItems' => count($loungesData['arrayLoungesByDay']),
  2698.             'arrayLoungesByDay' => $loungesData['arrayLoungesByDay'],
  2699.             // Totales globales (usando nullsafe operator para arrays si $data no garantiza claves)
  2700.             'totales_global_con_iva' => $data['totales_global_con_iva'] ?? 0,
  2701.             'totales_global_iva' => $data['totales_global_iva'] ?? 0,
  2702.             'totales_global_neto' => $data['totales_global_neto'] ?? 0,
  2703.             'totales_global_servicios_con_iva' => $data['totales_global_servicios_con_iva'] ?? 0,
  2704.             'totales_global_servicios_neto' => $data['totales_global_servicios_neto'] ?? 0,
  2705.             'totales_global_servicios_iva' => $data['totales_global_servicios_iva'] ?? 0,
  2706.             'sumatoria_totales_global_con_iva' => $data['sumatoria_totales_global_con_iva'] ?? 0,
  2707.             'sumatoria_totales_global_neto' => $data['sumatoria_totales_global_neto'] ?? 0,
  2708.             'sumatoria_totales_global_iva' => $data['sumatoria_totales_global_iva'] ?? 0,
  2709.             'reserva' => $reserva,
  2710.             'createdBy' => $createdBy,
  2711.             'arraySalas' => null,
  2712.             'lounges' => $reservationsLounges,
  2713.             'salasReserva' => $reservationsLounges,
  2714.             'periods' => null,
  2715.             'services' => $services,
  2716.             'loungesNumbers' => count($reservationsLounges),
  2717.             'listSupplier' => $listSupplier,
  2718.             'resultados' => $invoicesData['resultados'],
  2719.             'paymentsAll' => $paymentsAll,
  2720.             'paymentNotIvoiced' => $paymentNotIvoiced,
  2721.             'allUsersActive' => $allUsersActive,
  2722.             'userLog' => $userId,
  2723.             'clientsContact' => $clientsContact,
  2724.             'nextMailAlert' => $nextMailAlert,
  2725.             'benefit' => $datax['benefit'],
  2726.             'percBenefit' => $datax['percBenefit'],
  2727.             'payedLounges' => $datax['payedLounges'],
  2728.             'payedServices' => $datax['payedServices'],
  2729.             'unPayedServices' => $datax['unPayedServices'],
  2730.             'depositsAll' => $depositsData['depositsAll'],
  2731.             'sumsByProforma' => $depositsData['sumsByProforma'],
  2732.             'proformas' => $depositsData['proformas'],
  2733.             'allReservationProformas' => $allReservationProformas,
  2734.             'urlCotizacion' => $urlCotizacion,
  2735.             'reservationContracts' => $reserva->getDocContracts(),
  2736.             'viewContract' => !$reserva->getDocContracts()->isEmpty(),
  2737.             'languagesWeb' => $languagesWeb,
  2738.             'sageVatRates' => $em->getRepository(SageVatRates::class)->findAll(),
  2739.             'arregloLineasAgenda' => $agenda,
  2740.             'htFile' => $htFile,
  2741.             'aveFile' => $aveFile,
  2742.             'tracings' => $tracings,
  2743.         ]);
  2744.     }
  2745.     /**
  2746.      * @Route("/showsimple/{id}",  name="reservations_venues_show_simple")
  2747.      */
  2748.     public function showReservationSimpleItemsAction(int $idEntityManagerInterface $em): Response
  2749.     {
  2750.         $reserva $em->getRepository(Reservation::class)->find($id);
  2751.         if (!$reserva) {
  2752.             throw new NotFoundHttpException('Reserva no encontrada.');
  2753.         }
  2754.         $user $this->getUser();
  2755.         $isLegendTeam = ($user && strtoupper(trim($user->getTeam() ?? '')) === 'LEGENDS VIEW');
  2756.         $allowedLoungeIds null;
  2757.         // Procesamiento de Salas (Lounges)
  2758.         $reservationsLoungesSimple $em->getRepository(ReservationLoungeSimple::class)->findByIdReservation($id);
  2759.         $services $em->getRepository(ReservationService::class)->findByReservationId($id);
  2760.         if ($isLegendTeam) {
  2761.             // Buscar espacio LEGEND
  2762.             $lSpace $em->getRepository(Space::class)->createQueryBuilder('s')
  2763.                 ->where('s.name LIKE :n')->setParameter('n''%LEGEND%')
  2764.                 ->setMaxResults(1)->getQuery()->getOneOrNullResult();
  2765.             if ($lSpace) {
  2766.                 $filteredLounges = [];
  2767.                 $allowedLoungeIds = [];
  2768.                 foreach ($reservationsLoungesSimple as $rls) {
  2769.                     $loungeDetails $em->getRepository(ReservationLoungeDetails::class)->find($rls->getIdLounge());
  2770.                     if ($loungeDetails && $loungeDetails->getSpace() && $loungeDetails->getSpace()->getId() === $lSpace->getId()) {
  2771.                         $filteredLounges[] = $rls;
  2772.                         $allowedLoungeIds[] = $rls->getId();
  2773.                     }
  2774.                 }
  2775.                 $reservationsLoungesSimple $filteredLounges;
  2776.             }
  2777.         }
  2778.         $loungesData $this->processLounges($reservationsLoungesSimple);
  2779.         // Cálculos Totales (si es Legend, recalculamos solo para sus salas)
  2780.         $data $this->CalculosTotalesEditSimple($id$reservationsLoungesSimple$services);
  2781.         // Usuarios y Creador
  2782.         $userCreatedBy $em->getRepository(User::class)->find($reserva->getCreatedBy());
  2783.         $createdBy $userCreatedBy ? ($userCreatedBy->getName() . ' ' $userCreatedBy->getLastName()) : '';
  2784.         // Facturación y Finanzas
  2785.         $client $reserva->getClient();
  2786.         $invoicesData $this->calculateInvoicesData($id$reserva$client$em);
  2787.         // Pagos
  2788.         $paymentsAll $em->getRepository(ReservationPaymentsClient::class)->findByReservationId($id);
  2789.         // Datos Adicionales
  2790.         $reservationsLounges $em->getRepository(ReservationLounge::class)->findByIdReservation($id);
  2791.         
  2792.         // Agenda filtrada
  2793.         $agenda $this->agendaService->getAgendaForView($id$allowedLoungeIds);
  2794.         return $this->render('MDS/VenuesBundle/reservations/show-reservations-simple.html.twig', [
  2795.             'id' => $id,
  2796.             'reserva' => $reserva,
  2797.             'arrayLoungesInFile' => $loungesData['arrayLoungesInFile'],
  2798.             'arrayLoungesByDay' => $loungesData['arrayLoungesByDay'],
  2799.             'facturas' => $invoicesData['allInvoiced'],
  2800.             'totales_global_con_iva' => $data['totales_global_con_iva'] ?? 0,
  2801.             'totales_global_iva' => $data['totales_global_iva'] ?? 0,
  2802.             'totales_global_neto' => $data['totales_global_neto'] ?? 0,
  2803.             'sumatoria_totales_global_con_iva' => $data['sumatoria_totales_global_con_iva'] ?? 0,
  2804.             'sumatoria_totales_global_neto' => $data['sumatoria_totales_global_neto'] ?? 0,
  2805.             'sumatoria_totales_global_iva' => $data['sumatoria_totales_global_iva'] ?? 0,
  2806.             'createdBy' => $createdBy,
  2807.             'lounges' => $reservationsLounges,
  2808.             'serviceLines' => $data['serviceLines'],
  2809.             'paymentsAll' => $paymentsAll,
  2810.             'arregloLineasAgenda' => $agenda,
  2811.             'aveFile' => $reserva->getAveFile(),
  2812.         ]);
  2813.     }
  2814.     /**
  2815.      * @Route("/tracing/add/{id}", name="reservations_venues_tracing_ajax_add", methods={"POST"})
  2816.      * @param int $id
  2817.      * @param Request $request
  2818.      * @param EntityManagerInterface $em
  2819.      * @return \Symfony\Component\HttpFoundation\JsonResponse
  2820.      */
  2821.     public function addTracingAjaxAction(int $idRequest $requestEntityManagerInterface $em)
  2822.     {
  2823.         $reserva $em->getRepository(Reservation::class)->find($id);
  2824.         if (!$reserva) {
  2825.             return new \Symfony\Component\HttpFoundation\JsonResponse(['status' => 'error''msg' => 'Reserva no encontrada'], 404);
  2826.         }
  2827.         $dateStr $request->request->get('tracingDate');
  2828.         $text $request->request->get('tracingText');
  2829.         if (empty($dateStr) || empty($text)) {
  2830.             return new \Symfony\Component\HttpFoundation\JsonResponse(['status' => 'error''msg' => 'Faltan parámetros'], 400);
  2831.         }
  2832.         try {
  2833.             $date = new \DateTime($dateStr);
  2834.             $user $this->getUser();
  2835.             $tracing = new ReservationTracing();
  2836.             $tracing->setReservationId($reserva->getId());
  2837.             $tracing->setDateAt($date);
  2838.             $tracing->setText($text);
  2839.             $tracing->setAgentId($user->getId());
  2840.             $tracing->setViewed('NO');
  2841.             $tracing->setCreatedId($user->getId());
  2842.             $tracing->setUpdatedId($user->getId());
  2843.             $tracing->setCreatedAt(new \DateTime());
  2844.             $tracing->setUpdatedAt(new \DateTime());
  2845.             
  2846.             $em->persist($tracing);
  2847.             $em->flush();
  2848.             return new \Symfony\Component\HttpFoundation\JsonResponse(['status' => 'ok']);
  2849.         } catch (\Exception $e) {
  2850.             return new \Symfony\Component\HttpFoundation\JsonResponse(['status' => 'error''msg' => $e->getMessage()], 500);
  2851.         }
  2852.     }
  2853.     private function createReservationLoungeCreateForm(ReservationLounge $entity)
  2854.     {
  2855.         $form $this->createForm(ReservationLoungeType::class, $entity, array(
  2856.             'action' => $this->generateUrl(
  2857.                 'reservations_venues_create_simple_lounge',
  2858.                 array(
  2859.                     'id' => $entity->getIdReservation(),
  2860.                 )
  2861.             ),
  2862.             'method' => 'POST'
  2863.         ));
  2864.         return $form;
  2865.     }
  2866.     private function createReservationLoungeMonDesCreateForm(ReservationLounge $entity)
  2867.     {
  2868.         $form $this->createForm(ReservationLoungeType::class, $entity, array(
  2869.             'action' => $this->generateUrl(
  2870.                 'reservations_venues_create_simple_lounge_mondes',
  2871.                 array(
  2872.                     'id' => $entity->getIdReservation(),
  2873.                 )
  2874.             ),
  2875.             'method' => 'POST'
  2876.         ));
  2877.         return $form;
  2878.     }
  2879.     /**
  2880.      * @Route("/contract/{id}", name="reservations_contract")
  2881.      */
  2882.     public function goContractAction($idEntityManagerInterface $em): Response
  2883.     {
  2884.         try {
  2885.             $dataContract $this->docContractService->renderContractTemplate((int)$id);
  2886.         } catch (\RuntimeException $e) {
  2887.             $this->addFlash('mensajereservationerror'$e->getMessage());
  2888.             $docContract $em->getRepository(DocContract::class)->find($id);
  2889.             $reservaId $docContract $docContract->getReservation()?->getId() : null;
  2890.             if ($reservaId) {
  2891.                 return $this->redirectToRoute('reservations_venues_edit_simple', ['id' => $reservaId]);
  2892.             }
  2893.             return $this->redirectToRoute('homepage');
  2894.         }
  2895.         return $this->render(
  2896.             'MDS/VenuesBundle/reservations/print-contract-gp.html.twig',
  2897.             array(
  2898.                 'dataContract' => $dataContract,
  2899.             )
  2900.         );
  2901.     }
  2902.     /**
  2903.      * @Route("/contract/{id}/save", name="reservations_contract_save", methods={"POST"})
  2904.      */
  2905.     public function saveContractAction(int $idRequest $requestEntityManagerInterface $em): JsonResponse
  2906.     {
  2907.         // 1. Obtener el contrato por su propio ID (ya no por ID de reserva)
  2908.         $docContract $em->getRepository(DocContract::class)->find($id);
  2909.         if (!$docContract) {
  2910.             return new JsonResponse(['status' => 'error''message' => 'Contrato no encontrado'], 404);
  2911.         }
  2912.         // 2. Obtener el contenido enviado por AJAX
  2913.         $content $request->request->get('content');
  2914.         if (empty($content)) {
  2915.             return new JsonResponse(['status' => 'error''message' => 'El contenido no puede estar vacío'], 400);
  2916.         }
  2917.         // 3. Actualizar y Guardar
  2918.         $docContract->setContractualDocument($content);
  2919.         $em->flush();
  2920.         return new JsonResponse(['status' => 'success''message' => 'Contrato guardado correctamente']);
  2921.     }
  2922.     /**
  2923.      * Muestra el contenido actual del contrato en una vista simple.
  2924.      * Se usa para abrir la "copia de seguridad" en una nueva pestaña.
  2925.      *
  2926.      * @Route("/contract/{id}/show-current", name="reservations_contract_show_current", methods={"GET"})
  2927.      */
  2928.     public function showCurrentContractAction(int $idEntityManagerInterface $em): Response
  2929.     {
  2930.         $docContract $em->getRepository(DocContract::class)->find($id);
  2931.         if (!$docContract) {
  2932.             throw $this->createNotFoundException('El contrato no existe.');
  2933.         }
  2934.         return $this->render('MDS/VenuesBundle/reservations/show_raw_contract.html.twig', [
  2935.             'contract_content' => $docContract->getContractualDocument()
  2936.         ]);
  2937.     }
  2938.     /**
  2939.      * Resincroniza el contrato desde su modelo original.
  2940.      *
  2941.      * @Route("/contract/{id}/resync", name="reservations_contract_resync", methods={"POST"})
  2942.      */
  2943.     public function resyncContractAction(int $idDocContractService $docContractServiceEntityManagerInterface $em): JsonResponse
  2944.     {
  2945.         try {
  2946.             $docContract $em->getRepository(DocContract::class)->find($id);
  2947.             if (!$docContract) {
  2948.                 return new JsonResponse(['status' => 'error''message' => 'Contrato no encontrado'], 404);
  2949.             }
  2950.             $newContent $docContractService->renderContractModelTemplate($docContract);
  2951.             // Actualizamos la entidad y guardamos en la BBDD.
  2952.             // $docContract->setContractualDocument($newContent);
  2953.             // $em->flush();
  2954.             // 4. Devolvemos el nuevo contenido al frontend.
  2955.             return new JsonResponse([
  2956.                 'status' => 'success',
  2957.                 'newContent' => $newContent
  2958.             ]);
  2959.         } catch (\Exception $e) {
  2960.             // Captura cualquier error que pueda ocurrir durante el renderizado y devuelve código HTTP 200 con status error
  2961.             return new JsonResponse(['status' => 'error''message' => $e->getMessage()], 200);
  2962.         }
  2963.     }
  2964.     /**
  2965.      * @Route("/updateloungegrid", name="reservations_venues_updateloungegrid", methods={"POST"})
  2966.      */
  2967.     public function updateLoungeGridAction(
  2968.         EntityManagerInterface $em,
  2969.         Request $request,
  2970.         TokenStorageInterface $tokenStorage
  2971.     ): Response {
  2972.         // 1. Obtención y validación de datos iniciales
  2973.         $reservationsLoungeGrid $request->request->all('lounge');
  2974.         $reservationGlobalLounge $request->request->all('reservation_global_lounge');
  2975.         $id $request->request->get('reservationId');
  2976.         $reserva $em->getRepository(Reservation::class)->find($id);
  2977.         if (!$reserva) {
  2978.             throw new NotFoundHttpException('Reserva no encontrada.');
  2979.         }
  2980.         $userLogueado $tokenStorage->getToken()?->getUser();
  2981.         $userId $userLogueado instanceof User $userLogueado->getId() : null;
  2982.         // 2. Pre-carga de datos para evitar consultas en bucle (Optimization N+1)
  2983.         // Mapeamos LoungeDetails por nombre para acceso rápido
  2984.         $loungeDetailsMap = [];
  2985.         $allLoungeDetails $em->getRepository(ReservationLoungeDetails::class)->findAll();
  2986.         foreach ($allLoungeDetails as $detail) {
  2987.             $loungeDetailsMap[$detail->getName()] = $detail;
  2988.         }
  2989.         // Cargamos la tasa de IVA por defecto
  2990.         $defaultSageVatRate $em->getRepository(SageVatRates::class)->findOneBy(['sageCode' => '03']);
  2991.         // Cache y arreglo diferido de agendas
  2992.         $sageArticlesCache = [];
  2993.         $agendasToProcess = [];
  2994.         // Carga masiva (Batch Pre-load) de Entidades ReservationLoungeSimple
  2995.         $loungeSimplesCache = [];
  2996.         if (is_array($reservationsLoungeGrid)) {
  2997.             $loungeIdsToFetch array_filter(array_keys($reservationsLoungeGrid), function($id) {
  2998.                 return is_numeric($id) && $id 0;
  2999.             });
  3000.             if (!empty($loungeIdsToFetch)) {
  3001.                 $loungesInDb $em->getRepository(ReservationLoungeSimple::class)->findBy(['id' => $loungeIdsToFetch]);
  3002.                 foreach ($loungesInDb as $lounge) {
  3003.                     $loungeSimplesCache[$lounge->getId()] = $lounge;
  3004.                 }
  3005.             }
  3006.         }
  3007.         // 3. Inicialización de fechas extremas para recalcular el rango de la reserva
  3008.         // Usamos variables locales para no modificar la entidad Reserva hasta el final
  3009.         $minDateStart = new DateTime('2999-01-01');
  3010.         $maxDateEnd = new DateTime('2000-01-01');
  3011.         $hasItems false// Flag para saber si procesamos algo
  3012.         $updatedCount 0;
  3013.         // 4. Procesamiento del Grid
  3014.         if (is_array($reservationsLoungeGrid)) {
  3015.             foreach ($reservationsLoungeGrid as $idReservationLounge => $reservationsLoungeData) {
  3016.                 if (!is_array($reservationsLoungeData)) {
  3017.                     continue;
  3018.                 }
  3019.                 // Basado en la estructura recibida, cada ID tiene un único día y una única sala
  3020.                 $dia key($reservationsLoungeData);
  3021.                 $items $reservationsLoungeData[$dia] ?? null;
  3022.                 if (!is_array($items)) {
  3023.                     continue;
  3024.                 }
  3025.                 $name key($items);
  3026.                 $item $items[$name] ?? null;
  3027.                 if (!is_array($item)) {
  3028.                     continue;
  3029.                 }
  3030.                 // Buscar o Crear entidad (usando Identity Map en memoria)
  3031.                 if (array_key_exists($idReservationLounge$loungeSimplesCache)) {
  3032.                             $reservationLounge $loungeSimplesCache[$idReservationLounge];
  3033.                         } else {
  3034.                             $reservationLounge = new ReservationLoungeSimple();
  3035.                             // Asignamos ID solo si es nuevo y persistimos implícitamente al final
  3036.                             // Lo añadimos al cache para evitar crear múltiples objetos vacíos si el mismo "fake id" itera en otro dia
  3037.                             $loungeSimplesCache[$idReservationLounge] = $reservationLounge;
  3038.                         }
  3039.                         // Parseo de horas (Refactorizado a método privado)
  3040.                         $startData $this->reservationService->formatTimeInput($item['dateHourMinStart'] ?? '');
  3041.                         $endData $this->reservationService->formatTimeInput($item['dateHourMinEnd'] ?? '');
  3042.                         $dateStartStr = ($item['newDate'] ?? '') . ' ' $startData['formatted'];
  3043.                         $dateEndStr = ($item['newDate'] ?? '') . ' ' $endData['formatted'];
  3044.                         // Validaciones de lógica de negocio (Sage)
  3045.                         /** @var ReservationLoungeDetails|null $loungeDetail */
  3046.                         $loungeDetail $loungeDetailsMap[$name] ?? null;
  3047.                         // Determinar IVA y Artículo Sage
  3048.                         $targetVat $defaultSageVatRate;
  3049.                         if (array_key_exists('iva'$item) && !empty($item['iva']) && is_numeric($item['iva'])) {
  3050.                             // Si viene un ID de IVA, tendríamos que buscar la entidad. 
  3051.                             // Asumo que $item['iva'] es el ID o la entidad si Symfony lo mapea, 
  3052.                             // pero para seguridad buscamos la referencia si es un ID.
  3053.                             $targetVat $em->getReference(SageVatRates::class, $item['iva']);
  3054.                         }
  3055.                         // Buscamos el artículo. Esto sigue siendo una query por iteración si varía mucho,
  3056.                         // pero es necesario ya que depende de la combinación VAT + Nombre.
  3057.                         $sageArticle null;
  3058.                         // Si el modulo de Sage no está activo no se hace
  3059.                         if ($this->session->get('_config')['msage']) {
  3060.                             if ($loungeDetail) {
  3061.                                 $cacheKey $targetVat->getId() . '_' $loungeDetail->getName();
  3062.                                 if (!array_key_exists($cacheKey$sageArticlesCache)) {
  3063.                                     $sageArticlesCache[$cacheKey] = $em->getRepository(SageArticle::class)->findOneBy([
  3064.                                         'vatType' => $targetVat,
  3065.                                         'name' => $loungeDetail->getName()
  3066.                                     ]);
  3067.                                 }
  3068.                                 $sageArticle $sageArticlesCache[$cacheKey];
  3069.                             }
  3070.                             if (!$sageArticle && $loungeDetail) {
  3071.                                 // Intento fallback con default VAT si falló el específico
  3072.                                 $cacheKeyFallback $defaultSageVatRate->getId() . '_' $loungeDetail->getName();
  3073.                                 if (!array_key_exists($cacheKeyFallback$sageArticlesCache)) {
  3074.                                     $sageArticlesCache[$cacheKeyFallback] = $em->getRepository(SageArticle::class)->findOneBy([
  3075.                                         'vatType' => $defaultSageVatRate,
  3076.                                         'name' => $loungeDetail->getName()
  3077.                                     ]);
  3078.                                 }
  3079.                                 $sageArticle $sageArticlesCache[$cacheKeyFallback];
  3080.                             }
  3081.                             if (!$sageArticle) {
  3082.                                 $this->addFlash('mensajereservationerror''No se ha encontrado el artículo de Sage para la sala: ' $name);
  3083.                                 continue;
  3084.                             }
  3085.                         }
  3086.                         // Asignación de datos
  3087.                         $reservationLounge->setIdReservation((int) $id);
  3088.                         // Datos heredados de ReservationGlobalLounge
  3089.                         if ($loungeDetail && isset($reservationGlobalLounge[$loungeDetail->getId()])) {
  3090.                             $globalData $reservationGlobalLounge[$loungeDetail->getId()];
  3091.                             $reservationLounge->setIdLounge($loungeDetail->getId());
  3092.                             $reservationLounge->setImportantDescription($globalData['importantDescription'] ?? null);
  3093.                             $reservationLounge->setImportantDescGeneralText($globalData['importantDescGeneralText'] ?? null);
  3094.                             $reservationLounge->setImportantDescSchedules($globalData['importantDescSchedules'] ?? null);
  3095.                             $reservationLounge->setImportantDescParking($globalData['importantDescParking'] ?? null);
  3096.                         } else {
  3097.                             $reservationLounge->setIdLounge(0);
  3098.                         }
  3099.                         // Seteo de valores simples
  3100.                         $price $item['price'] ?? 0;
  3101.                         $pax = !empty($item['pax']) ? $item['pax'] : 0;
  3102.                         // if(!array_key_exists('type', $item)){
  3103.                         //     dd($item);
  3104.                         // }
  3105.                         // dump($item['type']);
  3106.                         if (!array_key_exists('type'$item)){
  3107.                             $type = empty($item['pax']) ? ($item['type'] ?? null) : null// Lógica original invertida para type
  3108.                         } else{
  3109.                             $type $item['type'];
  3110.                         }
  3111.                 
  3112.                         try {
  3113.                             $dtStart = new DateTime($dateStartStr);
  3114.                             $dtEnd = new DateTime($dateEndStr);
  3115.                             $reservationLounge->setDateStart($dtStart);
  3116.                             $reservationLounge->setDateEnd($dtEnd);
  3117.                             // Actualizar rango global
  3118.                             if ($dtStart $minDateStart) {
  3119.                                 $minDateStart = clone $dtStart;
  3120.                                 $hasItems true;
  3121.                             }
  3122.                             if ($dtEnd $maxDateEnd) {
  3123.                                 $maxDateEnd = clone $dtEnd;
  3124.                                 $hasItems true;
  3125.                             }
  3126.                         } catch (\Exception $e) {
  3127.                             // Ignorar fechas inválidas
  3128.                         }
  3129.                         $reservationLounge->setType($type);
  3130.                         $reservationLounge->setPax($pax);
  3131.                         $reservationLounge->setServicePrice($price);
  3132.                         $reservationLounge->setSageIva($targetVat);
  3133.                         $reservationLounge->setOpIva(1);
  3134.                         $reservationLounge->setLoungeName($name);
  3135.                         // Horas desglosadas
  3136.                         $reservationLounge->setHourStart($startData['hour']);
  3137.                         $reservationLounge->setMinStart($startData['min']);
  3138.                         $reservationLounge->setHourEnd($endData['hour']);
  3139.                         $reservationLounge->setMinEnd($endData['min']);
  3140.                         $reservationLounge->setLanguage($reservationGlobalLounge['language'] ?? 'es'); // Default 'es' por seguridad
  3141.                         $reservationLounge->setUpdatedBy($userId);
  3142.                         $reservationLounge->setCreatedBy($userId); // Nota: Originalmente sobreescribe createdBy al editar
  3143.                         $reservationLounge->setSageArticle($sageArticle);
  3144.                         $em->persist($reservationLounge);
  3145.                         $updatedCount++;
  3146.                         // Guardamos en memoria para procesar en bloque después del flush global
  3147.                         $agendasToProcess[] = $reservationLounge;
  3148.             }
  3149.         }
  3150.         // 5. Persistencia y Actualización Diferida (Salas y Agendas)
  3151.         try {
  3152.             if ($updatedCount 0) {
  3153.                 // Solo actualizamos las fechas de la reserva si procesamos items válidos
  3154.                 // y si las fechas calculadas expanden el rango actual (según lógica original).
  3155.                 if ($hasItems) {
  3156.                     $this->reservationService->updateReservationDates($reserva);
  3157.                 }
  3158.                 // Flush GLOBAL para guardar salas y evitar llamadas continuas a BD 
  3159.                 $em->flush();
  3160.                 
  3161.                 // --- Post Procesamiento Diferido de Agenda ---
  3162.                 foreach ($agendasToProcess as $rLounge) {
  3163.                     $this->agendaService->createAgendaFromSource(
  3164.                         $rLounge->getIdReservation(),
  3165.                         'SALAS A UTILIZAR',
  3166.                         null,
  3167.                         null,
  3168.                         $rLounge->getDateStart(),
  3169.                         $rLounge->getDateEnd(),
  3170.                         $rLounge->getLoungename(),
  3171.                         $rLounge->getId(),
  3172.                         'ReservationLoungeSimple',
  3173.                         $rLounge->getUpdatedBy(),
  3174.                         false // $doFlush = false para englobarlo en el último flush
  3175.                     );
  3176.                 }
  3177.                 // Se llama al servicio para actualizar en la agenda de las fechas
  3178.                 $this->agendaService->updateDatesLine($id$userId);
  3179.                 // Actualizamos el Pax de la Agenda
  3180.                 $paxAge $this->agendaService->calculatePaxForReservation($id);
  3181.                 $this->agendaService->updatePaxLine($id$paxAge$userId);
  3182.                 // Ultimo Flush global para aplicar la agenda calculada sin latencias
  3183.                 $em->flush();
  3184.                 $this->addFlash('mensajereservation''The Item has been updated.');
  3185.             }
  3186.         } catch (\Exception $e) {
  3187.             $this->addFlash('mensajereservationerror''An error occurred: ' $e->getMessage());
  3188.         }
  3189.         // Creamos la Snapshot de las salas y servicios del sistema (LOG)
  3190.         $version $this->venueService->createSnapshot($reserva);
  3191.         return $this->redirectToRoute('reservations_venues_edit_simple', [
  3192.             'id' => $id,
  3193.             'token' => null,
  3194.             '_fragment' => 'btn_quotes'
  3195.         ]);
  3196.     }
  3197.     /**
  3198.      * @Route("/deleteitemservice/{idService}/{idReservation}", name="reservations_venues_deleteitemservice")
  3199.      */
  3200.     public function deleteItemServiceAction($idService$idReservationEntityManagerInterface $emRequest $request)
  3201.     {
  3202.         $service $em->getRepository(ReservationService::class)->findOneById($idService);
  3203.         $em->remove($service);
  3204.         $em->flush();
  3205.         $event 'The Item has been deleted.';
  3206.         $successMessage $this->translator->trans($event);
  3207.         $this->addFlash('mensajereservation'$successMessage);
  3208.         return $this->redirectToRoute('reservations_venues_edit_simple', array('id' => $idReservation'token' => null));
  3209.     }
  3210.     /**
  3211.      * @Route("/updateservicegrid/{id}", name="reservations_venues_updateservicegrid", requirements={"id"="\d+"}, methods={"POST"})
  3212.      */
  3213.     public function updateServiceGridAction(
  3214.         int $id,
  3215.         EntityManagerInterface $em,
  3216.         Request $request,
  3217.         TokenStorageInterface $tokenStorage,
  3218.         TranslatorInterface $translator,
  3219.         SyncronizationsCateringService $syncCateringService,
  3220.         SyncronizationsAVService $syncAVService,
  3221.         AppConfigManager $configManager
  3222.     ): Response {
  3223.         $servicesInput $request->request->all('services');
  3224.         if (!is_array($servicesInput)) {
  3225.             $servicesInput = [];
  3226.         }
  3227.         $reserva $em->getRepository(Reservation::class)->find($id);
  3228.         if (!$reserva) {
  3229.             throw new NotFoundHttpException('Reservation not found');
  3230.         }
  3231.         $userLogueado $tokenStorage->getToken()?->getUser();
  3232.         $userId $userLogueado instanceof User $userLogueado->getId() : null;
  3233.         $agendaSecurity null;
  3234.         // 1. Pre-carga de configuraciones y datos globales
  3235.         $sessionConfig $request->getSession()->get('_config', []);
  3236.         $mcatering = !empty($sessionConfig['mcatering']);
  3237.         $mav = !empty($sessionConfig['mav']);
  3238.         $msage = !empty($sessionConfig['msage']);
  3239.         $cachedSuppliers = [];
  3240.         // Datos para Sincronización
  3241.         $htFile $em->getRepository(HtFile::class)->findByReservation($reserva);
  3242.         $aveFile $em->getRepository(AveFiles::class)->findByReservation($reserva);
  3243.         // Determinamos el VAT Rate base (Lógica original SUCOE como valor por defecto)
  3244.         $sageIvaCode = ($reserva->IsSucoe()) ? '00' '03';
  3245.         $defaultSageVatRate $em->getRepository(SageVatRates::class)->findOneBy(['sageCode' => $sageIvaCode]);
  3246.         $updatedCount 0;
  3247.         foreach ($servicesInput as $idService => $serviceData) {
  3248.             $serviceEntity $em->getRepository(ReservationService::class)->find($idService);
  3249.             if (!$serviceEntity) {
  3250.                 $serviceEntity = new ReservationService();
  3251.                 $serviceEntity->setReservationId($id);
  3252.             }
  3253.             // --- 1. Datos Básicos ---
  3254.             $supplierId = isset($serviceData['supplier']) ? (int) $serviceData['supplier'] : null;
  3255.             $serviceEntity->setSupplierId($supplierId);
  3256.             // --- 2. Agente / Nombre ---
  3257.             $this->resolveAgentAndName($serviceEntity$serviceData$em);
  3258.             // --- 3. Precios y Numéricos ---
  3259.             $serviceEntity->setPrice($this->parseCurrency($serviceData['price'] ?? null, (float) $serviceEntity->getPrice()));
  3260.             $serviceEntity->setCommission($this->parseCurrency($serviceData['commission'] ?? null, (float) $serviceEntity->getCommission(), true));
  3261.             $serviceEntity->setOver($this->parseCurrency($serviceData['over'] ?? null, (float) $serviceEntity->getOver()));
  3262.             $serviceEntity->setCurrency($serviceData['currency'] ?? null);
  3263.             $serviceEntity->setUnits($serviceData['units'] ?? null);
  3264.             $serviceEntity->setPax($serviceData['pax'] ?? null);
  3265.             $serviceEntity->setOpCommission($serviceData['opCommission'] ?? null);
  3266.             $serviceEntity->setOpOver($serviceData['opOver'] ?? null);
  3267.             $serviceEntity->setOpIva($serviceData['opIva'] ?? null);
  3268.             // --- 4. Flags ---
  3269.             $serviceEntity->setToinvoice(array_key_exists('toinvoice'$serviceData));
  3270.             $serviceEntity->setViewInfo(array_key_exists('viewinfo'$serviceData));
  3271.             // --- 5. Fechas ---
  3272.             try {
  3273.                 $startStr = ($serviceData['dateInAt'] ?? '') . ' ' . ($serviceData['start'] ?? '00:00');
  3274.                 $endStr = ($serviceData['dateOutAt'] ?? '') . ' ' . ($serviceData['end'] ?? '00:00');
  3275.                 $serviceEntity->setDateInAt(new DateTime($startStr));
  3276.                 $serviceEntity->setDateOutAt(new DateTime($endStr));
  3277.             } catch (\Exception $e) {
  3278.                 // Error de fecha silenciado según lógica original
  3279.             }
  3280.             $serviceEntity->setUpdatedId($userId);
  3281.             $serviceEntity->setUpdatedAt(new DateTime('now'));
  3282.             // --- 6. LÓGICA DE IVA Y ARTÍCULO SAGE (MODIFICADO) ---
  3283.             $catName $serviceEntity->getServiceCatName();
  3284.             // 6.1 Priorizar el IVA enviado desde el formulario
  3285.             if (isset($serviceData['iva']) && !empty($serviceData['iva'])) {
  3286.                 $selectedVat $em->getRepository(SageVatRates::class)->find($serviceData['iva']);
  3287.                 if ($selectedVat) {
  3288.                     $serviceEntity->setSageIva($selectedVat);
  3289.                 }
  3290.             } else {
  3291.                 // Si no se envía IVA (o el select estaba vacío), aplicamos el SUCOE/Default
  3292.                 $serviceEntity->setSageIva($defaultSageVatRate);
  3293.             }
  3294.             // 6.2 Buscar el artículo Sage basándonos en el IVA asignado arriba
  3295.             $sageArticle $em->getRepository(SageArticle::class)->findOneBy([
  3296.                 'vatType' => $serviceEntity->getSageIva(),
  3297.                 'name'    => $catName
  3298.             ]);
  3299.             if (!$sageArticle && $msage) {
  3300.                 $this->addFlash(
  3301.                     'mensajereservationerror',
  3302.                     'No se ha encontrado el artículo de Sage para el servicio: ' $catName ' con el IVA ' $serviceEntity->getSageIva()?->getIva() . '%. No se ha podido actualizar.'
  3303.                 );
  3304.                 return $this->redirectToRoute('reservations_venues_edit_simple', [
  3305.                     'id' => $id,
  3306.                     '_fragment' => 'btn_srv'
  3307.                 ]);
  3308.             }
  3309.             $serviceEntity->setSageArticle($sageArticle);
  3310.             $em->persist($serviceEntity);
  3311.             if (($serviceEntity->getServiceCatId() == 17)) {
  3312.                 $agendaSecurity[] = array(
  3313.                     'units' => $serviceEntity->getUnits(),
  3314.                     'pax' => $serviceEntity->getPax(),
  3315.                     'dateStart' => $serviceEntity->getDateInAt(),
  3316.                     'dateEnd' => $serviceEntity->getDateOutAt(),
  3317.                 );
  3318.             }
  3319.             $updatedCount++;
  3320.             // --- 7. Sincronizaciones ---
  3321.             if ($supplierId) {
  3322.                 if (!isset($cachedSuppliers[$supplierId])) {
  3323.                     $cachedSuppliers[$supplierId] = $em->getRepository(Supplier::class)->find($supplierId);
  3324.                 }
  3325.                 $supplier $cachedSuppliers[$supplierId];
  3326.                 if ($supplier) {
  3327.                     $this->handleSynchronization(
  3328.                         $reserva,
  3329.                         $serviceEntity,
  3330.                         $supplier,
  3331.                         $mcatering,
  3332.                         $mav,
  3333.                         $htFile,
  3334.                         $aveFile,
  3335.                         $userLogueado,
  3336.                         $syncCateringService,
  3337.                         $syncAVService,
  3338.                         $em,
  3339.                         $configManager
  3340.                     );
  3341.                 }
  3342.             }
  3343.         }
  3344.         // Actualizamos la línea de Seguridad
  3345.         if ($agendaSecurity) {
  3346.             $this->agendaService->updateSecurityLine($id$agendaSecurity$userId);
  3347.         }
  3348.         try {
  3349.             if ($updatedCount 0) {
  3350.                 $em->flush();
  3351.                 $this->addFlash('mensajereservation'$translator->trans('The Item has been updated.'));
  3352.             }
  3353.         } catch (\Exception $e) {
  3354.             $this->addFlash('mensajereservationerror'$translator->trans('An error occurred: ' $e->getMessage()));
  3355.         }
  3356.         $this->venueService->createSnapshot($reserva);
  3357.         return $this->redirectToRoute('reservations_venues_edit_simple', [
  3358.             'id' => $id,
  3359.             'token' => null,
  3360.             '_fragment' => 'btn_srv'
  3361.         ]);
  3362.     }
  3363.     /**
  3364.      * @Route("/addloungegeneral", name="reservations_venues_add_lounge_general")
  3365.      */
  3366.     public function addLoungeGeneralAction(EntityManagerInterface $emRequest $request)
  3367.     {
  3368.         $reservationsLounge $request->request->get('lounge_price');
  3369.         $yaExisteLounge $em->getRepository(ReservationLoungeDetails::class)->findOneByName($reservationsLounge['name']);
  3370.         if (!empty($yaExisteLounge)) {
  3371.             //Si ya existe la sala con ese nombre se envia a la pantalla de edicion de la sala en cuestion
  3372.             $id $yaExisteLounge->getId();
  3373.             return $this->redirectToRoute('reservations_lounge_details', array('id' => $id));
  3374.         }
  3375.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  3376.         $user_id $user_logueado->getId();
  3377.         $now = new DateTime('now');
  3378.         $reservationsLoungeNew = new ReservationLoungeDetails();
  3379.         $reservationsLoungeNew->setName($reservationsLounge['name']);
  3380.         $reservationsLoungeNew->setMeters($reservationsLounge['meters']);
  3381.         $reservationsLoungeNew->setLength($reservationsLounge['length']);
  3382.         $reservationsLoungeNew->setWidth($reservationsLounge['width']);
  3383.         $reservationsLoungeNew->setHeight($reservationsLounge['height']);
  3384.         $reservationsLoungeNew->setCapSchool($reservationsLounge['capschool']);
  3385.         $reservationsLoungeNew->setCapTheater($reservationsLounge['captheater']);
  3386.         $reservationsLoungeNew->setCapCocktail($reservationsLounge['capcocktail']);
  3387.         $reservationsLoungeNew->setCapBanquet($reservationsLounge['capbanquet']);
  3388.         $reservationsLoungeNew->setCapImperial($reservationsLounge['capimperial']);
  3389.         $reservationsLoungeNew->setCreatedId($user_id);
  3390.         $reservationsLoungeNew->setCreatedAt($now);
  3391.         $reservationsLoungeNew->setUpdatedId($user_id);
  3392.         $reservationsLoungeNew->setUpdatedAt($now);
  3393.         try {
  3394.             $em->persist($reservationsLoungeNew);
  3395.             $em->flush();
  3396.             $event 'The Item has been created.';
  3397.             $successMessage $this->translator->trans($event);
  3398.             $this->addFlash('mensajereservation'$successMessage);
  3399.         } catch (\Exception $e) {
  3400.             $event 'An error occurred: ' $e->getMessage();
  3401.             $errorMessage $this->translator->trans($event);
  3402.             $this->addFlash('mensajereservationerror'$errorMessage);
  3403.         }
  3404.         if (!empty($reservationsLoungeNew->getId())) {
  3405.             // Esto pertenece a otra entidad
  3406.             $reservationsLoungeNewDescription = new ReservationLoungeDescription();
  3407.             $reservationsLoungeNewDescription->setLoungeId($reservationsLoungeNew->getId());
  3408.             $reservationsLoungeNewDescription->setLanguage($reservationsLounge['language']);
  3409.             $reservationsLoungeNewDescription->setDescription($reservationsLounge['description']);
  3410.             $reservationsLoungeNewDescription->setCreatedId($user_id);
  3411.             $reservationsLoungeNewDescription->setCreatedAt($now);
  3412.             $reservationsLoungeNewDescription->setUpdatedId($user_id);
  3413.             $reservationsLoungeNewDescription->setUpdatedAt($now);
  3414.             try {
  3415.                 $em->persist($reservationsLoungeNewDescription);
  3416.                 $em->flush();
  3417.                 $event 'The Item has been created.';
  3418.                 $successMessage $this->translator->trans($event);
  3419.                 $this->addFlash('mensajereservation'$successMessage);
  3420.             } catch (\Exception $e) {
  3421.                 $event 'An error occurred: ' $e->getMessage();
  3422.                 $errorMessage $this->translator->trans($event);
  3423.                 $this->addFlash('mensajereservationerror'$errorMessage);
  3424.             }
  3425.             return $this->redirectToRoute('reservations_lounge_details', array('id' => $reservationsLoungeNew->getId()));
  3426.         }
  3427.         return $this->redirectToRoute('reservations_venues_edit_general');
  3428.     }
  3429.     /**
  3430.      * @Route("/addloungedescription/{id}", name="reservations_venues_add_lounge_description")
  3431.      */
  3432.     public function addLoungeDescriptionAction($idRequest $request)
  3433.     {
  3434.         $em $this->getDoctrine()->getManager();
  3435.         /* Obtengo usuario logueado */
  3436.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  3437.         $user_id $user_logueado->getId();
  3438.         $now = new DateTime('now');
  3439.         $reservationsLoungeDescriptoin $request->request->get('lounge_description');
  3440.         //        $reservationsLoungeDetail = $em->getRepository(ReservationLoungeDetails::class)->findOneById($id);
  3441.         //        $reservationsLoungeDetail->setImportantDescription($reservationsLoungeDescriptoin['importantDescription']);
  3442.         //
  3443.         //        $em->persist($reservationsLoungeDetail);
  3444.         //        $em->flush();
  3445.         if (empty($reservationsLoungeDescriptoin['language']) or empty($reservationsLoungeDescriptoin['description'])) {
  3446.             return $this->redirectToRoute('reservations_lounge_details', array('id' => $id));
  3447.         }
  3448.         $newLoungeDescription = new reservationLoungeDescription();
  3449.         $newLoungeDescription->setLoungeId($id);
  3450.         $newLoungeDescription->setLanguage($reservationsLoungeDescriptoin['language']);
  3451.         $newLoungeDescription->setDescription($reservationsLoungeDescriptoin['description']);
  3452.         $newLoungeDescription->setCreatedId($user_id);
  3453.         $newLoungeDescription->setUpdatedId($user_id);
  3454.         $newLoungeDescription->setCreatedAt($now);
  3455.         $newLoungeDescription->setUpdatedAt($now);
  3456.         try {
  3457.             $em->persist($newLoungeDescription);
  3458.             $em->flush();
  3459.             $event 'The Item has been created.';
  3460.             //            $successMessage = $this->translator->trans($event);
  3461.             $successMessage 'El elemento ha sido creado.';
  3462.             $this->addFlash('mensajereservation'$successMessage);
  3463.         } catch (\Exception $e) {
  3464.             $event 'An error occurred: ' $e->getMessage();
  3465.             $errorMessage $this->translator->trans($event);
  3466.             $this->addFlash('mensajereservationerror'$errorMessage);
  3467.         }
  3468.         return $this->redirectToRoute('reservations_lounge_details', array('id' => $id));
  3469.     }
  3470.     /**
  3471.      * @Route("/addwebinfo/{id}", name="reservations_venues_add_web_info")
  3472.      * Actualiza la información de la sala a presentar en la web, que esta almacenada por defecto
  3473.      * Actualiza la información del contrato
  3474.      */
  3475.     public function addLoungeWebInfoAction($idEntityManagerInterface $emRequest $request)
  3476.     {
  3477.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  3478.         $user_id $user_logueado->getId();
  3479.         $now = new \DateTimeImmutable('now');
  3480.         $reservationsLounge $em->getRepository(ReservationLoungeDetails::class)->findOneById($id);
  3481.         if (empty($reservationsLounge)) {
  3482.             $this->addFlash('mensajereservationerror''Error, no se ha encontrado la sala con ID: ' $id);
  3483.             return $this->redirectToRoute('reservations_venues_edit_general');
  3484.         }
  3485.         $reservationsLoungeWebDescription $request->request->get('lounge_web_description') ?? [];
  3486.         foreach ($reservationsLoungeWebDescription as $key => $descriptions) {
  3487.             $reservationsLoungeDetail $em->getRepository(ReservationLoungeWebDescription::class)->findOneBy(array('lounge' => $reservationsLounge'language' => $key));
  3488.             if (empty($reservationsLoungeDetail)) {
  3489.                 $reservationsLoungeDetail = new ReservationLoungeWebDescription();
  3490.                 $reservationsLoungeDetail->setLounge($reservationsLounge);
  3491.                 $reservationsLoungeDetail->setLanguage($key);
  3492.                 $reservationsLoungeDetail->setCreatedId($user_logueado);
  3493.             }
  3494.             $reservationsLoungeDetail->setImportantDescription($descriptions['importantDescription']);
  3495.             $reservationsLoungeDetail->setImportantDescGeneralText($descriptions['importantDescGeneralText']);
  3496.             $reservationsLoungeDetail->setImportantDescSchedules($descriptions['importantDescSchedules']);
  3497.             $reservationsLoungeDetail->setImportantDescParking($descriptions['importantDescParking']);
  3498.             $reservationsLoungeDetail->setUpdatedId($user_logueado);
  3499.             $em->persist($reservationsLoungeDetail);
  3500.         }
  3501.         $em->flush();
  3502.         return $this->redirectToRoute('reservations_lounge_details', array('id' => $id));
  3503.     }
  3504.     /**
  3505.      * @Route("/updatedescritiongrid/{id}", name="reservations_venues_updatedescriptiongrid")
  3506.      */
  3507.     public function updateDescriptionGridAction($idRequest $request)
  3508.     {
  3509.         $descriptions $request->request->get('description');
  3510.         $em $this->getDoctrine()->getManager();
  3511.         /* Obtengo usuario logueado */
  3512.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  3513.         $user_id $user_logueado->getId();
  3514.         foreach ($descriptions as $idDesc => $description) {
  3515.             $descriptionOriginal $em->getRepository(ReservationLoungeDescription::class)->findOneById($idDesc);
  3516.             $descriptionOriginal->setLanguage($description['language']);
  3517.             $descriptionOriginal->setDescription($description['text']);
  3518.             $descriptionOriginal->setUpdatedId($user_id);
  3519.             $descriptionOriginal->setUpdatedAt(new DateTime('now'));
  3520.             try {
  3521.                 $em->persist($descriptionOriginal);
  3522.                 $em->flush();
  3523.                 $event 'The Item has been updated.';
  3524.                 //                $successMessage = $this->translator->trans($event);
  3525.                 $successMessage 'El elemento ha sido actualizado.';
  3526.                 $this->addFlash('mensajereservation'$successMessage);
  3527.             } catch (\Exception $e) {
  3528.                 $event 'An error occurred: ' $e->getMessage();
  3529.                 $errorMessage $this->translator->trans($event);
  3530.                 $this->addFlash('mensajereservationerror'$errorMessage);
  3531.             }
  3532.         }
  3533.         return $this->redirectToRoute('reservations_lounge_details', array('id' => $id));
  3534.     }
  3535.     /**
  3536.      * @Route("/addloungepicture/{id}", name="reservations_venues_add_lounge_picture")
  3537.      */
  3538.     public function addLoungePictureAction($idEntityManagerInterface $emRequest $request//, LoggerInterface $logger)
  3539.     {
  3540.         /* Obtengo usuario logueado */
  3541.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  3542.         $user_id $user_logueado->getId();
  3543.         $now = new DateTime('now');
  3544.         $picturefiles $request->files->all();
  3545.         $reservationsLoungeId $id;
  3546.         $imagenes $picturefiles['loungepicturegallery'];
  3547.         $data $reservationsLoungeId;
  3548.         if (!empty($imagenes['image1']) || !empty($imagenes['image2']) || !empty($imagenes['image3']) || !empty($imagenes['image4']) || !empty($imagenes['image5'])) {
  3549.             $num 0;
  3550.             foreach ($imagenes as $img) {
  3551.                 $num $num;
  3552.                 if (!is_null($img)) {
  3553.                     $data $this->CargarImgGalleryAction($reservationsLoungeId$img$num$request);
  3554.                 } //, $logger);
  3555.             }
  3556.         } else {
  3557.             $errorMessage $this->translator->trans('Error, some fields are empty');
  3558.             $this->addFlash('mensajegalleryerror'$errorMessage);
  3559.         }
  3560.         return $this->redirectToRoute('reservations_lounge_details', array('id' => $id));
  3561.     }
  3562.     protected function CargarImgGalleryAction($reservationsLoungeId$image$numRequest $request//, LoggerInterface $logger)
  3563.     {
  3564.         $gallery = new ReservationLoungePicture();
  3565.         $gallery->setLoungeId($reservationsLoungeId);
  3566.         $gallery->setCreatedAt(new DateTime('now'));
  3567.         $gallery->setUpdatedAt(new DateTime('now'));
  3568.         $gallery->setTitle(null);
  3569.         if ($num == -1) {
  3570.             $gallery->setTitle('Blueprint');
  3571.         }
  3572.         if ($num == 'TEATRO') {
  3573.             $gallery->setTitle('Teatro');
  3574.         }
  3575.         if ($num == 'COCTEL') {
  3576.             $gallery->setTitle('Coctel');
  3577.         }
  3578.         if ($num == 'ESCUELA') {
  3579.             $gallery->setTitle('Escuela');
  3580.         }
  3581.         $id $reservationsLoungeId;
  3582.         /* Carga de imagenes */
  3583.         $calidad "90";
  3584.         $calidadpng "9";
  3585.         $imageName md5(rand() * time());
  3586.         $camino "assets/images/venues/lounges/";
  3587.         $extension $image->guessExtension();
  3588.         $entrada 'si';
  3589.         $image_id $imageName '.' $extension;
  3590.         $image_temp $id '-' $imageName '.' $extension;
  3591.         $image->move($camino$image_temp);
  3592.         // Nombres image
  3593.         $s "small-";
  3594.         $m "medium-";
  3595.         $l "large-";
  3596.         ########################
  3597.         # Copiar imagen 300 x Altura
  3598.         ########################
  3599.         $datos getimagesize($camino $image_temp);
  3600.         $anchura "300";
  3601.         $altura "190";
  3602.         $thumb imagecreatetruecolor($anchura$altura);
  3603.         switch ($extension) {
  3604.             case 'jpeg':
  3605.                 $img imagecreatefromjpeg($camino $image_temp);
  3606.                 imagecopyresampled($thumb$img0000$anchura$altura$datos[0], $datos[1]);
  3607.                 imagejpeg($thumb$camino $s $image_id$calidad);
  3608.                 break;
  3609.             case 'png':
  3610.                 $img imagecreatefrompng($camino $image_temp);
  3611.                 imagecopyresampled($thumb$img0000$anchura$altura$datos[0], $datos[1]);
  3612.                 imagepng($thumb$camino $s $image_id$calidadpng);
  3613.                 break;
  3614.             case 'gif':
  3615.                 $img imagecreatefromgif($camino $image_temp);
  3616.                 imagecopyresampled($thumb$img0000$anchura$altura$datos[0], $datos[1]);
  3617.                 imagegif($thumb$camino $s $image_id);
  3618.                 break;
  3619.         }
  3620.         ########################
  3621.         # Copiar imagen 600 x Altura
  3622.         ########################
  3623.         $datos2 getimagesize($camino $image_temp);
  3624.         $anchura2 "600";
  3625.         $ratio2 = ($datos2[0] / $anchura2);
  3626.         $altura2 round($datos2[1] / $ratio2);
  3627.         $thumb2 imagecreatetruecolor($anchura2$altura2);
  3628.         switch ($extension) {
  3629.             case 'jpeg':
  3630.                 $img2 imagecreatefromjpeg($camino $image_temp);
  3631.                 imagecopyresampled($thumb2$img20000$anchura2$altura2$datos2[0], $datos2[1]);
  3632.                 imagejpeg($thumb2$camino $m $image_id$calidad);
  3633.                 break;
  3634.             case 'png':
  3635.                 $img2 imagecreatefrompng($camino $image_temp);
  3636.                 imagecopyresampled($thumb2$img20000$anchura2$altura2$datos2[0], $datos2[1]);
  3637.                 imagepng($thumb2$camino $m $image_id$calidadpng);
  3638.                 break;
  3639.             case 'gif':
  3640.                 $img2 imagecreatefromgif($camino $image_temp);
  3641.                 imagecopyresampled($thumb2$img20000$anchura2$altura2$datos2[0], $datos2[1]);
  3642.                 imagegif($thumb2$camino $m $image_id);
  3643.                 break;
  3644.         }
  3645.         ########################
  3646.         # Copiar imagen 1600 x Altura
  3647.         ########################
  3648.         $datos3 getimagesize($camino $image_temp);
  3649.         $anchura3 "1600";
  3650.         $ratio3 = ($datos3[0] / $anchura3);
  3651.         $altura3 round($datos3[1] / $ratio3);
  3652.         $thumb3 imagecreatetruecolor($anchura3$altura3);
  3653.         switch ($extension) {
  3654.             case 'jpeg':
  3655.                 $img3 imagecreatefromjpeg($camino $image_temp);
  3656.                 imagecopyresampled($thumb3$img30000$anchura3$altura3$datos3[0], $datos3[1]);
  3657.                 imagejpeg($thumb3$camino $l $image_id$calidad);
  3658.                 break;
  3659.             case 'png':
  3660.                 $img3 imagecreatefrompng($camino $image_temp);
  3661.                 imagecopyresampled($thumb3$img30000$anchura3$altura3$datos3[0], $datos3[1]);
  3662.                 imagepng($thumb3$camino $l $image_id$calidadpng);
  3663.                 break;
  3664.             case 'gif':
  3665.                 $img3 imagecreatefromgif($camino $image_temp);
  3666.                 imagecopyresampled($thumb3$img30000$anchura3$altura3$datos3[0], $datos3[1]);
  3667.                 imagegif($thumb3$camino $l $image_id);
  3668.                 break;
  3669.         }
  3670.         ########################
  3671.         # borrar imagen original
  3672.         ########################
  3673.         $imagen_borrar $camino $image_temp;
  3674.         unlink($imagen_borrar);
  3675.         $gallery->setImageSmall($s $image_id);
  3676.         $gallery->setImageMedium($m $image_id);
  3677.         $gallery->setImageLarge($l $image_id);
  3678.         /* Fin Carga de imagenes */
  3679.         /* Obtengo usuario logueado */
  3680.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  3681.         $user_id $user_logueado->getId();
  3682.         $gallery->setCreatedId($user_id);
  3683.         $gallery->setUpdatedId($user_id);
  3684.         $em $this->getDoctrine()->getManager();
  3685.         /* Gestión de eventos en Log */
  3686.         $user_lastname $user_logueado->getLastname();
  3687.         $user_name $user_logueado->getName();
  3688.         $user_email $user_logueado->getEmail();
  3689.         $user_rol $user_logueado->getRoles();
  3690.         $event_url $request->getPathInfo();
  3691.         $event_complete $user_name ' ' $user_lastname ' - ' $user_email ' - ' $user_rol[0] . ' | ' $event_url;
  3692.         try {
  3693.             $em->persist($gallery);
  3694.             $em->flush();
  3695.             $event 'Images from this supplier have been uploaded.';
  3696.             $successMessage $this->translator->trans($event);
  3697.             $this->addFlash('mensajegallery'$successMessage);
  3698.         } catch (\Exception $e) {
  3699.             $event 'An error occurred: ' $e->getMessage() . ' | transport';
  3700.             /* Para el usuario */
  3701.             $errorMessage $this->translator->trans($event);
  3702.             $this->addFlash('mensajegalleryerror'$errorMessage);
  3703.         }
  3704.         /* Fin Gestión de eventos en Log */
  3705.         return $id;
  3706.     }
  3707.     /**
  3708.      * @Route("/addloungevideo/{id}", name="reservations_venues_add_lounge_video")
  3709.      */
  3710.     public function addLoungeVideoAction($idEntityManagerInterface $emRequest $request//, LoggerInterface $logger)
  3711.     {
  3712.         /* Obtengo usuario logueado */
  3713.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  3714.         $user_id $user_logueado->getId();
  3715.         $now = new DateTime('now');
  3716.         $urlvideo $request->request->get('loungevideo');
  3717.         $urlvideo $urlvideo['urlvideo'];
  3718.         $reservationsLoungeId $id;
  3719.         if (!empty($urlvideo)) {
  3720.             switch (true) {
  3721.                 case strpos($urlvideo'youtube'):
  3722.                     $patron '%^ (?:https?://)? (?:www\.)? (?: youtu\.be/ | youtube\.com (?: /embed/ | /v/ | /watch\?v= ) ) ([\w-]{10,12}) ($|&).* $%x';
  3723.                     preg_match($patron$urlvideo$parte);
  3724.                     $urvideo_final 'https://www.youtube.com/embed/' $parte[1];
  3725.                     break;
  3726.                 case strpos($urlvideo'youtu'):
  3727.                     $patron '%^ (?:https?://)? (?:www\.)? (?: youtu\.be/ | youtube\.com (?: /embed/ | /v/ | /watch\?v= ) ) ([\w-]{10,12}) ($|&).* $%x';
  3728.                     preg_match($patron$urlvideo$parte);
  3729.                     $urvideo_final 'https://www.youtube.com/embed/' $parte[1];
  3730.                     break;
  3731.                 case strpos($urlvideo'vimeo'):
  3732.                     $patron '%^https?:\/\/(?:www\.|player\.)?vimeo.com\/(?:channels\/(?:\w+\/)?|groups\/([^\/]*)\/videos\/|album\/(\d+)\/video\/|video\/|)(\d+)(?:$|\/|\?)(?:[?]?.*)$%im';
  3733.                     preg_match($patron$urlvideo$parte);
  3734.                     $urvideo_final 'https://player.vimeo.com/video/' $parte[3];
  3735.                     break;
  3736.             }
  3737.             if (!empty($urlvideo) && !empty($urvideo_final)) {
  3738.                 $video = new ReservationLoungeVideo();
  3739.                 $video->setCreatedId($user_id);
  3740.                 $video->setUpdatedId($user_id);
  3741.                 $video->setVideo($urvideo_final);
  3742.                 $video->setLoungeId($reservationsLoungeId);
  3743.                 $video->setCreatedAt($now);
  3744.                 $video->setUpdatedAt($now);
  3745.                 $em->persist($video);
  3746.                 $em->flush();
  3747.             }
  3748.         }
  3749.         if (empty($urlvideo)) {
  3750.             $errorMessage $this->translator->trans('Error, some fields are empty');
  3751.             $this->addFlash('mensajegalleryerror'$errorMessage);
  3752.         }
  3753.         return $this->redirectToRoute('reservations_lounge_details', array('id' => $id));
  3754.     }
  3755.     /**
  3756.      * @Route("/deleteloungevideo/{id}", name="reservations_venues_delete_lounge_video")
  3757.      */
  3758.     public function deleteLoungeVideoAction($idEntityManagerInterface $emRequest $request//, LoggerInterface $logger)
  3759.     {
  3760.         $video $em->getRepository(ReservationLoungeVideo::class)->findOneById($id);
  3761.         $idLounge $video->getLoungeId();
  3762.         try {
  3763.             $em->remove($video);
  3764.             $em->flush();
  3765.             //            $event = 'The Item has been deleted.';
  3766.             $successMessage 'El elemento ha sido eliminado.';
  3767.             //            $successMessage = $this->translator->trans($event);
  3768.             $this->addFlash('mensajereservation'$successMessage);
  3769.         } catch (\Exception $e) {
  3770.             $event 'An error occurred: ' $e->getMessage();
  3771.             $errorMessage $this->translator->trans($event);
  3772.             $this->addFlash('mensajereservationerror'$errorMessage);
  3773.         }
  3774.         return $this->redirectToRoute('reservations_lounge_details', array('id' => $idLounge));
  3775.     }
  3776.     /**
  3777.      * @Route("/addloungeblueprints/{id}", name="reservations_venues_add_lounge_blueprints")
  3778.      */
  3779.     public function addLoungeBlueprintsAction($idEntityManagerInterface $emRequest $request//, LoggerInterface $logger)
  3780.     {
  3781.         /* Obtengo usuario logueado */
  3782.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  3783.         $user_id $user_logueado->getId();
  3784.         $now = new DateTime('now');
  3785.         $picturefiles $request->files->all();
  3786.         $reservationsLoungeId $id;
  3787.         $imagen $picturefiles['loungepicturegalleryblueprints'];
  3788.         $data $reservationsLoungeId;
  3789.         if (!empty($imagen)) {
  3790.             $num = -1;
  3791.             $data $this->CargarImgGalleryAction($reservationsLoungeId$imagen$num$request); //, $logger);
  3792.         } else {
  3793.             $errorMessage $this->translator->trans('Error, some fields are empty');
  3794.             $this->addFlash('mensajegalleryerror'$errorMessage);
  3795.         }
  3796.         return $this->redirectToRoute('reservations_lounge_details', array('id' => $id));
  3797.     }
  3798.     /**
  3799.      * @Route("/addpicturemounting/{id}", name="reservations_venues_add_lounge_picture_mounting")
  3800.      */
  3801.     public function addLoungePictureMountingAction($idEntityManagerInterface $emRequest $request//, LoggerInterface $logger)
  3802.     {
  3803.         /* Obtengo usuario logueado */
  3804.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  3805.         $user_id $user_logueado->getId();
  3806.         $now = new DateTime('now');
  3807.         $picturefiles $request->files->all();
  3808.         $reservationsLoungeId $id;
  3809.         $imagen $picturefiles['picturemounting'];
  3810.         $data $reservationsLoungeId;
  3811.         if (!empty($imagen)) {
  3812.             $num $request->request->get('picturemounting');
  3813.             $num $num['type'];
  3814.             $data $this->CargarImgGalleryAction($reservationsLoungeId$imagen$num$request); //, $logger);
  3815.         } else {
  3816.             $errorMessage $this->translator->trans('Error, some fields are empty');
  3817.             $this->addFlash('mensajegalleryerror'$errorMessage);
  3818.         }
  3819.         return $this->redirectToRoute('reservations_lounge_details', array('id' => $id));
  3820.     }
  3821.     /**
  3822.      * @Route("/updatedimmensions/{id}", name="update_dimmensions")
  3823.      */
  3824.     public function updateDimmensionsAction($idEntityManagerInterface $emRequest $request)
  3825.     {
  3826.         $reservationsLounge $em->getRepository(ReservationLoungeDetails::class)->findOneById($id);
  3827.         $newData $request->request->get('loungedimmensions');
  3828.         $reservationsLounge->setMeters($newData['meters']);
  3829.         $reservationsLounge->setLength($newData['length']);
  3830.         $reservationsLounge->setWidth($newData['width']);
  3831.         $reservationsLounge->setHeight($newData['height']);
  3832.         $reservationsLounge->setCapSchool($newData['capSchool']);
  3833.         $reservationsLounge->setCapTheater($newData['capTheater']);
  3834.         $reservationsLounge->setCapCocktail($newData['capCocktail']);
  3835.         $reservationsLounge->setCapBanquet($newData['capBanquet']);
  3836.         $reservationsLounge->setCapImperial($newData['capImperial']);
  3837.         /* Obtengo usuario logueado */
  3838.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  3839.         $user_id $user_logueado->getId();
  3840.         $now = new DateTime('now');
  3841.         $reservationsLounge->setUpdatedId($user_id);
  3842.         $reservationsLounge->setUpdatedAt($now);
  3843.         try {
  3844.             $em->persist($reservationsLounge);
  3845.             $em->flush();
  3846.             $event 'The Note has been created succesfully.';
  3847.             $successMessage $this->translator->trans($event);
  3848.             $this->addFlash('mensaje'$successMessage);
  3849.         } catch (\Exception $e) {
  3850.             $event 'An error occurred: ' $e->getMessage();
  3851.             /* Para el usuario */
  3852.             $errorMessage $this->translator->trans($event);
  3853.             $this->addFlash('mensajeerror'$errorMessage);
  3854.         }
  3855.         return $this->redirectToRoute('reservations_lounge_details', array('id' => $id));
  3856.     }
  3857.     /**
  3858.      * @Route("/get_lounges_by_space", name="venues_get_lounges_by_space", methods={"GET"})
  3859.      */
  3860.     public function getLoungesBySpaceAction(Request $requestEntityManagerInterface $em): JsonResponse
  3861.     {
  3862.         $spaceId $request->query->get('space_id');
  3863.         $lounges = [];
  3864.         if ($spaceId) {
  3865.             $repo $em->getRepository(ReservationLoungeDetails::class);
  3866.             $results $repo->findBy(['space' => $spaceId], ['name' => 'ASC']);
  3867.             foreach ($results as $lounge) {
  3868.                 $lounges[] = [
  3869.                     'id' => $lounge->getId(),
  3870.                     'name' => $lounge->getName()
  3871.                 ];
  3872.             }
  3873.         }
  3874.         return new JsonResponse($lounges);
  3875.     }
  3876.     /**
  3877.      * @Route("/addvisit", name="reservations_venues_addvisit", methods={"GET", "POST"})
  3878.      */
  3879.     public function addVisitAction(EntityManagerInterface $emRequest $request)
  3880.     {
  3881.         $visit = new ReservationVisit();
  3882.         $visit->setDateStart(new \DateTime());
  3883.         // REFACTORIZACIÓN: El array 'agent_choices' ya no es necesario.
  3884.         $form $this->createForm(VisitEditType::class, $visit);
  3885.         $form->handleRequest($request);
  3886.         if ($form->isSubmitted() && $form->isValid()) {
  3887.             // Al estar la lógica dentro de la Entidad, esto ya guarda ambos IDs automáticamente
  3888.             return $this->processVisitForm($form$visit$em$requesttrue);
  3889.         }
  3890.         // Listado de visitas (para la tabla inferior)
  3891.         $visitas $em->getRepository(ReservationVisit::class)
  3892.             ->createQueryBuilder('v')
  3893.             ->leftJoin('v.agent''a')
  3894.             ->addSelect('a')
  3895.             ->orderBy('v.dateStart''DESC')
  3896.             ->setMaxResults(50)
  3897.             ->getQuery()
  3898.             ->getResult();
  3899.         return $this->render('MDS/VenuesBundle/reservations/add-visit.html.twig', [
  3900.             'visitas' => $visitas,
  3901.             'form' => $form->createView(),
  3902.         ]);
  3903.     }
  3904.     /**
  3905.      * @Route("/editvisit/{id}", name="venues_edit_visit", methods={"GET", "POST"})
  3906.      */
  3907.     public function editVisitAction(Request $requestEntityManagerInterface $emint $id): Response
  3908.     {
  3909.         $visit $em->getRepository(\App\MDS\VenuesBundle\Entity\ReservationVisit::class)->find($id);
  3910.         if (!$visit) {
  3911.             throw $this->createNotFoundException('Visita no encontrada');
  3912.         }
  3913.         // REFACTORIZACIÓN: Ya no necesitamos pasar el array de 'agent_choices'
  3914.         $form $this->createForm(\App\MDS\VenuesBundle\Form\VisitEditType::class, $visit);
  3915.         // Preload manual fields (fechas)
  3916.         if ($visit->getDateStart() instanceof \DateTimeInterface) {
  3917.             $form->get('visit_date')->setData($visit->getDateStart());
  3918.             $form->get('visit_time')->setData($visit->getDateStart()->format('H:i'));
  3919.         }
  3920.         // REFACTORIZACIÓN: Todo el bloque de "Agent mapping" SE ELIMINA.
  3921.         // Symfony ahora hace el mapeo automáticamente porque quitamos el 'mapped' => false del formulario.
  3922.         // Space / Lounge mapping
  3923.         $loungeId $visit->getIdLounge();
  3924.         $loadedLounge null;
  3925.         if ($loungeId) {
  3926.             $loadedLounge $em->getRepository(ReservationLoungeDetails::class)->find($loungeId);
  3927.             if ($loadedLounge) {
  3928.                 $form->get('lounge')->setData($loadedLounge);
  3929.                 // Force space from lounge
  3930.                 if ($loadedLounge->getSpace()) {
  3931.                     $form->get('space')->setData($loadedLounge->getSpace());
  3932.                 }
  3933.             }
  3934.         }
  3935.         if (!$loadedLounge && $visit->getSpace()) {
  3936.             $form->get('space')->setData($visit->getSpace());
  3937.         }
  3938.         // Reservation mapping
  3939.         if ($visit->getIdReservation()) {
  3940.             $res $em->getRepository(Reservation::class)->find($visit->getIdReservation());
  3941.             if ($res) {
  3942.                 $form->get('reservation')->setData($res);
  3943.             }
  3944.         }
  3945.         $form->handleRequest($request);
  3946.         if ($form->isSubmitted() && $form->isValid()) {
  3947.             return $this->processVisitForm($form$visit$em$requestfalse);
  3948.         }
  3949.         return $this->render('MDS/VenuesBundle/reservations/edit-visit.html.twig', [
  3950.             'form' => $form->createView(),
  3951.             'visit' => $visit,
  3952.         ]);
  3953.     }
  3954.     /**
  3955.      * @Route("/createvisit", name="reservations_venues_createvisit", methods={"GET", "POST"})
  3956.      */
  3957.     public function createVisitAction(EntityManagerInterface $emRequest $request)
  3958.     {
  3959.         // Redirect logic to addVisitAction to use the same form handling
  3960.         return $this->addVisitAction($em$request);
  3961.     }
  3962.     private function getAgentChoices(EntityManagerInterface $em): array
  3963.     {
  3964.         $users $em->getRepository(\App\Entity\User::class)
  3965.             ->createQueryBuilder('u')
  3966.             ->select('partial u.{id, name, lastname}')
  3967.             // AÑADIMOS EL FILTRO POR EQUIPOS AQUÍ
  3968.             ->where('u.team IN (:teams)')
  3969.             ->setParameter('teams', [416])
  3970.             ->orderBy('u.id''ASC')
  3971.             ->getQuery()
  3972.             ->getResult();
  3973.         $agentChoices = [];
  3974.         foreach ($users as $u) {
  3975.             // PHP 8.1: Uso del operador nullsafe (?->) para simplificar la lógica
  3976.             $label $u->getFullName() ?: ($u->getName() ?: 'Usuario #' $u->getId());
  3977.             $agentChoices[$label] = $u->getId();
  3978.         }
  3979.         return $agentChoices;
  3980.     }
  3981.     private function processVisitForm($form$visitEntityManagerInterface $emRequest $requestbool $isNew)
  3982.     {
  3983.         /* Obtengo usuario logueado */
  3984.         $user_logueado $this->getUser();
  3985.         // 1. Agent
  3986.         $selAgentId $form->get('agent')->getData();
  3987.         if ($selAgentId) {
  3988.             $agent $em->getRepository(\App\Entity\User::class)->find($selAgentId);
  3989.             $visit->setAgent($agent);
  3990.         }
  3991.         // 2. Date/Time -> dateStart / dateEnd
  3992.         $selDate $form->get('visit_date')->getData(); // DateTime object
  3993.         $selTime $form->get('visit_time')->getData(); // String "H:i"
  3994.         if ($selDate && $selTime) {
  3995.             [$h$m] = explode(':'$selTime);
  3996.             $start = (clone $selDate)->setTime((int) $h, (int) $m0);
  3997.             $visit->setDateStart($start);
  3998.             $visit->setDateEnd($start);
  3999.             // Legacy hour/min fields
  4000.             $visit->setHourStart($h);
  4001.             $visit->setMinStart($m);
  4002.             $visit->setHourEnd(sprintf('%02d', (int) $h 1));
  4003.             $visit->setMinEnd($m);
  4004.         }
  4005.         // 3. Space (mapped=true, handled automatically)
  4006.         // Ensure space is set on entity.
  4007.         // 4. Lounge (mapped=false)
  4008.         $lounge $form->get('lounge')->getData(); // ReservationLoungeDetails entity
  4009.         if ($lounge) {
  4010.             $visit->setIdLounge($lounge->getId());
  4011.         } else {
  4012.             $visit->setIdLounge(null); // or 0
  4013.         }
  4014.         // 5. Reservation
  4015.         $res $form->get('reservation')->getData();
  4016.         if ($res) {
  4017.             $visit->setIdReservation($res->getId());
  4018.             // Append title if creating? Legacy logic did: $title . ' - ' . $res->getTitle()
  4019.             // But title is mapped field now.
  4020.             // Maybe we should append only if it's not already there? 
  4021.             // Leaving title as user typed it in form.
  4022.         } else {
  4023.             $visit->setIdReservation(null);
  4024.         }
  4025.         if ($isNew) {
  4026.             $visit->setType('Visit');
  4027.             $visit->setCreatedAt(new \DateTime());
  4028.             $visit->setCreatedId($user_logueado->getId());
  4029.             $visit->setUpdatedAt(new \DateTime());
  4030.             $visit->setUpdatedId($user_logueado->getId());
  4031.             $em->persist($visit);
  4032.             $msg 'Visita creada correctamente';
  4033.             $route 'reservations_venues_addvisit';
  4034.         } else {
  4035.             $visit->setUpdatedAt(new \DateTime());
  4036.             // $visit->setUpdatedId($user_logueado->getId()); // if method exists
  4037.             $msg 'Visita actualizada correctamente';
  4038.             $route 'reservations_venues_addvisit';
  4039.         }
  4040.         $em->flush();
  4041.         $this->addFlash('mensajeclient'$msg);
  4042.         return $this->redirectToRoute($route);
  4043.     }
  4044.     /**
  4045.      * @Route("/deletevisit/{id}", name="get_reservations_deletevisit")
  4046.      */
  4047.     public function deleteVisitAction($idEntityManagerInterface $emRequest $request)
  4048.     {
  4049.         $visit $em->getRepository(ReservationVisit::class)->findOneById($id);
  4050.         if (!empty($visit)) {
  4051.             $em->remove($visit);
  4052.             $em->flush();
  4053.         }
  4054.         return $this->redirectToRoute('reservations_venues_addvisit');
  4055.     }
  4056.     /**
  4057.      * @Route("/sendconfirmationrequestmail/{id}", name="reservations_venues_send_confirmation_request_mail")
  4058.      * Enviar correo a Salvador y Rafael Guerrero para que la reserva (id) pase al estado confirmado
  4059.      */
  4060.     public function sendConfirmationRequestMailAction($idEntityManagerInterface $emRequest $request)
  4061.     {
  4062.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  4063.         $user_id $user_logueado->getId();
  4064.         $mailArrayTo = [];
  4065.         $mailAlert = [];
  4066.         //        $mailArrayTo['salvador@avexpress.tv'] = 'salvador@avexpress.tv';
  4067.         $mailArrayTo['rafael.guerrero@inout-travel.com'] = 'rafael.guerrero@inout-travel.com';
  4068.         //
  4069.         //        $dataGP = $this->disponibilidadVenues($id);
  4070.         //        $dataAV = $this->disponibilidadAvExpress($id);
  4071.         $dataLounges = array();
  4072.         //        foreach ($dataGP as $item){
  4073.         //            $reservationsLounges = $em->getRepository(ReservationLoungeSimple::class)->findBy(array('idReservation'=>$item->getId(),'type'=>null));
  4074.         //            foreach ($reservationsLounges as $elem){ $dataLounges[$item->getId()][] = $elem; }
  4075.         //        }
  4076.         $dataLounges = [];
  4077.         $dataLounges[$id] = $em->getRepository(ReservationLoungeSimple::class)
  4078.             ->findBy(['idReservation' => $id'type' => null]);
  4079.         $reserva $em->getRepository(Reservation::class)->findOneById($id);
  4080.         $agente $em->getRepository(User::class)->findOneById($user_id);
  4081.         $mailAddressFrom $agente->getEmail();
  4082.         $mailSubject 'Confirmación de reserva: ' $reserva->getTitle();
  4083.         $mensajePopup '';
  4084.         $mailBody 'Estimado administrador,' .
  4085.             '<br><br>' $agente->getName() . ' ' $agente->getLastName() . ' ha solicitado la confirmación de la reserva:' .
  4086.             '<br><br>' $reserva->getTitle() . ' con ID: ' $reserva->getId() .
  4087.             '<br>Este evento incia el día ' $reserva->getDateStart()->format('d/m/Y') . ' a las ' $reserva->getDateStart()->format('H:i') . ' y finaliza el día ' $reserva->getDateEnd()->format('d/m/Y') . ' a las ' $reserva->getDateEnd()->format('H:i') . '<br><br><br>';
  4088.         if (!empty($dataGP) or !empty($dataAV)) {
  4089.             if (!empty($dataGP)) {
  4090.                 $mensajePopup .= 'No se puede CONFIRMAR, conflicto con:' '<br><br>';
  4091.                 // Conflictos con otros eventos en Venues
  4092.                 $mailSubject '⚠️ ALERTA️ ‼️ DOBLE CONFIRMADO MISMA SALA' $mailSubject;
  4093.                 $mailBody $mailBody 'Este evento coincide con la(s) reserva(s): <br>';
  4094.                 foreach ($dataGP as $res) {
  4095.                     $mailBody $mailBody 'Reserva: ' $res->getTitle() . ', con ID: ' $res->getId() . ', fecha de inicio: ' $res->getDateStart()->format('d/m/Y') . ' a las ' $res->getDateStart()->format('H:i') . ', fecha de finalización: ' $res->getDateEnd()->format('d/m/Y') . ' a las ' $res->getDateEnd()->format('H:i');
  4096.                     if (!empty($dataLounges[$res->getId()])) {
  4097.                         $mailBody $mailBody ', Salas: ';
  4098.                         foreach ($dataLounges[$res->getId()] as $reservationsLoungeItem) {
  4099.                             $mailBody $mailBody $reservationsLoungeItem->getLoungeName() . ', ';
  4100.                         }
  4101.                         $mailBody $mailBody '<br>';
  4102.                     }
  4103.                     $mensajePopup .= 'Reserva: ' $res->getTitle() . ', con ID: ' $res->getId() . '<br>';
  4104.                 }
  4105.                 $mailBody $mailBody '<br><br>';
  4106.             }
  4107.             if (!empty($dataAV)) {
  4108.                 // Conflictos con otros eventos de AvExpress
  4109.                 $mailBody $mailBody 'Este evento coincide en AV con el expediente(s): <br>';
  4110.                 foreach ($dataAV as $file) {
  4111.                     $mailBody $mailBody 'Expediente: ' $file->getTitle() . ', con ID: ' $file->getId() . ', fecha de inicio: ' $file->getDateStart()->format('d/m/Y H:i') . ', fecha de finalización: ' $file->getDateEnd()->format('d/m/Y H:i') . '<br>';
  4112.                 }
  4113.             }
  4114.             $mailAlert = array('mailBody' => $mailBody'mailSubject' => $mailSubject);
  4115.         }
  4116.         $mailBody $mailBody '<br><br><a href="https://mantevenues.mante.solutions/venues/">CALENDARIO GREEN PATIO</a>';
  4117.         $mailBody $mailBody '<br><br> <a href="https://mantevenues.mante.solutions/venues/adminconfirmres/y/' $id '">"SI"</a> deseo confirmar la reserva.';
  4118.         $mailBody $mailBody '<br><br> <a href="https://mantevenues.mante.solutions/venues/adminconfirmres/n/' $id '">"NO"</a> deseo confirmar la reserva.';
  4119.         $mailBody $mailBody '<br><br><br> <a href="https://inout.mante.solutions">"PARA QUE LOS ENLACES FUNCIONEN, ANTES DEBES INCIAR SESION"</a><br><br>';
  4120.         // Se envia el correo pidiendo la confirmacion
  4121.         $this->sendMailLot($mailAddressFrom$mailArrayTo$mailSubject$mailBody);
  4122.         //Alerta a Gabriela, Agente modificador del expediente y Mariale
  4123.         if (!empty($dataGP)) {
  4124.             $mailArrayTo = [];
  4125.             $agentAlert $em->getRepository(User::class)->findOneById($reserva->getUpdatedBy());
  4126.             if (!empty($agentAlert) and ($agentAlert->getStatus() == 1)) {
  4127.                 $mailArrayTo[$agentAlert->getEmail()] = $agentAlert->getEmail();
  4128.             }
  4129.             $agentAlert $em->getRepository(User::class)->findOneById(82);         // Gabriela Bracho
  4130.             if (!empty($agentAlert) and ($agentAlert->getStatus() == 1)) {
  4131.                 $mailArrayTo[$agentAlert->getEmail()] = $agentAlert->getEmail();
  4132.             }
  4133.             $agentAlert $em->getRepository(User::class)->findOneById(129);         // Maria Alejandra Martinez
  4134.             if (!empty($agentAlert) and ($agentAlert->getStatus() == 1)) {
  4135.                 $mailArrayTo[$agentAlert->getEmail()] = $agentAlert->getEmail();
  4136.             }
  4137.             $this->sendMailLot($mailAddressFrom$mailArrayTo$mailSubject$mailAlert['mailBody']);
  4138.         }
  4139.         if (!empty($mensajePopup)) {
  4140.             $this->addFlash('mensajereservationerror'$mensajePopup);
  4141.         }
  4142.         return $this->redirectToRoute('reservations_venues_edit_simple', array('id' => $id'token' => null));
  4143.     }
  4144.     /**
  4145.      * @Route("/adminconfirmres/{op}/{id}", name="reservations_venues_admin_confirm_res")
  4146.      * Confirmacion del administrador, positiva o negativa (op) de la reserva (id)
  4147.      */
  4148.     public function adminConfirmationReservationAction($op$idEntityManagerInterface $emRequest $request)
  4149.     {
  4150.         /* Obtengo usuario logueado */
  4151.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  4152.         $user_id $user_logueado->getId();
  4153.         $reserva $em->getRepository(Reservation::class)->findOneById($id);
  4154.         $mailArrayTo = array();
  4155.         $mailArrayTo['salvador@avexpress.tv'] = 'salvador@avexpress.tv';
  4156.         $mailArrayTo['rafael.guerrero@inout-travel.com'] = 'rafael.guerrero@inout-travel.com';
  4157.         $mailArrayTo['comercial@venues.es'] = 'comercial@venues.es';
  4158.         $mailArrayTo['comercial2@venues.es'] = 'comercial2@venues.es';
  4159.         //        $mailArrayTo['gustavo.ayala@develup.solutions'] = 'gustavo.ayala@develup.solutions';
  4160.         $agente $em->getRepository(User::class)->findOneById($user_id);
  4161.         $mailAddressFrom $agente->getEmail();
  4162.         $mailSubject 'Confirmación de reserva: ' $reserva->getTitle();
  4163.         switch ($op) {
  4164.             case 'y':
  4165.                 // Se va a Confirmar la reserva
  4166.                 $reserva->setStatus('Confirmed');
  4167.                 $reserva->setUpdatedBy($user_id);
  4168.                 $reserva->setUpdatedAt(new DateTime('now'));
  4169.                 $em->persist($reserva);
  4170.                 $em->flush();
  4171.                 $mailBody 'Estimado agente,' .
  4172.                     '<br><br>' $agente->getName() . ' ' $agente->getLastName() . ' ha confirmado la reserva:' .
  4173.                     '<br><br>' $reserva->getTitle() . ' con ID: ' $reserva->getId() .
  4174.                     '<br>Este evento incia el día ' $reserva->getDateStart()->format('d/m/Y H:i') . ' y finaliza el día ' $reserva->getDateEnd()->format('d/m/Y H:i') . '<br><br><br>';
  4175.                 //                $mailBody = $mailBody .'<br><br> <a href="http://127.0.0.1:8000/venues/editsimple/'.$id.'">Ir a la reserva</a>';
  4176.                 $mailBody $mailBody '<br><br> <a href="https://mantevenues.mante.solutions/venues/editsimple/' $id '">Ir a la reserva</a>';
  4177.                 break;
  4178.             case 'n':
  4179.                 // No se va a Confirmar la reserva - Pasa a un editar (para ajustar fechas etc)
  4180.                 $reserva->setStatus('Cotizado');
  4181.                 $reserva->setUpdatedBy($user_id);
  4182.                 $reserva->setUpdatedAt(new DateTime('now'));
  4183.                 $em->persist($reserva);
  4184.                 $em->flush();
  4185.                 $mailBody 'Estimado agente,' .
  4186.                     '<br><br>' $agente->getName() . ' ' $agente->getLastName() . ' ha rechazado la confirmación de la reserva:' .
  4187.                     '<br><br>' $reserva->getTitle() . ' con ID: ' $reserva->getId() .
  4188.                     '<br>Este evento inciaba el día ' $reserva->getDateStart()->format('d/m/Y H:i') . ' y finalizaba el día ' $reserva->getDateEnd()->format('d/m/Y H:i') . '<br><br><br>' .
  4189.                     '<br>POR FAVOR, PONGANSE EN CONTACTO PARA DETEMINAR UN NUEVO HORARIO<br><br><br>';
  4190.                 //                $mailBody = $mailBody .'<br><br> <a href="http://127.0.0.1:8000/venues/editsimple/'.$id.'">Ir a la reserva</a>';
  4191.                 $mailBody $mailBody '<br><br> <a href="http://inout.mante.solutions/venues/editsimple/' $id '">Ir a la reserva</a>';
  4192.                 break;
  4193.             default:
  4194.                 break;
  4195.         }
  4196.         // Enviar correo al agente (envia a las 2 agentes? enviar al creador de la reserva?)
  4197.         $this->sendMailLot($mailAddressFrom$mailArrayTo$mailSubject$mailBody);
  4198.         echo 'Ha finalizado correctamente su sesión. Puede cerrar la aplicación';
  4199.         exit();
  4200.     }
  4201.     /**
  4202.      * @Route("/viewcontract/{id}", name="reservations_venues_view_contract")
  4203.      * Vista del contrato de la reserva (id)
  4204.      */
  4205.     public function viewContractReservationAction($idEntityManagerInterface $emRequest $request)
  4206.     {
  4207.         // El cliente es obligatorio y no puede ser null
  4208.         // El contacto es obligatorio y no puede ser null, será el representante del cliente en el contrato
  4209.         // En el expediente solo deben estar las salas definitivas para el contrato
  4210.         $reserva $em->getRepository(Reservation::class)->findOneById($id);
  4211.         $contractOrigin $reserva->getContract();
  4212.         $dateStart $reserva->getDateStart();
  4213.         $dateEnd $reserva->getDateEnd();
  4214.         //Buscamos el representante
  4215.         $representante $reserva->getClientContact();
  4216.         $representante $em->getRepository(ClientContact::class)->findOneById($representante);
  4217.         $representanteCorreo $representante->getEmail();
  4218.         $representante $representante->getName() . ' ' $representante->getLastName();
  4219.         //Buscamos el cliente
  4220.         $client $reserva->getClient();
  4221.         $client $em->getRepository(Client::class)->findOneById($client);
  4222.         // La fecha de inicio y fin del evento incluyen montaje y desmontaje
  4223.         // Determinamos el primer y ultimo dia del evento y lo modificamos en la reserva sin tocar la base de datos
  4224.         $allOnlySalasReservadas $em->getRepository(ReservationLoungeSimple::class)->findBy(array('idReservation' => $id'type' => null));
  4225.         if (!empty($allOnlySalasReservadas)) {
  4226.             $reserva->setDateStart($allOnlySalasReservadas[0]->getDateStart());
  4227.             $reserva->setDateEnd($allOnlySalasReservadas[0]->getDateEnd());
  4228.             foreach ($allOnlySalasReservadas as $item) {
  4229.                 if ($item->getDateStart() < $reserva->getDateStart()) {
  4230.                     $reserva->setDateStart($item->getDateStart());
  4231.                 }
  4232.                 if ($item->getDateEnd() > $reserva->getDateEnd()) {
  4233.                     $reserva->setDateEnd($item->getDateEnd());
  4234.                 }
  4235.             }
  4236.         }
  4237.         //Generamos la fecha actual
  4238.         $fechaActual = new DateTime('now');
  4239.         $mesActual $fechaActual->format('m');
  4240.         switch ($mesActual) {
  4241.             case '01':
  4242.                 $mesActual 'enero';
  4243.                 break;
  4244.             case '02':
  4245.                 $mesActual 'febrero';
  4246.                 break;
  4247.             case '03':
  4248.                 $mesActual 'marzo';
  4249.                 break;
  4250.             case '04':
  4251.                 $mesActual 'abril';
  4252.                 break;
  4253.             case '05':
  4254.                 $mesActual 'mayo';
  4255.                 break;
  4256.             case '06':
  4257.                 $mesActual 'jumio';
  4258.                 break;
  4259.             case '07':
  4260.                 $mesActual 'julio';
  4261.                 break;
  4262.             case '08':
  4263.                 $mesActual 'agosto';
  4264.                 break;
  4265.             case '09':
  4266.                 $mesActual 'septiembre';
  4267.                 break;
  4268.             case '10':
  4269.                 $mesActual 'octubre';
  4270.                 break;
  4271.             case '11':
  4272.                 $mesActual 'noviembre';
  4273.                 break;
  4274.             case '12':
  4275.                 $mesActual 'diciembre';
  4276.                 break;
  4277.             default:
  4278.                 $mesActual '';
  4279.                 break;
  4280.         }
  4281.         $contract00 '';
  4282.         $contract01 '';
  4283.         $contract02 '';
  4284.         $contract03 '';
  4285.         $contract04 '';
  4286.         $contract05 '';
  4287.         //Generamos la fecha de inicio
  4288.         $fechaInicio $reserva->getDateStart()->format('m');
  4289.         switch ($fechaInicio) {
  4290.             case '01':
  4291.                 $mesInicio 'enero';
  4292.                 break;
  4293.             case '02':
  4294.                 $mesInicio 'febrero';
  4295.                 break;
  4296.             case '03':
  4297.                 $mesInicio 'marzo';
  4298.                 break;
  4299.             case '04':
  4300.                 $mesInicio 'abril';
  4301.                 break;
  4302.             case '05':
  4303.                 $mesInicio 'mayo';
  4304.                 break;
  4305.             case '06':
  4306.                 $mesInicio 'jumio';
  4307.                 break;
  4308.             case '07':
  4309.                 $mesInicio 'julio';
  4310.                 break;
  4311.             case '08':
  4312.                 $mesInicio 'agosto';
  4313.                 break;
  4314.             case '09':
  4315.                 $mesInicio 'septiembre';
  4316.                 break;
  4317.             case '10':
  4318.                 $mesInicio 'octubre';
  4319.                 break;
  4320.             case '11':
  4321.                 $mesInicio 'noviembre';
  4322.                 break;
  4323.             case '12':
  4324.                 $mesInicio 'diciembre';
  4325.                 break;
  4326.             default:
  4327.                 $mesInicio '';
  4328.                 break;
  4329.         }
  4330.         $fechaInicio $reserva->getDateStart()->format('d') . ' de ' $mesInicio ' del ' $reserva->getDateStart()->format('Y') . ' ';
  4331.         $contract06 '';
  4332.         $horaInicio $reserva->getDateStart()->format('H:i') . ' ';
  4333.         $contract07 '';
  4334.         //Generamos la fecha de fin
  4335.         $fechaFin $reserva->getDateEnd()->format('m');
  4336.         switch ($fechaFin) {
  4337.             case '01':
  4338.                 $mesFin 'enero';
  4339.                 break;
  4340.             case '02':
  4341.                 $mesFin 'febrero';
  4342.                 break;
  4343.             case '03':
  4344.                 $mesFin 'marzo';
  4345.                 break;
  4346.             case '04':
  4347.                 $mesFin 'abril';
  4348.                 break;
  4349.             case '05':
  4350.                 $mesFin 'mayo';
  4351.                 break;
  4352.             case '06':
  4353.                 $mesFin 'jumio';
  4354.                 break;
  4355.             case '07':
  4356.                 $mesFin 'julio';
  4357.                 break;
  4358.             case '08':
  4359.                 $mesFin 'agosto';
  4360.                 break;
  4361.             case '09':
  4362.                 $mesFin 'septiembre';
  4363.                 break;
  4364.             case '10':
  4365.                 $mesFin 'octubre';
  4366.                 break;
  4367.             case '11':
  4368.                 $mesFin 'noviembre';
  4369.                 break;
  4370.             case '12':
  4371.                 $mesFin 'diciembre';
  4372.                 break;
  4373.             default:
  4374.                 $mesFin '';
  4375.                 break;
  4376.         }
  4377.         if ($reserva->getDateStart()->format('ymd') != $reserva->getDateEnd()->format('ymd')) {
  4378.             $fechaFin ' el día ' $reserva->getDateEnd()->format('d') . ' de ' $mesFin ' del ' $reserva->getDateEnd()->format('Y') . ' a las ' $reserva->getDateEnd()->format('H:i') . ' ';
  4379.             $contractAlfa '';
  4380.             $contract08 $fechaFin $contractAlfa;
  4381.         } else {
  4382.             // El evento empieza y termina el mismo dia
  4383.             $horaFin ' las ' $reserva->getDateEnd()->format('H:i') . ' ';
  4384.             $contractAlfa '';
  4385.             $contract08 $horaFin $contractAlfa;
  4386.         }
  4387.         // Buscamos las salas
  4388.         $allSalasReservadas $em->getRepository(ReservationLoungeSimple::class)->findByIdReservation($id);
  4389.         $arrayTextoSalas = array();
  4390.         foreach ($allSalasReservadas as $item) {
  4391.             $arrayTextoSalas[$item->getIdLounge()] = $item->getIdLounge();
  4392.         }
  4393.         $textoSalas '';
  4394.         $logAllGreen false;       // Si se asigna el edificio completo no hay que verificar mas salas
  4395.         foreach ($arrayTextoSalas as $item) {
  4396.             $sala $em->getRepository(ReservationLoungeDetails::class)->findOneById($item);
  4397.             switch ($sala->getId()) {
  4398.                 case '1':
  4399.                     $textoSalas '<b>TODO EL EDIFICIO EN EXCLUSIVA</b>';
  4400.                     $logAllGreen true;
  4401.                     break;
  4402.                 case '16':
  4403.                     if (empty($textoSalas)) {
  4404.                         $textoSalas '<b>Sala Plenaria La Imprenta, Sala Invernadero</b>';
  4405.                     } else {
  4406.                         $textoSalas $textoSalas '<b>Sala Plenaria La Imprenta, Sala Invernadero</b>';
  4407.                     }
  4408.                     break;
  4409.                 case '17':
  4410.                     if (empty($textoSalas)) {
  4411.                         $textoSalas '<b>Sala Plenaria La Imprenta, Sala Invernadero, Sala Escenario</b>';
  4412.                     } else {
  4413.                         $textoSalas $textoSalas '<b>Sala Plenaria La Imprenta, Sala Invernadero, Sala Escenario</b>';
  4414.                     }
  4415.                     break;
  4416.                 default:
  4417.                     if (!$logAllGreen) {
  4418.                         if (empty($textoSalas)) {
  4419.                             $textoSalas '<b>' $sala->getName() . '</b>';
  4420.                         } else {
  4421.                             $textoSalas $textoSalas '<b>, ' $sala->getName() . '</b>';
  4422.                         }
  4423.                     }
  4424.                     break;
  4425.             }
  4426.         }
  4427.         $contract09 '';
  4428.         $cierre $reserva->getDateEnd()->format('H:i') . ' horas del día ' $reserva->getDateEnd()->format('d') . ' de ' $mesFin ' del ' $reserva->getDateEnd()->format('Y');
  4429.         $contract10 '';
  4430.         $pax $reserva->getPax();
  4431.         $contract11 '';
  4432.         $contract12 '</span></span><b><span lang="ES-TRAD" style="font-size:12.0pt"><o:p></o:p></span></b></font></p><p class="MsoListParagraph"><!--[if !supportLists]--><font face="Arial"><span lang="ES-TRAD" style="font-size:12.0pt">-<span style="font-variant-numeric: normal; font-variant-east-asian: normal; font-stretch: normal; font-size: 7pt; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><!--[endif]--><span class="Hyperlink1"><span lang="ES-TRAD" style="font-size:12.0pt">Salas a utilizar: </span></span><span class="Ninguno"><b><u><span lang="ES-TRAD">';
  4433.         $contract13 '</span></u></b></span><b><span lang="ES-TRAD" style="font-size:12.0pt"><o:p></o:p></span></b></font></p>';
  4434.         // Se asume que los montajes seran como maximo de dos dias
  4435.         $montaje = array();
  4436.         $mesInicioMontaje '';
  4437.         $mesFinMontaje '';
  4438.         foreach ($allSalasReservadas as $item) {
  4439.             if ($item->getType() == 'Montaje') {
  4440.                 if (empty($montaje)) {
  4441.                     $montaje[0] = $item->getDateStart();
  4442.                     switch ($item->getDateStart()->format('m')) {
  4443.                         case '01':
  4444.                             $mesInicioMontaje 'enero';
  4445.                             break;
  4446.                         case '02':
  4447.                             $mesInicioMontaje 'febrero';
  4448.                             break;
  4449.                         case '03':
  4450.                             $mesInicioMontaje 'marzo';
  4451.                             break;
  4452.                         case '04':
  4453.                             $mesInicioMontaje 'abril';
  4454.                             break;
  4455.                         case '05':
  4456.                             $mesInicioMontaje 'mayo';
  4457.                             break;
  4458.                         case '06':
  4459.                             $mesInicioMontaje 'jumio';
  4460.                             break;
  4461.                         case '07':
  4462.                             $mesInicioMontaje 'julio';
  4463.                             break;
  4464.                         case '08':
  4465.                             $mesInicioMontaje 'agosto';
  4466.                             break;
  4467.                         case '09':
  4468.                             $mesInicioMontaje 'septiembre';
  4469.                             break;
  4470.                         case '10':
  4471.                             $mesInicioMontaje 'octubre';
  4472.                             break;
  4473.                         case '11':
  4474.                             $mesInicioMontaje 'noviembre';
  4475.                             break;
  4476.                         case '12':
  4477.                             $mesInicioMontaje 'diciembre';
  4478.                             break;
  4479.                         default:
  4480.                             $mesInicioMontaje '';
  4481.                             break;
  4482.                     }
  4483.                 } else {
  4484.                     $montaje[1] = $item->getDateEnd();
  4485.                     switch ($item->getDateEnd()->format('m')) {
  4486.                         case '01':
  4487.                             $mesFinMontaje 'enero';
  4488.                             break;
  4489.                         case '02':
  4490.                             $mesFinMontaje 'febrero';
  4491.                             break;
  4492.                         case '03':
  4493.                             $mesFinMontaje 'marzo';
  4494.                             break;
  4495.                         case '04':
  4496.                             $mesFinMontaje 'abril';
  4497.                             break;
  4498.                         case '05':
  4499.                             $mesFinMontaje 'mayo';
  4500.                             break;
  4501.                         case '06':
  4502.                             $mesFinMontaje 'jumio';
  4503.                             break;
  4504.                         case '07':
  4505.                             $mesFinMontaje 'julio';
  4506.                             break;
  4507.                         case '08':
  4508.                             $mesFinMontaje 'agosto';
  4509.                             break;
  4510.                         case '09':
  4511.                             $mesFinMontaje 'septiembre';
  4512.                             break;
  4513.                         case '10':
  4514.                             $mesFinMontaje 'octubre';
  4515.                             break;
  4516.                         case '11':
  4517.                             $mesFinMontaje 'noviembre';
  4518.                             break;
  4519.                         case '12':
  4520.                             $mesFinMontaje 'diciembre';
  4521.                             break;
  4522.                         default:
  4523.                             $mesFinMontaje '';
  4524.                             break;
  4525.                     }
  4526.                 }
  4527.             }
  4528.         }
  4529.         switch (sizeof($montaje)) {
  4530.             case 1:
  4531.                 $textoMontaje $montaje[0]->format('d') . ' de ' $mesInicioMontaje ' del ' $montaje[0]->format('Y');
  4532.                 break;
  4533.             case 2:
  4534.                 if ($mesInicioMontaje == $mesFinMontaje) {
  4535.                     // Dos dias de montaje en el mismo mes
  4536.                     $textoMontaje $montaje[0]->format('d') . ' y ' $montaje[1]->format('d') . ' de ' $mesInicioMontaje ' del ' $montaje[0]->format('Y');
  4537.                 } else {
  4538.                     // Dos dias de montaje con diferentes meses, ejemplo 31/03 y 01/04
  4539.                     $textoMontaje $montaje[0]->format('d') . ' de ' $mesInicioMontaje ' y ' $montaje[1]->format('d') . ' de ' $mesFinMontaje ' del ' $montaje[0]->format('Y');
  4540.                 }
  4541.                 break;
  4542.             default:
  4543.                 $textoMontaje null;
  4544.                 break;
  4545.         }
  4546.         if (!empty($textoMontaje)) {
  4547.             $textoMontaje '<p class="MsoListParagraph"><!--[if !supportLists]--><font face="Arial"><span lang="ES-TRAD" style="font-size:12.0pt">-<span style="font-variant-numeric: normal; font-variant-east-asian: normal; font-stretch: normal; font-size: 7pt; line-height: normal;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span></span><!--[endif]--><span class="Hyperlink1"><span lang="ES-TRAD" style="font-size:12.0pt">MONTAJE: ' $textoMontaje '</span></span><b><span lang="ES-TRAD" style="font-size:12.0pt"><o:p></o:p></span></b></font></p>';
  4548.         }
  4549.         // Se asume que los desmontajes seran como maximo de dos dias
  4550.         $desmontaje = array();
  4551.         $mesInicioDesmontaje '';
  4552.         $mesFinDesmontaje '';
  4553.         foreach ($allSalasReservadas as $item) {
  4554.             if ($item->getType() == 'Desmontaje') {
  4555.                 if (empty($desmontaje)) {
  4556.                     $desmontaje[0] = $item->getDateStart();
  4557.                     switch ($item->getDateStart()->format('m')) {
  4558.                         case '01':
  4559.                             $mesInicioDesmontaje 'enero';
  4560.                             break;
  4561.                         case '02':
  4562.                             $mesInicioDesmontaje 'febrero';
  4563.                             break;
  4564.                         case '03':
  4565.                             $mesInicioDesmontaje 'marzo';
  4566.                             break;
  4567.                         case '04':
  4568.                             $mesInicioDesmontaje 'abril';
  4569.                             break;
  4570.                         case '05':
  4571.                             $mesInicioDesmontaje 'mayo';
  4572.                             break;
  4573.                         case '06':
  4574.                             $mesInicioDesmontaje 'jumio';
  4575.                             break;
  4576.                         case '07':
  4577.                             $mesInicioDesmontaje 'julio';
  4578.                             break;
  4579.                         case '08':
  4580.                             $mesInicioDesmontaje 'agosto';
  4581.                             break;
  4582.                         case '09':
  4583.                             $mesInicioDesmontaje 'septiembre';
  4584.                             break;
  4585.                         case '10':
  4586.                             $mesInicioDesmontaje 'octubre';
  4587.                             break;
  4588.                         case '11':
  4589.                             $mesInicioDesmontaje 'noviembre';
  4590.                             break;
  4591.                         case '12':
  4592.                             $mesInicioDesmontaje 'diciembre';
  4593.                             break;
  4594.                         default:
  4595.                             $mesInicioDesmontaje '';
  4596.                             break;
  4597.                     }
  4598.                 } else {
  4599.                     $desmontaje[1] = $item->getDateEnd();
  4600.                     switch ($item->getDateEnd()->format('m')) {
  4601.                         case '01':
  4602.                             $mesFinDesmontaje 'enero';
  4603.                             break;
  4604.                         case '02':
  4605.                             $mesFinDesmontaje 'febrero';
  4606.                             break;
  4607.                         case '03':
  4608.                             $mesFinDesmontaje 'marzo';
  4609.                             break;
  4610.                         case '04':
  4611.                             $mesFinDesmontaje 'abril';
  4612.                             break;
  4613.                         case '05':
  4614.                             $mesFinDesmontaje 'mayo';
  4615.                             break;
  4616.                         case '06':
  4617.                             $mesFinDesmontaje 'jumio';
  4618.                             break;
  4619.                         case '07':
  4620.                             $mesFinDesmontaje 'julio';
  4621.                             break;
  4622.                         case '08':
  4623.                             $mesFinDesmontaje 'agosto';
  4624.                             break;
  4625.                         case '09':
  4626.                             $mesFinDesmontaje 'septiembre';
  4627.                             break;
  4628.                         case '10':
  4629.                             $mesFinDesmontaje 'octubre';
  4630.                             break;
  4631.                         case '11':
  4632.                             $mesFinDesmontaje 'noviembre';
  4633.                             break;
  4634.                         case '12':
  4635.                             $mesFinDesmontaje 'diciembre';
  4636.                             break;
  4637.                         default:
  4638.                             $mesFinDesmontaje '';
  4639.                             break;
  4640.                     }
  4641.                 }
  4642.             }
  4643.         }
  4644.         switch (sizeof($desmontaje)) {
  4645.             case 1:
  4646.                 $textoDesmontaje $desmontaje[0]->format('d') . ' de ' $mesInicioDesmontaje ' del ' $desmontaje[0]->format('Y');
  4647.                 break;
  4648.             case 2:
  4649.                 if ($mesInicioDesmontaje == $mesFinDesmontaje) {
  4650.                     // Dos dias de montaje en el mismo mes
  4651.                     $textoDesmontaje $desmontaje[0]->format('d') . ' y ' $desmontaje[1]->format('d') . ' de ' $mesInicioDesmontaje ' del ' $desmontaje[0]->format('Y');
  4652.                 } else {
  4653.                     // Dos dias de montaje con diferentes meses, ejemplo 31/03 y 01/04
  4654.                     $textoDesmontaje $desmontaje[0]->format('d') . ' de ' $mesInicioDesmontaje ' y ' $desmontaje[1]->format('d') . ' de ' $mesFinDesmontaje ' del ' $desmontaje[0]->format('Y');
  4655.                 }
  4656.                 break;
  4657.             default:
  4658.                 $textoDesmontaje 'Mismo día al finalizar el evento desde las 17 horas hasta las 00:00 horas';
  4659.                 break;
  4660.         }
  4661.         if (!empty($textoDesmontaje)) {
  4662.             $textoDesmontaje '';
  4663.         }
  4664.         $contract14 '';
  4665.         if (empty($mesInicioMontaje)) {
  4666.             switch ($dateStart->format('m')) {
  4667.                 case '01':
  4668.                     $mesInicioMontajeZ 'enero';
  4669.                     break;
  4670.                 case '02':
  4671.                     $mesInicioMontajeZ 'febrero';
  4672.                     break;
  4673.                 case '03':
  4674.                     $mesInicioMontajeZ 'marzo';
  4675.                     break;
  4676.                 case '04':
  4677.                     $mesInicioMontajeZ 'abril';
  4678.                     break;
  4679.                 case '05':
  4680.                     $mesInicioMontajeZ 'mayo';
  4681.                     break;
  4682.                 case '06':
  4683.                     $mesInicioMontajeZ 'jumio';
  4684.                     break;
  4685.                 case '07':
  4686.                     $mesInicioMontajeZ 'julio';
  4687.                     break;
  4688.                 case '08':
  4689.                     $mesInicioMontajeZ 'agosto';
  4690.                     break;
  4691.                 case '09':
  4692.                     $mesInicioMontajeZ 'septiembre';
  4693.                     break;
  4694.                 case '10':
  4695.                     $mesInicioMontajeZ 'octubre';
  4696.                     break;
  4697.                 case '11':
  4698.                     $mesInicioMontajeZ 'noviembre';
  4699.                     break;
  4700.                 case '12':
  4701.                     $mesInicioMontajeZ 'diciembre';
  4702.                     break;
  4703.                 default:
  4704.                     $mesInicioMontajeZ '';
  4705.                     break;
  4706.             }
  4707.             $tiempoCedido $dateStart->format('H:i') . ' horas del día ' $dateStart->format('d') . ' de ' $mesInicioMontajeZ ' del ' $dateStart->format('Y') . ' hasta las ';
  4708.         } else {
  4709.             $tiempoCedido $dateStart->format('H:i') . ' horas del día ' $dateStart->format('d') . ' de ' $mesInicioMontaje ' del ' $dateStart->format('Y') . ' hasta las ';
  4710.         }
  4711.         if (empty($mesInicioDesmontaje)) {
  4712.             switch ($dateStart->format('m')) {
  4713.                 case '01':
  4714.                     $mesInicioDesmontajeZ 'enero';
  4715.                     break;
  4716.                 case '02':
  4717.                     $mesInicioDesmontajeZ 'febrero';
  4718.                     break;
  4719.                 case '03':
  4720.                     $mesInicioDesmontajeZ 'marzo';
  4721.                     break;
  4722.                 case '04':
  4723.                     $mesInicioDesmontajeZ 'abril';
  4724.                     break;
  4725.                 case '05':
  4726.                     $mesInicioDesmontajeZ 'mayo';
  4727.                     break;
  4728.                 case '06':
  4729.                     $mesInicioDesmontajeZ 'jumio';
  4730.                     break;
  4731.                 case '07':
  4732.                     $mesInicioDesmontajeZ 'julio';
  4733.                     break;
  4734.                 case '08':
  4735.                     $mesInicioDesmontajeZ 'agosto';
  4736.                     break;
  4737.                 case '09':
  4738.                     $mesInicioDesmontajeZ 'septiembre';
  4739.                     break;
  4740.                 case '10':
  4741.                     $mesInicioDesmontajeZ 'octubre';
  4742.                     break;
  4743.                 case '11':
  4744.                     $mesInicioDesmontajeZ 'noviembre';
  4745.                     break;
  4746.                 case '12':
  4747.                     $mesInicioDesmontajeZ 'diciembre';
  4748.                     break;
  4749.                 default:
  4750.                     $mesInicioDesmontajeZ '';
  4751.                     break;
  4752.             }
  4753.             $tiempoCedido $tiempoCedido $dateEnd->format('H:i') . ' horas del día ' $dateEnd->format('d') . ' de ' $mesInicioDesmontajeZ ' del ' $dateEnd->format('Y');
  4754.         } else {
  4755.             $tiempoCedido $tiempoCedido $dateEnd->format('H:i') . ' horas del día ' $dateEnd->format('d') . ' de ' $mesInicioDesmontaje ' del ' $dateEnd->format('Y');
  4756.         }
  4757.         $contract15 '';
  4758.         // 5. Normas de Seguridad
  4759.         $contract16 '';
  4760.         // 6. Coste, plazo y forma de pago
  4761.         $data $this->CalculosTotalesEditSimple($reserva->getId());
  4762.         $contract17 '';
  4763.         // 8. Reserva
  4764.         $contract18 '';
  4765.         // 9. Confidencialidad y publicidad
  4766.         // 11. Derechos de imagen y propiedad intelectual
  4767.         // 12. Prevencion de la corrupcion
  4768.         // 13. Proteccion de datos personales
  4769.         // 14. Responsabilidad
  4770.         $contract19 '';
  4771.         // 15. Comunicaciones
  4772.         $contract20 '';
  4773.         // 16. Cesión
  4774.         // 17. Nulidad Parcial
  4775.         // 18. Fuerza Mayor
  4776.         // 19. Acuerdo Completo
  4777.         $contract21 '';
  4778.         // Normas de uso
  4779.         $contract22 '';
  4780.         // Logotipo de Venues centrado
  4781.         $contract23 '
  4782.         <div class="col-md-4 col-xs-6" ></div><div class="col-md-4 col-xs-6" ><p class="MsoNormal" align="right" style="margin-bottom: background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;"><b><span lang="EN-US" style="font-size: 9pt;"><font face="Arial"><o:p><br></o:p></font></span></b></p><p class="MsoNormal" align="right" style="margin-bottom: 7.5pt; text-align: right; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;"><b><span lang="EN-US" style="font-size: 9pt;"><font face="Arial"><o:p><br></o:p></font></span></b></p><p class="MsoNormal" align="right" style="margin-bottom: 7.5pt; text-align: right; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAVYAAAEJCAYAAADPdw+hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAAFxEAABcRAcom8z8AACVdSURBVHhe7d0JmFxVmTfwBBAQUWTfZJFdliTdde+t6iw2MpCJyA4BEhgFSQJ8GCCEJN3p7jp3qeqq3tNhF2ZAGRyfOAoyOmFkWAQZB0FxPkb8RPlAVhFFw2IEMtT839tvNV3Vt7qW7oRO5/97nvN03XPPPXc7973nLlU9iYiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIho3Gs2dVPcwL40CJx56fS03TWbiIhqYXzrXD/lvN+eTeQyHQ0517fvRfZWA2OJiKhqxrNezHY25BBcc0E6npMAizxfRxMRUTW8wElmOhveloCKz2GSwIpe6zpjErtoMSIiqsSiRbGPGN/+z86eGYNBVZL0XDMdiXfdwLlZixIRUSUQVBcEaWf90N5qPnV2N+SM7/yHMUduq8WJiKgc9Ex7evqmDwuqklLt8RyC7uvGWOdqcSIiKsd49rXdvdGBVZIEXde3rtHiREQ0kjbPakxn4i9JzzQqqErSoNutkxAR0UjcwLm4d1XhQ6vi1NUzXV67+uqaNXO31smIiKgUN4hfKIEzKqDmU9ibTTmvGeMcp5MREW2ZjInN7O2dfl5ra+xEzRrG+PELygVWSZ3d03PJZOwinWwYz7PO7L921nktLfUHaxYR0cSCoOqkM/HXVq2emQtSzgZj6i/XUQWMZ19SSWDtQmB1XScysLq+vaKjqyG3+tpZuXQ28TjmfYSOIiKaGBDY9vcC+yn5eqrrO7l0JpHLdiTeRwBcqkUGIbA2SVCMCqZDkwRfuW2gk4X6Fx+yHcZlM5iP3C6QefX2z8wlXesKLUJENDGk0/Epmc5Ezk998KRfgmtHZ2KD68eXZrOxnbToJATgVRKA8+VKpYHA+kGPtc2zG4xvPyj1Dn2jIAywnv371tb4oVqUiGjz5/v2UfJ11KGBNR/0kN53A/txE8SO9X3r/CAdf1fKDi0XlTIdCQRM604PARX1L/BT9nr5LYHib2vJPCXf952pujhERJu/UoE1H/gkwEpPU1JUmVJJgmh+uqivv0qS+sIy6DXr4hARbf6MsY4O0tGBNZ8GAm/0uJFSuek04L5lTAMfYBHRxCE91nKBdWMluV+b9GNdxjRur4tDRLT5W7z4kO3cwO7r6Cr/GtVYJ3nI1ebZp+uiEBFNHJ4XOyHTkXinlsv9WlP4epdnP93aWn+MLgYR0cQhv/qPIPf97r4Z4fulUYFwLJPcW0Ug/6v8tqsuAhHRxOP7Vl22I/Gr9mz591RHm+QWQNKzH21qt3fV2RMRTUxJ37pBgt7GvCUg762m2uPPyUMznS0R0cQlPUg/sB+SH1GJCoqjTXILQN6LTSZji3WWREQTX1PTzJ0RXP9zYwTXrh75n1jWXUuWJD6qsyMi2jLID7P4aeexTvnO/xg8zJI6unpm5PyU/aMuM2UPnQ0R0cRhzJE7GmOdEgTWfpo1jDHxA9PZxJj0XOW+bSYbf9CYun20+mFMKubIv37RQSKizUf426tZ5yeeb7+eao8/6Qb2t/xM9LukK1bE9m/PxB+t5BetSqVMR0OuPeM8vHJl/d5a7VCTXd9qbu9I3Ifl+W22I/GyG1iX5XKTJut4IqLxz/fjp/StnplLZ+LhS/ryS1Qd3YlXg7TjN2WO2VmLDWr1rfP9lPOWPHSKCpwjpfAXrVLO00vMkbtodYNSKdtyffuudCbxP9IrlrIShLOdiXdMwH/rQkSbEQTWE7NFP1YtQS38+b6U/ZDnWZ/XooNcz/6/CHgF01SSJGgnk9aPtZqQ3A5AL3khAvl7Ub98Ff6X15RzqhYnIhr/ogKrJHl3dSC4SqCzW93AuSzpOhdL8nznZenhFk9TLkkv1/WsF41vLWr16xdIneilPigBN5AecMT7st29M3JtKf5+ABFtRlKpxMldA//7PzJJgJVLc+k5SgDuwOdSv6daSZIAKvXIfymQoCnBO6qcJLkV4KftHxsz9UBdXCKi8S+dju+J4HlvJf+7aixTJd/mkmAu/1dLF5WIaPNhWusXdHRO/8toeqJjnSTQI/g+w6+6EtFmy/Xsr3V0b9pea6kk92KznQ3vG8+6WhePiGjzY4LYTNe335Z/Rx0V7DZV0p8QzCGo+rpoRESbL9+PnxGknfXy2lNU0NvYSf4ljLxLi6D6DSwOvxRARBNDW5t1pp9y3pMn8pvynqtc/subAug19zU1Df9iAhHRZq3VxE50A/tJeTVqpNehilP4nmpgP+UGzlPVfDNLXufKdiY2+O22Z0zjNroYREQTi3mgcRs35QTpbOLP8qMp5QKl/GJVT9+MnOfbX/d85/rOMg/CpLxc9ssDs2xHw498316qsyYimtjkv6b6KeerXmC/JYEzf/+1+D1U6dlmOxK/DwLnONe3MmGQHTJeyueT3Gbo7Z+R8wP7x7j0TxsT20FnR0S05UDAnN2ejV+IHukvpAcrAVZ6sZLks/x2gPHszkVm7x2MqZ8dpOP/T3qtQ8uEX11Ny9da7duzXfEL5XdetXoioi2XMdZBnX3TG9q8+s8ZP/aP0pPFpf9zyD9Dfg3LSzlz2zznCy1B/cEIqL2pdPwtL7BecP1Yi9duy3TxpUunfEyrIyKioYw5YHvTae+FnudumjUJl/Ztru8Y+Tx37qStOzE+nZ62eziSiIiqh95pEr1YVweJiGi0hvZYiYhoDDCwEhGNMQZWIqIxxsBKRDTGJLAaz27VQSIiGi0E1hYT2L06SEREo+UFznIE1/uMadxRs4iIaDR8P77UDeyfy//S0iwiIhoNz3NWGt/6QxDUHaBZREQ0Gl7KOdX1nWX8XVUiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiKiLUX/4kO2S7r2pV5gr/JT8dWe76w2ntVrAuc4LVKzxYvnbOe61jnGm9Zkgvqri5Pr1y8zXmy58a1T5s6dtK1OVrPcpEmTUdcZMr+k1B0xz8iE8l6q7ivGNG6vVVXEBNOOx3xMZJ0lEtYZ5adN1yoqYozzCePVtbaYqcdqVsWa00fvKevX5tUnfX/aoZq9SRgz7XiD+UZtBy+ILXf9uiXGxGZq8TGXTsf3NEHsKtl2xkzZQ7OrZsxhu2E9rsTyrohal3JJ9nkQ1H1WqxuRl66flXTrAzeov3TRothHNHvUWoL6g3Fc+65v9fspZ7Uc78bYlyzuP2Q7LUJjwfj2Sa7v3OMHzhOp9nhu1eqZuf5rZoV/e/tn5LDh16XSzsMIjHemcXDqZFXJZmM7YUc+1J6N5yRlOxORyfXtvyKgP5Fuj/9QdnytB0EuN2my61lrZV7pEeZXnLp6GmR93zEmsYtWVRHPt67vWTU9l+mIrjcqXXPdzJwJ7HatoiJB0HBA0O5gPvGXg2DqbM2uSJsfj8n26O6dnvNS9umavUmE26evxPbpSoT52O5/9ALnMazfg2iPAU6wW+vkoxYE8WMzHQ3hvBBUbunvn1NTEDGmboqfdsJ2Urwesg4p7JsA40u1A9nnfmD3aXUj8gIru/ramTnPt19b2jXlY5pdk5tuin0E653MdjY8gO38bFfPdD3OZ4Z/5bj3Us7PcKzc53l1f2MaG7fRSalaK1fW740gdn1HV+K93n7swMBej8D2ItJzHyRH/v4O4zb09M2QBvOy7zu3NaMHoNVURAPrD6XBoc4/o7G8MDw5zyO9jPm9Lju6d9UMNELnmeUrpzpaTcXCwOrH/jU8YFPO29HzG54wX1mGJ1dkj99Jq6qIbMdubB9Z/qh6o1JX7/TnsS2WaBUVkcCKaTZIcHQD67/Ry9tfR5U1EFgTCKwzcm3epg6sDgKrnKSdV4ZvC+z3IPyMdua8joM/19OHAJSy7zdm6jTZl1pNTboQlJKudb/UK8EVHYl3m4x1kI6uiu9bh7uB/fRAOylaD6wb2u6GII0gVaId6D5v1upGNBBYZ+Vcz/n9aAJr0nXmoaPynAT2zm60G9/5A5b1tx8c42GS4/4vcsylMwkcL85jy0zdPloFVUouk7GjfyuNHY3kVTdwvuP7dZ+RM1tU8rz6OBrUd2XDy9kOwfXLWlVFBgKr/UCfBPBU/PKoeQxNuDQ5O51NPNDZ3YAebuKVFlNf1e2IgcBqfU/mhx7CdVHzKJUWIWk1FXM9+yY5cFta6g+OqrNUmjt3blW9MgmsxnPelROGHCTGq7zHa1KJejlhhdP5zmmavUngBHnDQLuxj4raDkMTAsESBKfHV62eJT3Ap006doRWUxPpZSJYIKBYT+Bk9EtZDvTeVuvoak2OWmZJra0SdK2fyzbGFc8hUWUkVbrPcbJpl94kgtwrtQZWCaqyPFIPetK/9jy7FSfjHaKWq6nJPgzb5TaU3yBXrOi9/mzFiqkHalVUjtxjSfrWOtnY6YzzU68tNkNHleUF9SlMa9aYuVXdBx0aWBGgL9XssnAwZORAQHD9hUnV12t2WYWB1enX7I0mH1hxEG/Us7wEVvQ2NiD9Dpekrw7M0/o/OnpE4yGwBmh7mjUiY47cET21tQMnYvubxjTUfF8UHYhvrL5uFoKps8oEU47r6E68irb4x6VL9xzV5XUxuXpA2/6ZbONUKrGvZtdstIHV9+PnpjPxDalMPIe2srbJTDlMR40ombT+DuvwG+lE4bh7THrpOopGkvTs28PL+s6GR6WHpdkbVWFgdS7T7LLCyzjPWhdeEvl2WrPLKuqxXqPZG80HgbXyS/NaSGANb2/g0jrp2tfJ+rXjwEkm7YVapKTx0WOt/CA1Qf1xcssj7GEaJ6HZVZHeGQLrumxXw4ue58ySPATsR7TX6oeFxghOcAdJr1i2sewnza7ZaAKrXH1iWf4g0yfd2CMrVsSqurXV3Fb3N15g/WUVeq64ur1NtqOOoig4AC+V+0yZbPyPCKpVPfwYjVoD602LcGnoW3eFPZfAdjW7rIkcWDu65AGb0y33yHHJ/Fh48AX2ujbPatRikTa7wGoSuwTtzh0D94QHgmK1kq7Vj+nfN779A82a5Kft+bKvsA0fM2bsHtKMp8CKY60vvM2Xjv9/WS7Nrorx6xfISRy91rc8Lx7XbIqCnfV9uX9iXPtHmrVJ1BpYhdwPlssSTO9pVlkTPrD69o0ybIy9l59y/ksOwKA9fsdIT9I3t8Aq0NtaIfvQBPYczapYc3ra7n4q/ius83tyn1Wzsc0at0FbehZt6h30Wq/W7FEbL4G1tTV+KLb3k+1ZaY/18zW7asYcua3chuldFW7/3rE8CU0o2qAewllog/FjX9TsTWKUgfX80QXWTXePdeXKqaO+tzaSfGB1fecGzcJ+nXYkTh7runrQQ0nFu5AV+RR9cwys2IfL+hBcagmsxnNSEpiwb36qWYNc175UenTp9vj3Uqn6vTV7VMZLYPU868qB48V5p7s7tptm18R49iXhMes7747FOk1ILYF1vJdyXpfXLcbyHcFK1BpY5YsFxo09KNOhodV0KwC9u2slz5hJW42UGhsnyRm5pld7PuixDjxFjao/n2Tby/KFE1YpKrDKU2Z5R7ELAVOCpus6GR1VYHMLrC0tR+2HfXdvVy+WN6juywPyBQg/7Tzc0TU91+rHhq2rMdP3Sfr2+lWrZ2Bb2DX36oYaN4E1sK6WkxGOt2eqfR+7GNrSvGxH4n/Q3t5nYC0h6TvBwAv/zkub+mZ0rYE1uwLTedab8vBKeiCaXVY+sIYPegL7WTewv4X1/peREgLj9/MPOKolr3R1InC4gfXvWM+7ourPJ+klIWDcUu27wCIqsIqmzDE7y3zlsi2VjiNYRASTze4ea92cHgRVOWGlTKyqd5kRLC+QoNnmWetxSbuXZg+Sb9ahZ5cMe3ae/W0cD6Pq2YnxEljl9oYG1r41a6p7na8Y1ulo49q/kXdzGVhLwEHdLfdX8bemwCrTIEDdjZ32MILjRZpdkaGB1fjxRZo9IpkfGtc/SeOXd1oxXPH9y3xgDRs5krzHWC5JUMJ6zdMqqiK9YulZyfyi6h6awl6lb7/YlKn+oUKpwCqaMjN3Rv3hu8borT3R1HTErjoqNB4CaxDUVXRwGmMfhnb6lOwTX75abRp31FFltbTUHYAT5E/lSy+4lL1c7hXqqAKeZzdksvH35EsT8lmzazaObgXkA+tSzapZKjV1X5ykfiKvbDGwltCashe0oyFhg79ay6WofE8dO/svN361Meen4h2aXZF8YJWD3gTykrLzqZbA2m9oMiZ+oO/HD5WUTNYvDdLOyz1hkLBfbDVTTtKqKpIPrDI/L2X/g7xfWi51dEzfZ0lP4qNaRVXkYZL0rNCo7ai6hyaZj+lq2KOW3sRIgVVc1mTviu32M7kywd9/Xrr0gwNyPARWXNIfW7zfg3DfWweFl+/Y9wiGLtrZ6+H90cB+aaWpr+pVqzYvdoLcFkEv6zUE5amaPYzcZvLRqxv4dpN15+LFo/uu/HgJrBJQ9dbZt3tqbM95Jqj7bJCyf4fjnbcCSpHLHRyQsuPf9lvtozS7YggIH8fOejXc2YFT1TuA+cAqPTYcLH/CWVC+Rvd8PmH4eVySve4HcQka72NHIgBIALEfQrAa8TWiKPnAKg0Ml+kVfTd7NPL3WJuba/sthUqVC6yi1cTO8nHpNtBzjX9DToiSL19p/bACa9ijH7hV8gr2v3ydcnDfI+8F7Ks3g5STk3WTfdY+8K7umpaW6n6k5tZbG7dHW/qBfGsLVx8Xa3ZJbW318a7uhhewnd6VE7tm12Tc9FgDu0neP8XfN0f78MoN4gvlIZ8cj0HgfFqzqRga2z2ys4xnrdGsio1FYJV7NRKA5KCX3mg+yXBX7wwJuuF4Sa5r3Sq/uKVVVKUosE64161GCqzCde0ueUugs3d6Lula4cMsk45P+bADq7zwP3S/D+z7mTn5nQW0jz/L6z24NO+WX3TSSatiMlMPRNvcMHC7xbkbaRmGl5dKxnOuxHyfzGKbyjJqNTUZL4EVJ5azM52JN7HuOFk4n9LsmmB9rpBjE9voF83N03bXbCqGwHWdvHCNRvRstWfosQiscnBh2ttxJrxwaArkr2t/qS1lnez51ho5S3qp2D+uwHRaRVW29MAqbx/I5bfsa/x9S95tNO2JQz68wOpcH/ZYfac5at/jkvwCuU0gy62T1ARXN7elMwP3uWV+0lbLJQmq4Ynct18odT+2EuMlsEpZ49r/Gh5Dnn2LZletBT3U9kz8F9KG9PXMUf0YzoQmv0uJwPaMfBsFl91VXSKPRWCVaY0fv0CzIxkz9Vg/Zb/f2dOQazLVv78otvTAKuSHNVJp5x9kG6D8D9F7me3jcvvDvMfaNYrfQi1HXs/Cvn4D6/gGeukXygOpShOm+SV6z++gjcp7wDUZL4FVJH17hbylIm/FJN1pV2h2xdCOd0ga6zth2wmc3zcb50gdRaXg7HNWOitPpxs2BGm7tZpfWEJAfWU0gVV31IivW8lDHePZV+GycT0a6Uu+X3+MjqoYA+uANm+ajZPUqwO9RftP2G/hfcwPK7BW+wWBarie9bWwfXnOI5pVMeNZKblNEaSdn6TTtV3yjqfAKg9h0SbvDN8CStlPV/OV4GXLDv940rVXyNsS2Gfv4PPCan+FbYskZyMcWGukoctZLUjFeyt5QBS023NwZv/zNdfNyrkpp0ezK1JNYM2Te17hQwjf/jV6sZ/U7IrkA6s0TASWmnshlfogsA48KNpYqg2sos2zrpRlk9+ImKiBVd4mQED7OdbznVbfOl+zKybHBPbhn+SHn9HeWjS7KuMpsApj5m7rBnbYucAx97abspqxniM+zPL9xDGpjPNtaS8duLIJqvglOgK5rEevsBMH2hv94S9HOe+iQbWl2p1mHHRflAcdJrCmm5TzRQTTZnzuRtl35dWUTDbxkufFT9CqKlJLYG316z6DZXxDDsg2E2vS7IrkA6tMi8Z1v5t2LsLfheWSSdmXhOtf5b02rNMNAwHPXoE6FkTVXZywbpe4QWxeucY+VC2BVRjPuVoCqzw8nIiBFdvd09em1s1dU/23CqVHhp6ZJ8uY9KwHKn3fdqjxFliFnOixbe6WE4bcc8XJ49/kGEf7W+y11X8OJ6E6z4udarx4kxdYSZR9Vn5iUQIryjCo1kr+nxV6rI/LfTfZibIDpGEgiD6D9Ip8lvyw54feTjYbvwo7q+qfcJPAanz7RwPfoIpfrtll+WnnNASEd7t6Gl73UvEzNbssDaz3yD0mue0hSV7hKZfkFS806PXysr1WVRH0rm/s658xUE+l88JBjHm9ZlJ1llZTljxwDP97gOfcrFkVc10rI78iLweY/LCNZm8SaEs3y9NlnERG9aPVUdraLDtIOb+WoIgTyFdq/bZR0G3tJw++av2aq/wEJzog/y1tbrSvbglcaXXI1SEC6x9qDaxCgmumM/FF41lPhccyjvGBtyasPyKQymuPf5UvU8iXCqRtYV/dvqn/w8SEtHz5MZ9q72qwcZBfhQb1XJB23sLn97CB30lnEm9hwz+CoPZ5Yyr/oeli/f04c+KypHfVzHVuEC/726FDtZn6yzu6G9ajN/JEpT0eCazydgF6aJif/QZ6eFiP8gknkjfRkJ83fY1V3XrA2b4bgXIdtpm85hJZd3HCtn0T2/mX6OFO02rKCoJZ+6E3sQ77pOp3c+X/h/mB/Wh3z4x12M9VfeFitDDfPhzM6+SSXbPGjATBjq7puOKy/iQPZzW7auF9Sd8yXb3TsX2ce+TLHDqqIhJMsV8eRhtaJ/tJs2smy4Jgtw69zKfNTaP/Crr8jkW2u2E6ttfXcYy/4aWcv8pxjs/rccX1StK3lkkcGPqlEhojGfTU5KVio6m7u3G3ar5OWIoEOum1dt/UuNuSJdV/GyRcHmPv1V/Ff5KUM/XQdakkSfn2dntXWV6tpiLGHLljuK2K6hsphctmErtU83NsxpitRrNP5BaQ7IPRvFZUC1leWe7Rfnc9Cure/qZwnWJjUr8sp/ziVbX/GVVuJzQ1HTNw/GA/aXbNpJcq69XUZMtXk8fsVSfZ94XHeGy3JrR5HU1ERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERES0kZxyyin7nHrqqcfq4DCLFy/e7qyzzpp7xhlnHKBZIZkO+SfoYEVOOumkHVDPRXPnzt1fPp922mlfRh2H6+gCKLPXmWeeOVsHZXh/lD2nsbFxG80adPrpp09FsnVwGNSzEMmSzyiXQLoM9e0YjlSod3vk1+Pj5IGcD2DaOqQpOjgIeUdhmr11cBhZZmynuA4OI8tw9tlnn6iDVZk3b95u2B5zdDCS1I8yp+tgAYzbCfv9QB0MYX/sKkkHS0KdTn57DoX8E6Rd6GABaT9Y18/pYKUmY3kuGbLvTsE8zovFYh8Jx6rzzjvvE0O3I6Y5DGUv1MFIqHM62uBuOhgJ2yiG+TWjrj3weWuZN6Ybdqxg3T6LcYfoIG3pcGB9Eg1iARrGDWgwn9fsAlIG495GSmlWCMOzke7VwbLQ+PfGfM5BfctPPvnkT59//vkfwwFwKfKWfuELXzhIiw3Cch2H+u/XQVmOAzHcjnSJZg1CWYP8VTpYAPO4CvPowsGR0OGZqGspAsDHwwJKDjKUyxpjttKsQTiozsc8foN5FARXDK/ANMfrYAHMYz/Mqx/zvRx/P6PZBVDnp5Eew8dhwbwczDuOaR/WwUhYbjk5fU0HB2F5DpbtjlSw3ZEfk2CigyWhzo5zzjnnJalfs0LIvxdp8GQ4FJZV3K2DFcE+qsN2XJnfd/h7Fur/8qJFiwoCK+o9HOlRHZT1+AzKpZC3TLMKyD7D+Hb8NaWCKwL1DEx/C5J/4okn7iWBVeaNZRjWmUD+N2WcDtKWDg3wMDSua9F4TkD6u6igIg0P4+5Hg5IgcgWywiCAz59DY/qOfK4EpneRFujgIATZo1DP1+fMmbOdZoWQNwvzvUsHQ7J8WObZmHdBQEC55SjfroODkL8MZVt1cESod1eUTUZtA9QzB/X3YfmvHBpMkCdBs1EHC2C7HYGgcBqmuQzpYs0ugPkdgLr/HR9rCawWpv0XHYykweDzSAUnRcz3s1jubh0chOU9BuOO0MGSUF+AwHMb/nZiHvtrtuR/B9NH9kqxrNLbvEMHK4JlvBbbbg8dLAn1HoJUcJJHe/oEliejgwWQ34byFyM1Y3mHndQlkMp+q2RbCJT7e9Q1VwdpS6YH3UJpWPo5g78zdfQgBL490WjuwTi5rPRlGrkcx0F4LD5XFFgx7bY4SJxSBwnqmX3CCSd8TAdDyJPAeqcODkI9MQlaOhhCucjAiry+qMtPvZ1QEMxQb8nAiuU+C/Wcib/Hocxgfag/MrDqbYU75GQhJyaU+zLKHayjB6GumgMrtuk0TPsQ6p4i6dxzz52CXuRhOnoQlsPG+DtkmXR4Dwyvxv77ZFhgCCxjA+qRXmFYJ+o/UgKUjh6EcZ0Yt0DWCetwI9ZxB80f08CKKxm5xXMNppPAeYy0QR1VQMcXBFaU3QnL0qKDg5AfQ/5SuX2Add0Hy3yzjhqEMjOxbsN6+qWgvq9i2zflt5vsC0xf9pYKTUByMKDRtumgHFTSEzyzOMDJgYhG+wAa29aSpLHioNwPDSguB5IWG5H0AEZqaKh3x+IDWBo36v+eBCfM/6NIn8aw3Cu9GqMLAhHGleqxNiN/2D0x5MWL11OWD+sWGVhlu6Cu8J4dpl2Nz+G9TeRfgemGBVbt+S3SQVmOqxCYp+rgIJSpObBiOrn8/R3SWizTWhzY8ndYkIDJmM85GHeZDMg8kfrDMUVQ17nz589/ROrD8q7F8Bp8HnaPGHkdSEvkM9YVm+C0hZo/poFVyIkJdcqtnrX4ezzm5eRPEnlY94NR931ye+lLX/rS9ih3BIYvxjQ9WiQkJ1RMPxvj5muWbI9mzGOw1y1kPijzbzpYFuazGtvtv2QZJeHzWsznJB1NWxI0nqvQCJbg70X4Kz3XC9CYfom/BZdGGljvzzdmlD0KZb6C/OOQvyYsVAFMMx/THK2DgzRYL8/3evLQMCWwrpWAi/nsgjInY/g+HV0A40v1WG9FgPhbHRyE8qcU99gwv3KBNbyNIeVQ742yfMi7EH+HBVaUlwDTItOg7EL8XSonseJ1RJnR9FjlwcqItwLyZBkxr0V6kmqN6oUKOSEgSEXeDx4K69SBeq6Sz/KwCuvWiSQ941ukXYSFiqB8TYF1KNlnSN9FT3ZfzQph/SSwPoC0u5TBcpyEJLcBik/A+yL/VmyLC/BX2ry0fRd//16LhLBOh6POq6LaQhTUcQvS2TpIWzI0Mrm/1KINbBEO1EX4ewXS8RLstFg+sP5waC8BjXc+pnsU+cMu1UuReWCaq1H3tpoVQp4cBCnpTWhWCOXlSevgww4JSmjsC4cuWx7ymlA2q4OD5CBH3dfLOmhWCHWfKAegDoZQtwRMt9StANk+OiiXqPsiT+7ReahrhmaHUO+xyJPt+BXUF25b+YvyNxQvB8oeiDoewMeqAyvqlHus9+hgWZj3ZZjmbKRL5DJYswtgeaZF9ayLYb5d2B5y5RDCvjkC69k7b968X6H+yLcgkH8qpvumDlYE+0RubRRsG6zH7TgxfEoHQ5j3oah78EFnKSh3EMoZ2Sf5/YK/sq8ujdg3JyJv2DOBKKjnVqTzdZC2VGgEl6PRRL6qg3HflEsqHcwH1h8UX36hXBvSP+tgWRKwUD6O+m7FQRmTwIYGfZ00cOlJabFBKCM9wqH1T8ZwI+pwdXgQ8q5GCnSwAPJnIX1P5iPDmP+VSN8o7rVJYEWZlhKB9XTUUfDUF1lzUP5R/C0IRCh3syynDg5C0NkN8+gdegLBOsorZBIcqw6sCID1mPa7OlgWllNeM7tbg1UkLHt4f1AHS0K5dsz7Sh0Moad7IJbpceQ3aFYBTHMSxn1dByuC7XsElvdr+Csnr62w/Bmky4vbot4KWKuDkaRNo8y1OlgA9f8txhU85JR9gzYqD1zvwbIfJe0Df7+F4fO0yCDk34Q0TwdpS4XG8ani142EBBU00v2GBhc0sK1xsO2Jj8MOfjTG3fVjxeTAlnlLgJHPxZfHeXLwYDkLehF6/6zgfVqBZZR3Moc9jMnDch4ul6zyGeX2k9e98LEggMo6l6pDlhHzKHhwIsNy8BW/+iPbqriskhODzHdwO8o20G1bNcxj2+LtU47sdyzDR3VwGKlTkg6WNH/+/J2jer2zZ8/epVT9sg3l5KKDlZosl+VYpp3kM/b9QcXbW1SyHVGHvIdasP3zpH5sm2HvIyN/R+RPlfvx8u4sPh8tD3N19CAJukM7I0RERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERFuKSZP+F0vlO4rFICMJAAAAAElFTkSuQmCC" alt="" style="float: left;"></p><p class="MsoNormal" style="margin-bottom: 7.5pt; text-indent: 3pt; background-image: initial; background-position: initial; background-size: initial; background-repeat: initial; background-attachment: initial; background-origin: initial; background-clip: initial;"></p></div></div></div></div><div class="col-md-4 col-xs-6" ></div>
  4783.         ';
  4784.         //Generamos el contrato
  4785.         $contract $contract00 '<b>' ' ' $client->getName() . '</b>' ' ' $contract01 'CIF ' $client->getIdDocument() . ' ' .
  4786.             $contract02 '<b>' ' ' $client->getAddress() . '</b>' ',' $contract03 ' ' $representante '.' .
  4787.             $contract04 $reserva->getTitle() . $contract05 $fechaInicio $contract06 $horaInicio $contract07 .
  4788.             $contract08 $textoSalas $contract09 $cierre $contract10 $pax $contract11 $fechaInicio .
  4789.             $contract12 $textoSalas $contract13 $textoMontaje $textoDesmontaje $contract14 $tiempoCedido .
  4790.             $contract15 $contract16 $contract17 $contract18 $contract19 $contract20 $contract21 $contract22 $contract23;
  4791.         // Si no habia contracto originalmente en la reserva se actualiza
  4792.         if (empty($contractOrigin)) {
  4793.             $reserva->setContract($contract);
  4794.             $em->persist($reserva);
  4795.             $em->flush();
  4796.         } else {
  4797.             $contract $contractOrigin;
  4798.         }
  4799.         return $this->render('MDS/VenuesBundle/reservations/view-contract-reservation.html.twig', array('id' => $id'contract' => $contract, ));
  4800.     }
  4801.     /**
  4802.      * @Route("/createdeposit/{id}", name="reservations_venues_createdeposit")
  4803.      */
  4804.     public function createDepositAction($idEntityManagerInterface $emRequest $request)
  4805.     {
  4806.         $newRequest $request->request->get('reservation_deposit');
  4807.         /* Obtengo usuario logueado */
  4808.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  4809.         $user_id $user_logueado->getId();
  4810.         $newDeposit = new ReservationDeposit();
  4811.         $newDeposit->setReservationId($id);
  4812.         if (empty($newRequest['date'])) {
  4813.             $newDeposit->setDate(new DateTime('now'));
  4814.         } else {
  4815.             $newDeposit->setDate(new DateTime($newRequest['date']));
  4816.         }
  4817.         if (empty($newRequest['description'])) {
  4818.             $newDeposit->setDescription(null);
  4819.         } else {
  4820.             $newDeposit->setDescription($newRequest['description']);
  4821.         }
  4822.         if (empty($newRequest['amount'])) {
  4823.             $newDeposit->setAmount(null);
  4824.         } else {
  4825.             $newDeposit->setAmount($newRequest['amount']);
  4826.         }
  4827.         if (array_key_exists('isDone'$newRequest)) {
  4828.             $newDeposit->setIsDone(true);
  4829.         } else {
  4830.             $newDeposit->setIsDone(false);
  4831.         }
  4832.         $newDeposit->setCreatedId($user_id);
  4833.         $newDeposit->setUpdatedId($user_id);
  4834.         $em->persist($newDeposit);
  4835.         $em->flush();
  4836.         return $this->redirectToRoute('reservations_venues_edit_simple', array('id' => $id'token' => null'_fragment' => 'btn_dpt'));
  4837.     }
  4838.     /**
  4839.      * @Route("/depositupdate/{id}", name="reservations_venues_deposit_update")
  4840.      */
  4841.     public function depositUpdateAction($idEntityManagerInterface $emRequest $request)
  4842.     {
  4843.         $newRequest $request->request->get('reservation_deposit_isdone_pending');
  4844.         $depósito $em->getRepository(ReservationDeposit::class)->findOneById($id);
  4845.         if (array_key_exists('isDone'$newRequest)) {
  4846.             $depósito->setIsDone(true);
  4847.         } else {
  4848.             $depósito->setIsDone(false);
  4849.         }
  4850.         /* Obtengo usuario logueado */
  4851.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  4852.         $user_id $user_logueado->getId();
  4853.         $depósito->setUpdatedAt(new DateTime('now'));
  4854.         $depósito->setUpdatedId($user_id);
  4855.         $em->persist($depósito);
  4856.         $em->flush();
  4857.         return $this->redirectToRoute('reservations_venues_edit_simple', array('id' => $depósito->getReservationId(), 'token' => null'_fragment' => 'btn_dpt'));
  4858.     }
  4859.     /**
  4860.      * @Route("/loadedreservations", name="reservations_venues_loaded_reservations")
  4861.      */
  4862.     public function loadedReservationsAction(EntityManagerInterface $emRequest $request)
  4863.     {
  4864.         $hoy = new DateTime('now');
  4865.         $diaInicio = new DateTime($hoy->format('Y-m') . '-01');
  4866.         // Se buscan las reservas creadas desde el inicio de mes
  4867.         $parameters = array('diaInicio' => $diaInicio, );
  4868.         $dql 'SELECT i
  4869.                 FROM VenuesBundle:Reservation i
  4870.                 WHERE  i.createdAt > :diaInicio';
  4871.         $query $em->createQuery($dql)->setParameters($parameters);
  4872.         $reservas $query->getResult();
  4873.         return $this->render('MDS/VenuesBundle/reservations/list-loaded-reservations.html.twig', array('reservations' => $reservas'itemsOfSearch' => '', ));
  4874.     }
  4875.     /**
  4876.      * @Route("/searchreservations", name="reservations_venues_search_reservations")
  4877.      */
  4878.     public function searchReservationsAction(EntityManagerInterface $emRequest $request)
  4879.     {
  4880.         $searchloaded $request->request->get('searchloaded');
  4881.         $dateStart = new \DateTime($searchloaded['date_start']);
  4882.         $dateEnd = new \DateTime($searchloaded['date_end']);
  4883.         $itemsOfSearch ' Entre las fechas: ' $dateStart->format('d/m/Y') . ' y ' $dateEnd->format('d/m/Y');
  4884.         // Se buscan las reservas creadas en las fechas solicitadas
  4885.         $parameters = array('diaInicio' => $dateStart'diaFin' => $dateEnd, );
  4886.         $dql 'SELECT i
  4887.                 FROM VenuesBundle:Reservation i
  4888.                 WHERE  i.createdAt BETWEEN :diaInicio AND :diaFin';
  4889.         $query $em->createQuery($dql)->setParameters($parameters);
  4890.         $reservas $query->getResult();
  4891.         return $this->render('MDS/VenuesBundle/reservations/list-loaded-reservations.html.twig', array('reservations' => $reservas'itemsOfSearch' => $itemsOfSearch, ));
  4892.     }
  4893.     /**
  4894.      * Cambia las descripciones de las reservas al idioma seleccionado
  4895.      * @Route("/changeLanguage/{id}/{idLanguage}", name="reservations_venues_change_language", methods={"GET"})
  4896.      */
  4897.     public function changeLanguageAction(int $idint $idLanguageEntityManagerInterface $emSerializerInterface $serializerInterface): JsonResponse
  4898.     {
  4899.         $descriptions $em->getRepository(ReservationLoungeSimple::class)->findBy(array('idReservation' => $id));
  4900.         $idiomas = array();
  4901.         foreach ($descriptions as $description) {
  4902.             $reservationsLoungeDetails $em->getRepository(ReservationLoungeDetails::class)->findOneById($description->getIdLounge());
  4903.             $idiomas[$description->getIdLounge()] = $em->getRepository(ReservationLoungeWebDescription::class)->findOneBy(array('lounge' => $reservationsLoungeDetails'language' => $idLanguage));
  4904.         }
  4905.         $idiomas $serializerInterface->serialize($idiomas'json', [
  4906.             'groups' => ['reservation_lounge_web_description:read']
  4907.         ]);
  4908.         $idiomas json_decode($idiomastrue);
  4909.         return $this->json([
  4910.             'status' => JsonResponse::HTTP_OK,
  4911.             'idiomas' => $idiomas,
  4912.         ], JsonResponse::HTTP_OK);
  4913.     }
  4914.     private function sendMail($mailAddressFrom$mailAddressTo$mailSubject$mailBody)
  4915.     {
  4916.         $em $this->getDoctrine()->getManager();
  4917.         $agent $em->getRepository(User::class)->findOneByEmail($mailAddressFrom);
  4918.         $client $em->getRepository(Client::class)->findOneByEmail($mailAddressTo);
  4919.         if (empty($client)) {
  4920.             $client $em->getRepository(ClientContact::class)->findOneByEmail($mailAddressTo);
  4921.         }     // Si el cliente era null puede ser un client contact
  4922.         if (!empty($client)) {
  4923.             $replyTo = array(
  4924.                 $client->getEmail() => $client->getName(),
  4925.                 $agent->getEmail() => $agent->getName() . ' ' $agent->getLastName(),
  4926.             );
  4927.         } else {
  4928.             // El AddressTo es un contacto no registrado
  4929.             $replyTo = array(
  4930.                 $mailAddressTo => $mailAddressTo,
  4931.                 $agent->getEmail() => $agent->getName() . ' ' $agent->getLastName(),
  4932.             );
  4933.         }
  4934.         $agentMail $mailAddressFrom;
  4935.         $mailAgent $agentMail;
  4936.         //Se prepara el correo con los agentes a notificar
  4937.         $firmGmail $agent->getFirmGmail();
  4938.         $data = array(
  4939.             'body' => $mailBody,
  4940.             'firm' => $firmGmail,
  4941.         );
  4942.         // EJECUTAR ENVIO DE ALERTA PARA EL AGENTE
  4943.         $transporter = new \Swift_SmtpTransport();
  4944.         $transporter->setHost('smtp.gmail.com')
  4945.             ->setEncryption('ssl'//ssl / tls
  4946.             ->setPort(465// 465 / 587
  4947.             ->setUsername('desarrollo@develup.solutions')
  4948.             ->setPassword('utvh hzoi wfdo ztjs');
  4949.         //            ->setPassword('MeDITeRRANeAN_Develup30102023#');
  4950.         $mailer = new \Swift_Mailer($transporter);
  4951.         $message = new \Swift_Message();
  4952.         $message->setSubject($mailSubject)
  4953.             ->setSender($agentMail)
  4954.             ->setFrom(array("desarrollo@develup.solutions" => "Venues"))
  4955.             ->setReplyTo($agentMail)
  4956.             ->setTo($replyTo)
  4957.             ->setBody(
  4958.                 $this->renderView(
  4959.                     'mail/structure-mail.html.twig',
  4960.                     array('data' => $data)
  4961.                 ),
  4962.                 'text/html'
  4963.             );
  4964.         //        $mailer->send($message);          Rafa dijo que no queria envío de correos con el cliente ya que se haría mediante la cotización Web (04/02/2025)
  4965.         return true;
  4966.     }
  4967.     private function makeAlert($reservaId$clientId$clientMail$agentId$agentMail)
  4968.     {
  4969.         $em $this->getDoctrine()->getManager();
  4970.         $alertaPrevia $em->getRepository(ReservationMailAlertClient::class)->findOneByReservationId($reservaId);
  4971.         $reserva $em->getRepository(Reservation::class)->findOneById($reservaId);
  4972.         $dias $reserva->getDaysBlock();
  4973.         if (empty($dias) or !(is_numeric($dias))) {
  4974.             $dias 7;
  4975.         }
  4976.         $diasMenosDos $dias 2;
  4977.         /* Obtengo usuario logueado */
  4978.         $user_logueado $this->get('security.token_storage')->getToken()->getUser();
  4979.         $user_id $user_logueado->getId();
  4980.         $hoy = new \DateTime("now"NULL);
  4981.         $hoyMasCinco $hoy;
  4982.         $hoyMasCinco->add(new DateInterval('P' $diasMenosDos 'D'));                   // 5 dias despues, 48 horas antes de la cancelacion (o los especificados)
  4983.         $hoyMasCinco->add(new DateInterval("PT2H"));                                  // Ajustamos la diferencia con el reloj del servidor
  4984.         $hoy = new \DateTime("now"NULL);
  4985.         $hoyMasSiete $hoy;
  4986.         $hoyMasSiete->add(new DateInterval('P' $dias 'D'));                           // Siete dias despues (o los especificados)
  4987.         $hoyMasSiete->add(new DateInterval("PT2H"));
  4988.         //Si no hay una alerta previa se hace la alerta
  4989.         if (empty($alertaPrevia)) {
  4990.             $alerta = new ReservationMailAlertClient();
  4991.             $alerta->setReservationId($reservaId);
  4992.             $alerta->setClientId($clientId);
  4993.             $alerta->setClientMail($clientMail);
  4994.             $alerta->setAgentId($agentId);
  4995.             $alerta->setAgentMail($agentMail);
  4996.             $alerta->setAlertDateTime($hoyMasCinco);                // A los 5 dias se alerta (o los especificados)
  4997.             $alerta->setAlertSended(false);
  4998.             $alerta->setCancelDateTime($hoyMasSiete);               // A los 7 dias se cancela (o los especificados)
  4999.             $alerta->setCancelSended(false);
  5000.             $alerta->setOldReservationId(null);                     // Aqui se guardara el Id de reserva cuando se vaya a eliminar el registro (solo se pondra reservationId a 0)
  5001.             $alerta->setCreatedAt($hoy);
  5002.             $alerta->setCreatedId($user_id);
  5003.             $em->persist($alerta);
  5004.             $em->flush();
  5005.         }
  5006.         return true;
  5007.     }
  5008. //    private function benefitForReservation($id)
  5009. //    {
  5010. //
  5011. //        $em = $this->getDoctrine()->getManager();
  5012. //        $reserva = $em->getRepository(Reservation::class)->findOneById($id);
  5013. //        $reservationsLounges = $em->getRepository(ReservationLoungeSimple::class)->findByIdReservation($id);
  5014. //        $services = $em->getRepository(ReservationService::class)->findByReservationId($id);
  5015. //        $payedLounges = array();
  5016. //        $payedServices = array();
  5017. //        $unPayedServices = array();
  5018. //
  5019. //        // Salas
  5020. //        foreach ($reservationsLounges as $item) {
  5021. //            // Si la sala esta en ReservationInvoiceItems se encuentra facturado, en caso contraio, no lo esta o ha sido rectificado
  5022. //            $reservationsLoungeInvoicedItem = $em->getRepository(ReservationInvoiceItems::class)->findOneByLngControlId($item->getId());
  5023. //            if (!empty($reservationsLoungeInvoicedItem)) {
  5024. //                $payedLounges[] = $item;
  5025. //            }                       // Esta facturado el Item
  5026. //        }
  5027. //
  5028. //        // Servicios
  5029. //        foreach ($services as $item) {
  5030. //            // Si el servicio esta en ReservationInvoiceItems se encuentra facturado, en caso contraio, no lo esta o ha sido rectificado
  5031. //            $serviceInvoicedItem = $em->getRepository(ReservationInvoiceItems::class)->findOneBySrvControlId($item->getId());
  5032. //
  5033. //            if (!empty($serviceInvoicedItem)) {
  5034. //                // Esta facturado el Item
  5035. //                $payedServices[] = $item;
  5036. //            } else {
  5037. //                // No esta facturado el Item o fue rectificado
  5038. //                $unPayedServices[] = $item;
  5039. //            }
  5040. //        }
  5041. //
  5042. //        $benefit = 0;
  5043. //        $payed = 0;
  5044. //
  5045. //        // Se suman los pagos
  5046. //        foreach ($payedLounges as $item) {
  5047. //            $benefit = $benefit + (float) $item->getServicePrice();
  5048. //            $payed = $payed + (float) $item->getServicePrice();
  5049. //        }
  5050. //
  5051. //        foreach ($payedServices as $item) {
  5052. //            $benefit = $benefit + (float) $item->getPrice();
  5053. //            $payed = $payed + (float) $item->getPrice();
  5054. //        }
  5055. //
  5056. //        // Se restan los impagos
  5057. //        foreach ($unPayedServices as $item) {
  5058. //            // Se verifica el check de toinvoice por si el servicio se facturara a futuro (Requisito de Rafa)
  5059. //            if ($item->getToinvoice()) {
  5060. //                $benefit += (float) $item->getPrice();
  5061. //                $payed += (float) $item->getPrice();
  5062. //            } else {
  5063. //                // No esta pagado y no esta marcado "Para facturar"
  5064. //                $benefit = $benefit - (float) $item->getPrice();
  5065. //            }
  5066. //        }
  5067. //
  5068. //        // Porcentaje de beneficio
  5069. //        $percBenefit = ($benefit * 100);
  5070. //        if (!($payed == 0)) {
  5071. //            $percBenefit = $percBenefit / $payed;
  5072. //        } else {
  5073. //            $percBenefit = 0;
  5074. //        }
  5075. //        ;
  5076. //
  5077. //        return array(
  5078. //            'benefit' => $benefit,
  5079. //            'percBenefit' => $percBenefit,
  5080. //            'payedLounges' => $payedLounges,
  5081. //            'payedServices' => $payedServices,
  5082. //            'unPayedServices' => $unPayedServices,
  5083. //        );
  5084. //    }
  5085.     private function benefitForReservation($id)
  5086.     {
  5087.         $em $this->getDoctrine()->getManager();
  5088.         $reserva $em->getRepository(Reservation::class)->findOneById($id);
  5089.         $reservationsLounges $em->getRepository(ReservationLoungeSimple::class)->findByIdReservation($id);
  5090.         $services $em->getRepository(ReservationService::class)->findByReservationId($id);
  5091.         $payedLounges = [];
  5092.         $payedServices = [];
  5093.         $unPayedServices = [];
  5094.         // Validar variable Sucoe (Ajusta este getter según la entidad Reservation)
  5095.         $reservaSucoe method_exists($reserva'getSucoe') ? $reserva->getSucoe() : false;
  5096.         // Salas
  5097.         foreach ($reservationsLounges as $item) {
  5098.             $reservationsLoungeInvoicedItem $em->getRepository(ReservationInvoiceItems::class)->findOneByLngControlId($item->getId());
  5099.             if (!empty($reservationsLoungeInvoicedItem)) {
  5100.                 $payedLounges[] = $item;
  5101.             }
  5102.         }
  5103.         // Servicios
  5104.         foreach ($services as $item) {
  5105.             $serviceInvoicedItem $em->getRepository(ReservationInvoiceItems::class)->findOneBySrvControlId($item->getId());
  5106.             if (!empty($serviceInvoicedItem)) {
  5107.                 $payedServices[] = $item;
  5108.             } else {
  5109.                 $unPayedServices[] = $item;
  5110.             }
  5111.         }
  5112.         // --- CLOSURE: FUNCIÓN PARA CALCULAR EL PRECIO REAL DEL SERVICIO ---
  5113.         $calculateServicePrice = function ($item) use ($reservaSucoe) {
  5114.             $priceRaw = (float) $item->getPrice();
  5115.             // Comisión y Over en precio unitario
  5116.             $commission = (float) $item->getCommission();
  5117.             $unitPrice = ($item->getOpCommission() == '1')
  5118.                 ? ($priceRaw + ($priceRaw $commission 100))
  5119.                 : ($priceRaw - ($priceRaw $commission 100));
  5120.             $over = (float) $item->getOver();
  5121.             $unitPrice = ($item->getOpOver() == '1') ? ($unitPrice $over) : ($unitPrice $over);
  5122.             $subneto $unitPrice;
  5123.             $subtotalLine $unitPrice;
  5124.             // Multiplicadores
  5125.             $pax max(1, (int) $item->getPax());
  5126.             $units max(1, (int) $item->getUnits());
  5127.             $dateIn $item->getDateInAt();
  5128.             $dateOut $item->getDateOutAt();
  5129.             $catId $item->getServiceCatId();
  5130.             // Lógica de días asegurando que las fechas no sean nulas
  5131.             $days 1;
  5132.             if ($dateIn && $dateOut) {
  5133.                 $daysDiff $dateIn->diff($dateOut)->days;
  5134.                 $days = ($catId == 5) ? $daysDiff : ($daysDiff 1);
  5135.                 $days max(1$days); // Prevenir multiplicador 0
  5136.             }
  5137.             switch ($catId) {
  5138.                 case 1// Alojamiento
  5139.                     $numNoches = ($dateIn && $dateOut) ? max(1$dateIn->diff($dateOut)->days) : 1;
  5140.                     $subneto *= $numNoches $units;
  5141.                     $subtotalLine *= $numNoches $units;
  5142.                     break;
  5143.                 case 2// Actividades
  5144.                     $subneto *= $days $units;
  5145.                     $subtotalLine *= $days $units;
  5146.                     break;
  5147.                 default: // Resto
  5148.                     $subneto *= $days $units $pax;
  5149.                     $subtotalLine *= $days $units $pax;
  5150.                     break;
  5151.             }
  5152.             // IVA
  5153.             $ivaRate $item->getSageIva() ? (float) $item->getSageIva()->getIva() : 21.0;
  5154.             if ($item->getOpIva() == '1') {
  5155.                 if (!$reservaSucoe) {
  5156.                     $subtotalLine *= (+ ($ivaRate 100));
  5157.                 }
  5158.             } else {
  5159.                 // Lógica heredada: extraemos la base
  5160.                 $subtotalLine = ($priceRaw 100) / (100 $ivaRate);
  5161.                 $subneto = ($subneto 100) / (100 $ivaRate);
  5162.             }
  5163.             $neto round($subneto2PHP_ROUND_HALF_UP);
  5164.             // $totalConIva = round($subtotalLine, 2, PHP_ROUND_HALF_UP);
  5165.             // Retornamos el Neto para cálculo de beneficios.
  5166.             // Si necesitas el valor con IVA, cambia esta línea a: return $totalConIva;
  5167.             return $neto;
  5168.         };
  5169.         // -------------------------------------------------------------------
  5170.         $benefit 0;
  5171.         $payed 0;
  5172.         // Se suman los pagos de Salas
  5173.         foreach ($payedLounges as $item) {
  5174.             $benefit += (float) $item->getServicePrice();
  5175.             $payed += (float) $item->getServicePrice();
  5176.         }
  5177.         // Se suman los pagos de Servicios usando la nueva lógica
  5178.         foreach ($payedServices as $item) {
  5179.             $realPrice $calculateServicePrice($item);
  5180.             $benefit += $realPrice;
  5181.             $payed += $realPrice;
  5182.         }
  5183.         // Se restan/suman los impagos de Servicios usando la nueva lógica
  5184.         foreach ($unPayedServices as $item) {
  5185.             $realPrice $calculateServicePrice($item);
  5186.             // Se verifica el check de toinvoice por si el servicio se facturara a futuro
  5187.             if ($item->getToinvoice()) {
  5188.                 $benefit += $realPrice;
  5189.                 $payed += $realPrice;
  5190.             } else {
  5191.                 // No esta pagado y no esta marcado "Para facturar"
  5192.                 $benefit -= $realPrice;
  5193.             }
  5194.         }
  5195.         // Porcentaje de beneficio
  5196.         $percBenefit 0;
  5197.         if ($payed != 0) {
  5198.             $percBenefit = ($benefit 100) / $payed;
  5199.         }
  5200.         return [
  5201.             'benefit' => $benefit,
  5202.             'percBenefit' => $percBenefit,
  5203.             'payedLounges' => $payedLounges,
  5204.             'payedServices' => $payedServices,
  5205.             'unPayedServices' => $unPayedServices,
  5206.         ];
  5207.     }
  5208.     private function verificarStatusInicialyFinal($id$user_id$estadoInicial$estadoFinal)
  5209.     {
  5210.         $em $this->getDoctrine()->getManager();
  5211.         // Nueva validación: No permitir pasar a 'Invoiced' manualmente si no hay facturas
  5212.         if ($estadoFinal === 'Invoiced' && $estadoInicial !== 'Invoiced') {
  5213.             $invoiceRepository $em->getRepository(ReservationInvoice::class);
  5214.             $invoiceRecRepository $em->getRepository(ReservationInvoiceRec::class);
  5215.             $hasInvoices = !empty($invoiceRepository->findByReservationId($id)) || !empty($invoiceRecRepository->findByReservationId($id));
  5216.             if (!$hasInvoices) {
  5217.                 $this->addFlash('mensajereservationerror''No se puede cambiar el estado a FACTURADO si la reserva no tiene facturas.');
  5218.                 return $estadoInicial;
  5219.             }
  5220.         }
  5221.         $reserva $em->getRepository(Reservation::class)->findOneById($id);
  5222.         $user_logueado $em->getRepository(User::class)->findOneById($user_id);
  5223.         $newStatus 'Pendiente';
  5224.         //Este Switch ya no es necesario
  5225.         switch ($estadoInicial) {
  5226.             case 'Bloqueo':
  5227.                 // De bloqueo solo se sale si el usuario es Salvador o un Admin O si se va a Cancelar "Deleted" o "Cotizado"
  5228.                 //                if (($user_logueado->getRole() == 'ROLE_ADMIN') or ($user_id == 14) or $estadoFinal == 'Deleted' or $estadoFinal == 'Cotizado'){
  5229.                 if ($estadoFinal == 'Deleted' or $estadoFinal == 'Cotizado') {
  5230.                     $newStatus $estadoFinal;
  5231.                 } else {
  5232.                     // No se cambia el estado
  5233.                     $newStatus $estadoInicial;
  5234.                 }
  5235.                 break;
  5236.             case 'Pendiente':
  5237.                 // De Pendiente solo se sale si el usuario es Salvador o un Admin O si se va a Cancelar "Deleted"
  5238.                 $newStatus $estadoFinal;
  5239.                 //                if (($user_logueado->getRole() == 'ROLE_ADMIN') or ($user_id == 14) or $estadoFinal == 'Deleted'){
  5240.                 if ($estadoFinal == 'Deleted') {
  5241.                     $newStatus $estadoFinal;
  5242.                 } else {
  5243.                     // No se cambia el estado
  5244.                     $newStatus $estadoInicial;
  5245.                 }
  5246.                 break;
  5247.             case 'Deleted':
  5248.                 // De Cancelado solo se sale si el usuario es Salvador o un Admin O "Bloqueo" o "Pendiente"
  5249.                 //                if (($user_logueado->getRole() == 'ROLE_ADMIN') or ($user_id == 14) or $estadoFinal == 'Bloqueo' or $estadoFinal == 'Pendiente'or $estadoFinal == 'Cotizado'){
  5250.                 if ($estadoFinal == 'Bloqueo' or $estadoFinal == 'Pendiente' or $estadoFinal == 'Cotizado') {
  5251.                     $newStatus $estadoFinal;
  5252.                 } else {
  5253.                     // No se cambia el estado
  5254.                     $newStatus $estadoInicial;
  5255.                 }
  5256.                 break;
  5257.             case 'Cotizado':
  5258.                 $newStatus $estadoFinal;
  5259.                 // De Cotizado solo se sale si el usuario es Salvador o un Admin O a  O "Bloqueo" o "Pendiente" o "Cancelado"
  5260.                 //                if (($user_logueado->getRole() == 'ROLE_ADMIN') or ($user_id == 14) or $estadoFinal == 'Bloqueo' or $estadoFinal == 'Pendiente' or $estadoFinal == 'Deleted'){
  5261.                 if ($estadoFinal == 'Bloqueo' or $estadoFinal == 'Pendiente' or $estadoFinal == 'Deleted' or $estadoFinal == 'Confirmed') {
  5262.                     $newStatus $estadoFinal;
  5263.                 }
  5264.                 break;
  5265.             case 'Invoiced':
  5266.                 // De Facturado no se debe salir a menos que se rectifique
  5267.                 // Si todas las facturas del expediente se encuentran rectificadas pasamos al estado "Confirmado" sino seguimos en "Facturado"
  5268.                 $reservaInvoices $em->getRepository(ReservationInvoice::class)->findByReservationId($id);
  5269.                 $estanTodasRectificadas true;
  5270.                 foreach ($reservaInvoices as $item) {
  5271.                     $reservaInvoiceRect $em->getRepository(ReservationInvoiceRec::class)->findOneByInvoiceToRec($item->getId());
  5272.                     if (empty($reservaInvoiceRect)) {
  5273.                         $estanTodasRectificadas false;
  5274.                     } else {
  5275.                         $estanTodasRectificadas = ($estanTodasRectificadas and true);
  5276.                     }
  5277.                 }
  5278.                 if ($estanTodasRectificadas) {
  5279.                     $newStatus 'Confirmed';
  5280.                 } else {
  5281.                     $newStatus $estadoInicial;
  5282.                 }
  5283.                 break;
  5284.             case 'Confirmed':
  5285.                 // Se puede ir a cualquier estado
  5286.                 $newStatus $estadoFinal;
  5287.                 break;
  5288.             default:
  5289.                 // No hacer nada con el campo Status
  5290.                 $newStatus $estadoInicial;
  5291.                 break;
  5292.         }
  5293.         $newStatus $estadoFinal;
  5294.         return $newStatus;
  5295.     }
  5296.     private function disponibilidadVenues($id)
  5297.     {
  5298.         // $id Id de la reserva
  5299.         $em $this->getDoctrine()->getManager();
  5300.         $reserva $em->getRepository(Reservation::class)->findOneById($id);
  5301.         //        $reservationsLounges = $em->getRepository(ReservationLoungeSimple::class)->findByIdReservation($id);
  5302.         //Buscamos salas que tengamos entre el inicio y fin del evento a confirmar
  5303.         //Sumamos un dia ya que por solicitud de Salva deseamos saber que eventos hay un dia antes y un dia despues
  5304.         $fechaInicio = new \DateTime($reserva->getDateStart()->format('Y-m-d H:i:s'));
  5305.         //        $fechaInicio->sub(new \DateInterval("P1D"));
  5306.         $fechaFin = new \Datetime($reserva->getDateEnd()->format('Y-m-d H:i:s'));
  5307.         //        $fechaFin->add(new \DateInterval("P1D"));
  5308.         // Los eventos que debemos verificar son los Confirmados y Facturados
  5309.         //        $parameters = array(
  5310.         //            'reservaId' => $id,
  5311.         //            'dateStart' => $fechaInicio,
  5312.         //            'dateEnd' => $fechaFin,
  5313.         //            'facturado' => 'Invoiced',
  5314.         //            'confirmado' => 'Confirmed',
  5315.         //        );
  5316.         //        $dql = 'SELECT r
  5317.         //                FROM  VenuesBundle:Reservation r
  5318.         //                INNER JOIN VenuesBundle:ReservationLoungeSimple l WITH r.id = l.idReservation
  5319.         //                  WHERE (r.status = :facturado OR r.status = :confirmado)
  5320.         //                    AND (not(r.id = :reservaId))
  5321.         //                    AND ((l.dateStart >= :dateStart and l.dateStart <= :dateEnd))';
  5322.         //
  5323.         //        $query = $em->createQuery($dql)->setParameters($parameters);
  5324.         //        $reservationInDates = $query->getResult();
  5325.         $parameters = array(
  5326.             'dateStart' => $fechaInicio,
  5327.             'dateEnd' => $fechaFin,
  5328.             'facturado' => 'Invoiced',
  5329.             'confirmado' => 'Confirmed',
  5330.         );
  5331.         $dql 'SELECT r
  5332.         FROM VenuesBundle:Reservation r
  5333.         INNER JOIN VenuesBundle:ReservationLoungeSimple l WITH r.id = l.idReservation
  5334.         WHERE (r.status = :facturado OR r.status = :confirmado) 
  5335.         AND (
  5336.             l.dateStart <= :dateEnd 
  5337.             AND l.dateEnd >= :dateStart
  5338.         )';
  5339.         $query $em->createQuery($dql)->setParameters($parameters);
  5340.         $reservationsInConflict $query->getResult();
  5341.         $arrayUso = [];
  5342.         $arrayAlert = [];
  5343.         $arrayAlertMontDesmont = [];                // Nuevo array para almacenar conflictos de montaje y desmontaje
  5344.         if (sizeof($reservationsInConflict) > 1) {
  5345.             foreach ($reservationsInConflict as $resConflict) {
  5346.                 $reservationsLoungesConflict $em->getRepository(ReservationLoungeSimple::class)->findByIdReservation($resConflict->getId());
  5347.                 foreach ($reservationsLoungesConflict as $item) {
  5348.                     $type $item->getType();                               // Puede ser NULL, "Montaje" o "Desmontaje"
  5349.                     $dateKey $item->getDateStart()->format('Ymd');
  5350.                     $reservationsLoungeId $item->getIdLounge();
  5351.                     $reservationId $item->getIdReservation();
  5352.                     if (in_array($reservationsLoungeId, [249])) {
  5353.                         // Plenaria, Invernadero y Escenario se consideran la misma sala
  5354.                         $arrayUso[2][$dateKey][$reservationId] = empty($type) ? 'Sala' $type;
  5355.                         $arrayUso[4][$dateKey][$reservationId] = empty($type) ? 'Sala' $type;
  5356.                         ;
  5357.                         $arrayUso[9][$dateKey][$reservationId] = empty($type) ? 'Sala' $type;
  5358.                         ;
  5359.                     } else {
  5360.                         $lngDetails $em->getRepository(ReservationLoungeDetails::class)->findOneById($reservationsLoungeId);
  5361.                         if (empty($lngDetails->getCombo())) {
  5362.                             $arrayUso[$reservationsLoungeId][$dateKey][$reservationId] = empty($type) ? 'Sala' $type;
  5363.                         } else {
  5364.                             $arrayComboLounges explode(","$lngDetails->getCombo());
  5365.                             foreach ($arrayComboLounges as $indLounge) {
  5366.                                 $arrayUso[$indLounge][$dateKey][$reservationId] = empty($type) ? 'Sala' $type;
  5367.                             }
  5368.                         }
  5369.                     }
  5370.                 }
  5371.             }
  5372.             foreach ($arrayUso as $idLounge => $dates) {
  5373.                 foreach ($dates as $dateKey => $reservations) {
  5374.                     // Si el ID de la reserva está presente, obtener su dato
  5375.                     $datoId = isset($reservations[$id]) ? $reservations[$id] : 0;
  5376.                     foreach ($reservations as $reservationId => $dato) {
  5377.                         if ($reservationId != $id) {
  5378.                             if ($datoId === "Sala" && $dato === "Sala") {
  5379.                                 $arrayAlert[$reservationId][] = array('dateKey' => $dateKey'idLounge' => $idLounge'reservationId' => $reservationId);
  5380.                             } elseif (($datoId === "Montaje" || $datoId === "Desmontaje") && ($dato === "Montaje" || $dato === "Desmontaje")) {
  5381.                                 $arrayAlertMontDesmont[$reservationId][] = array('dateKey' => $dateKey'idLounge' => $idLounge'reservationId' => $reservationId);
  5382.                             } elseif ($datoId === "Sala" && ($dato === "Montaje" || $dato === "Desmontaje")) {
  5383.                                 $arrayAlert[$reservationId][] = array('dateKey' => $dateKey'idLounge' => $idLounge'reservationId' => $reservationId);
  5384.                             } elseif (($datoId === "Montaje" || $datoId === "Desmontaje") && $dato === "Sala") {
  5385.                                 $arrayAlert[$reservationId][] = array('dateKey' => $dateKey'idLounge' => $idLounge'reservationId' => $reservationId);
  5386.                             }
  5387.                         }
  5388.                     }
  5389.                 }
  5390.             }
  5391.         }
  5392.         $reservationInDates = [];
  5393.         if (!empty($arrayAlert)) {
  5394.             foreach ($arrayAlert as $key => $item) {
  5395.                 $resvConf $em->getRepository(Reservation::class)->findOneById($key);
  5396.                 $reservationInDates[] = $resvConf;
  5397.             }
  5398.             // La reserva no puede pasar a confirmada
  5399.             $reserva->setStatus('Cotizado');
  5400.             $em->persist($reserva);
  5401.             $em->flush();
  5402.         } else {
  5403.             $mensajeWarning '<br>';
  5404.             if (!empty($arrayAlertMontDesmont)) {
  5405.                 foreach ($arrayAlertMontDesmont as $key => $item) {
  5406.                     $mensajeWarning .= 'Reserva ID: ' $key '<br>';
  5407.                 }
  5408.                 $this->addFlash('mensajereservationerror''ADVERTENCIA, se han guardado los cambios, pero hay coincidencias en los Montajes y/o Desmontajes' $mensajeWarning);
  5409.                 $reservationInDates = [];
  5410.             }
  5411.         }
  5412.         return $reservationInDates;
  5413.     }
  5414.     //    private function disponibilidadAvExpress($id){
  5415.     //        // $id Id de la reserva de Venues que vamos a confirmar
  5416.     //        $em = $this->getDoctrine()->getManager();
  5417.     //        $reserva = $em->getRepository(Reservation::class)->findOneById($id);
  5418.     //
  5419.     //        //Sumamos un dia ya que por solicitud de Salva deseamos saber que eventos hay un dia antes y un dia despues
  5420.     //        $fechaInicio = new \Datetime($reserva->getDateStart()->format('Y-m-d'));
  5421.     //        $fechaInicio->sub(new \DateInterval("P1D"));
  5422.     //        $fechaFin = new \Datetime($reserva->getDateEnd()->format('Y-m-d 23:59'));
  5423.     //        $fechaFin->add(new \DateInterval("P1D"));
  5424.     //
  5425.     //        $parameters = array( 'dateStart' => $fechaInicio, 'dateEnd' => $fechaFin, );
  5426.     //
  5427.     //        $dql = 'SELECT i
  5428.     //                FROM AvexpressBundle:AveFiles i
  5429.     //                WHERE (i.dateStart <= i.dateEnd)
  5430.     //                  AND (
  5431.     //                      (i.dateStart <= :dateStart AND i.dateEnd >= :dateEnd)
  5432.     //                      OR (i.dateEnd = :dateStart)
  5433.     //                      OR (i.dateEnd > :dateStart AND i.dateEnd <= :dateEnd)
  5434.     //                      OR (i.dateStart = :dateStart)
  5435.     //                      OR (i.dateStart > :dateStart AND i.dateStart <= :dateEnd)
  5436.     //                      OR (i.dateStart = :dateEnd)
  5437.     //                  )
  5438.     //                ORDER BY i.dateStart ASC';
  5439.     //
  5440.     //        $query = $em->createQuery($dql)->setParameters($parameters);
  5441.     //        $avFilesInDates = $query->getResult();
  5442.     //
  5443.     //        return $avFilesInDates;
  5444.     //    }
  5445.     private function sendMailLot($mailAddressFrom$mailArrayTo$mailSubject$mailBody)
  5446.     {
  5447.         $em $this->getDoctrine()->getManager();
  5448.         $agent $em->getRepository(User::class)->findOneByEmail($mailAddressFrom);
  5449.         $replyTo = array();
  5450.         // Verificamos que los correos sean validos
  5451.         foreach ($mailArrayTo as $item) {
  5452.             if (filter_var($itemFILTER_VALIDATE_EMAIL)) {
  5453.                 $replyTo[$item] = $item;
  5454.             }
  5455.         }
  5456.         $agentMail $mailAddressFrom;
  5457.         $mailAgent $agentMail;
  5458.         //Se prepara el correo con los agentes a notificar
  5459.         $firmGmail $agent->getFirmGmail();
  5460.         $data = array('body' => $mailBody'firm' => $firmGmail, );
  5461.         // EJECUTAR ENVIO DE ALERTA PARA EL AGENTE
  5462.         $transporter = new \Swift_SmtpTransport();
  5463.         $transporter->setHost('smtp.gmail.com')
  5464.             ->setEncryption('ssl'//ssl / tls
  5465.             ->setPort(465// 465 / 587
  5466.             ->setUsername('desarrollo@develup.solutions')
  5467.             ->setPassword('utvh hzoi wfdo ztjs');
  5468.         //            ->setPassword('MeDITeRRANeAN_Develup30102023#');
  5469.         $mailer = new \Swift_Mailer($transporter);
  5470.         $message = new \Swift_Message();
  5471.         $message->setSubject($mailSubject)
  5472.             ->setSender($agentMail)
  5473.             ->setFrom(array("desarrollo@develup.solutions" => "System Mante 3.0"))
  5474.             ->setReplyTo($agentMail)
  5475.             ->setTo($replyTo)
  5476.             ->setBody(
  5477.                 $this->renderView(
  5478.                     'mail/structure-mail.html.twig',
  5479.                     array('data' => $data)
  5480.                 ),
  5481.                 'text/html'
  5482.             );
  5483.         $mailer->send($message);
  5484.         return true;
  5485.     }
  5486.     private function notificacionReservasPorCotizar()
  5487.     {
  5488.         // Se buscan las reservas en estado "Iniciado" y se notifica a todos los
  5489.         // agentes de Venues, Solo se notifica 1 vez por dia
  5490.         // Solo se mantendran las alertas de los ultimos 6 meses
  5491.         $em $this->getDoctrine()->getManager();
  5492.         $alertas $em->getRepository(ReservationAlertStarted::class)->findAll();
  5493.         if (!empty($alertas)) {
  5494.             $ultimaAlerta end($alertas);
  5495.         } else {
  5496.             $ultimaAlerta null;
  5497.         }
  5498.         $alertas $em->getRepository(ReservationAlertStarted::class)->findAll();
  5499.         $agentesVenues $em->getRepository(User::class)->findByUserrol(48);
  5500.         $hoy = new DateTime('now');
  5501.         $fechaLimite = new DateTime('now');
  5502.         $fechaLimite->modify('-180 day');
  5503.         if (!empty($ultimaAlerta)) {
  5504.             $mismaFecha $ultimaAlerta->getAlertDate()->format('Ymd') == $hoy->format('Ymd');
  5505.         } else {
  5506.             $mismaFecha false;
  5507.         }
  5508.         if ($mismaFecha) {
  5509.             // No se debe notificar, la ultima alerta es del dia de hoy
  5510.         } else {
  5511.             // Hay que notificar
  5512.             if (empty($agentesVenues)) {
  5513.                 return true;
  5514.             }
  5515.             $mailAddressFrom $agentesVenues[0]->getEmail();
  5516.             $mailArrayTo = array();
  5517.             foreach ($agentesVenues as $agente) {
  5518.                 $mailArrayTo[$agente->getEmail()] = $agente->getEmail();
  5519.             }
  5520.             $mailSubject 'EXPENDIENTES POR COTIZAR';
  5521.             $reservasIniciado $em->getRepository(Reservation::class)->findByStatus('Iniciado');
  5522.             $mailBody null;
  5523.             foreach ($reservasIniciado as $reserva) {
  5524.                 $agenteReserva $em->getRepository(User::class)->findOneById($reserva->getCreatedBy());
  5525.                 $agenteReserva $agenteReserva->getName() . ' ' $agenteReserva->getLastName();
  5526.                 $mailBody $mailBody '<br>Evento: ' $reserva->getId() . '<br>Nombre del Evento: ' $reserva->getTitle() . '<br>Agente: ' $agenteReserva '<br>Enlace al Evento: <a href="https://mantevenues.mante.solutions/venues/editsimple/' $reserva->getId() . '">"IR AL EXPEDIENTE"</a><br><br>';
  5527.             }
  5528.             if (!empty($mailBody)) {
  5529.                 $this->sendMailLot($mailAddressFrom$mailArrayTo$mailSubject$mailBody);
  5530.                 // Creamos la alerta del dia
  5531.                 $alertToday = new ReservationAlertStarted();
  5532.                 $alertToday->setAlertDate($hoy);
  5533.                 $alertToday->setMessage($mailBody);
  5534.                 $em->persist($alertToday);
  5535.                 $em->flush();
  5536.             }
  5537.         }
  5538.         // Eliminamos las alertas con mas de 6 meses de antiguedad
  5539.         foreach ($alertas as $alerta) {
  5540.             if ($alerta->getAlertDate() < $fechaLimite) {
  5541.                 $em->remove($alerta);
  5542.                 $em->flush();
  5543.             }
  5544.         }
  5545.         return true;
  5546.     }
  5547.     private function reordenarSalas($number$idLounge)
  5548.     {
  5549.         // number es el numero de la sala editada
  5550.         $em $this->getDoctrine()->getManager();
  5551.         $number--;
  5552.         $parameters = array('idLounge' => $idLounge'rankLounge' => $number, );
  5553.         $dql 'SELECT i
  5554.                 FROM VenuesBundle:ReservationLoungeDetails i
  5555.                 WHERE  i.rankLounge > :rankLounge AND i.id <> :idLounge';
  5556.         $query $em->createQuery($dql)->setParameters($parameters);
  5557.         $salasParaReordenar $query->getResult();
  5558.         foreach ($salasParaReordenar as $sala) {
  5559.             $sala->setRankLounge(($sala->getRankLounge() + 1));
  5560.             $em->persist($sala);
  5561.             $em->flush();
  5562.         }
  5563.         return empty($resInv);
  5564.     }
  5565.     private function laReservaEsConfirmable($id)
  5566.     {
  5567.         $confirmable false;
  5568.         // Una reserva se puede confirmar solo cuando tiene un depósito realizado
  5569.         $em $this->getDoctrine()->getManager();
  5570.         $depósitos $em->getRepository(ReservationDeposit::class)->findBy(array('reservationId' => $id'isDone' => true));
  5571.         $depósitos true;      // Rafa indica que este requisito no se usara por el momento 24/02/2025
  5572.         // Si la reserva no tiene ninguna sala asignada, no se puede pasar a confirmado
  5573.         $salas $em->getRepository(ReservationLoungeSimple::class)->findBy(array('idReservation' => $id));
  5574.         if (!empty($depósitos) and !empty($salas)) {
  5575.             $confirmable true;
  5576.         }
  5577.         return $confirmable;
  5578.     }
  5579.     private function laReservaEsCotizable($id)
  5580.     {
  5581.         // Una reserva se puede cotizar solo cuando tiene al menos una sala agregada
  5582.         $em $this->getDoctrine()->getManager();
  5583.         $salas $em->getRepository(ReservationLoungeSimple::class)->findBy(array('idReservation' => $id));
  5584.         return true;            // Se pidio que siempre se sincronizara con Av
  5585.     }
  5586.     private function notificacionReservasPendientesDelSegundoDepósito()
  5587.     {
  5588.         // Se buscan las reservas con depósitos y se notifica a todos los
  5589.         // agentes de Venues si no tienen el segundo depósito y faltan 30 días
  5590.         // o menos para el evento, Solo se notifica 1 vez por dia
  5591.         $em $this->getDoctrine()->getManager();
  5592.         $depósitosHechos $em->getRepository(ReservationDeposit::class)->findByIsDone(true);
  5593.         $arrayDepósitos = array();
  5594.         $arrayReservasPemdientesSegunDepósitos = array();
  5595.         $today = new \Datetime('now');
  5596.         $todayPlusMonth = new \Datetime('+ 30 days');
  5597.         // Se agrupan los depósitos por reservas
  5598.         foreach ($depósitosHechos as $item) {
  5599.             $arrayDepósitos[$item->getReservationId()][] = $item;
  5600.         }
  5601.         foreach ($arrayDepósitos as $item) {
  5602.             if (sizeof($item) < 2) {
  5603.                 // Solo nos interesan reservas con un depósito
  5604.                 $reserva $em->getRepository(Reservation::class)->findOneById($item[0]->getReservationId());
  5605.                 if ($reserva->getStatus() == 'Confirmed') {
  5606.                     // Solo nos interesan reservas confirmadas
  5607.                     if (($reserva->getDateStart() < $todayPlusMonth) and ($reserva->getDateStart() > $today)) {
  5608.                         // Solo nos interesan reservas que inician en 30 dias
  5609.                         $arrayReservasPemdientesSegunDepósitos[] = $reserva;
  5610.                     }
  5611.                 }
  5612.             }
  5613.         }
  5614.         $alertas $em->getRepository(ReservationAlertSecondDeposit::class)->findAll();
  5615.         if (!empty($alertas)) {
  5616.             $ultimaAlerta end($alertas);
  5617.         } else {
  5618.             $ultimaAlerta null;
  5619.         }
  5620.         $agentesVenues $em->getRepository(User::class)->findByUserrol(48);
  5621.         $hoy = new DateTime('now');
  5622.         $fechaLimite = new DateTime('now');
  5623.         $fechaLimite->modify('-180 day');
  5624.         if (!empty($ultimaAlerta)) {
  5625.             $mismaFecha $ultimaAlerta->getAlertDate()->format('Ymd') == $hoy->format('Ymd');
  5626.         } else {
  5627.             $mismaFecha false;
  5628.         }
  5629.         if ($mismaFecha) {
  5630.             // No se debe notificar, la ultima alerta es del dia de hoy
  5631.         } else {
  5632.             // Hay que notificar
  5633.             if (empty($agentesVenues)) {
  5634.                 return true;
  5635.             }
  5636.             $mailAddressFrom $agentesVenues[0]->getEmail();
  5637.             $mailArrayTo = array();
  5638.             foreach ($agentesVenues as $agente) {
  5639.                 $mailArrayTo[$agente->getEmail()] = $agente->getEmail();
  5640.             }
  5641.             $mailSubject 'EXPENDIENTES CON DEPÓSITOS PENDIENTES';
  5642.             $reservasIniciado $arrayReservasPemdientesSegunDepósitos;
  5643.             $mailBody null;
  5644.             foreach ($reservasIniciado as $reserva) {
  5645.                 $agenteReserva $em->getRepository(User::class)->findOneById($reserva->getCreatedBy());
  5646.                 $agenteReserva $agenteReserva->getName() . ' ' $agenteReserva->getLastName();
  5647.                 $mailBody $mailBody '<br>Evento: ' $reserva->getId() . '<br>Nombre del Evento: ' $reserva->getTitle() . '<br>Agente: ' $agenteReserva '<br>Enlace al Evento: <a href="https://mantevenues.mante.solutions/venues/editsimple/' $reserva->getId() . '">"IR AL EXPEDIENTE"</a><br><br>';
  5648.             }
  5649.             if (!empty($mailBody)) {
  5650.                 $this->sendMailLot($mailAddressFrom$mailArrayTo$mailSubject$mailBody);
  5651.                 // Creamos la alerta del dia
  5652.                 $alertToday = new ReservationAlertSecondDeposit();
  5653.                 $alertToday->setAlertDate($hoy);
  5654.                 $alertToday->setMessage($mailBody);
  5655.                 $em->persist($alertToday);
  5656.                 $em->flush();
  5657.             }
  5658.         }
  5659.         // Eliminamos las alertas con mas de 6 meses de antiguedad
  5660.         foreach ($alertas as $alerta) {
  5661.             if ($alerta->getAlertDate() < $fechaLimite) {
  5662.                 $em->remove($alerta);
  5663.                 $em->flush();
  5664.             }
  5665.         }
  5666.         return true;
  5667.     }
  5668.     /**
  5669.      * Actualiza las salas y servicios de la reserva.
  5670.      */
  5671.     private function _actualizarSalasYServicios(Reservation $reserva)
  5672.     {
  5673.         $msage $this->session->get('_config')['msage'];
  5674.         // Si no es sucoe, cogemos el IVA del 21% y si lo es, entonces el del 0%
  5675.         if (!$reserva->isSucoe()) {
  5676.             $sageVatRate $this->em->getRepository(SageVatRates::class)->findOneBy(array('sageCode' => '03'));
  5677.         } else {
  5678.             $sageVatRate $this->em->getRepository(SageVatRates::class)->findOneBy(array('sageCode' => '00'));
  5679.         }
  5680.         // Coger todas las salas de la reserva
  5681.         $reservationsLounges $this->em->getRepository(ReservationLoungeSimple::class)->findByIdReservation($reserva->getId());
  5682.         foreach ($reservationsLounges as $reservationsLounge) {
  5683.             // Si el módulo de Sage está activo, asignar el artículo correspondientec
  5684.             if ($msage) {
  5685.                 $sageArticle $this->em->getRepository(SageArticle::class)->findOneBy(array('vatType' => $sageVatRate'name' => $reservationsLounge->getLoungeName()));
  5686.                 if (!$sageArticle) {
  5687.                     throw new \Exception('No se ha encontrado el artículo Sage para la sala: ' $reservationsLounge->getLoungeName());
  5688.                 }
  5689.                 $reservationsLounge->setSageArticle($sageArticle);
  5690.             }
  5691.             $reservationsLounge->setSageIva($sageVatRate);
  5692.             $this->em->persist($reservationsLounge);
  5693.         }
  5694.         // Coger todos los servicios de la reserva
  5695.         $services $this->em->getRepository(ReservationService::class)->findByReservationId($reserva->getId());
  5696.         foreach ($services as $service) {
  5697.             // Si el módulo de Sage está activo, asignar el artículo correspondiente
  5698.             if ($msage) {
  5699.                 $sageArticle $this->em->getRepository(SageArticle::class)->findOneBy(array('vatType' => $sageVatRate'name' => $service->getServiceCatName()));
  5700.                 if (!$sageArticle) {
  5701.                     throw new \Exception('No se ha encontrado el artículo Sage para el servicio: ' $service->getServiceCatName());
  5702.                 }
  5703.                 $service->setSageArticle($sageArticle);
  5704.             }
  5705.             $service->setSageIva($sageVatRate);
  5706.             $this->em->persist($service);
  5707.         }
  5708.         // Persistimos los cambios
  5709.         $this->em->flush();
  5710.     }
  5711.     /**
  5712.      * Procesa los lounges simples para agruparlos por día y generar el array para el archivo.
  5713.      */
  5714.     private function processLounges(array $reservationsLoungesSimple): array
  5715.     {
  5716.         $arrayLoungesByDay = [];
  5717.         $arrayLoungesInFile = [];
  5718.         foreach ($reservationsLoungesSimple as $item) {
  5719.             $dateStart $item->getDateStart()->format('Ymd');
  5720.             $rank $item->getRankQuote();
  5721.             $arrayLoungesByDay[$rank][$dateStart][] = $item;
  5722.             ksort($arrayLoungesByDay[$rank]);
  5723.             // Ignorar montajes y desmontajes. Ignorar los montajes y desmontajes, parece ser un error, genera un arraglo vacio (arrayLoungesInFile) en editSimple
  5724. //            if (empty($item->getType())) {
  5725.             // NOTA: $dataContract no existía en el código original antes de este punto.
  5726.             // Se asume vacío para evitar error de variable indefinida.
  5727.             $fullContract '';
  5728.             $arrayLoungesInFile[$rank][$item->getIdLounge()] = [
  5729.                 'rankQuote' => $rank,
  5730.                 'idLounge' => $item->getIdLounge(),
  5731.                 'loungeName' => $item->getLoungeName(),
  5732.                 'loungeImportantDescription' => $item->getImportantDescription(),
  5733.                 'loungeImportantDescGeneralText' => $item->getImportantDescGeneralText(),
  5734.                 'loungeImportantDescSchedules' => $item->getImportantDescSchedules(),
  5735.                 'loungeImportantDescParking' => $item->getImportantDescParking(),
  5736.                 'loungeDocFullContract' => $fullContract,
  5737.                 'language' => $item->getLanguage(),
  5738.             ];
  5739.             //            }
  5740.         }
  5741.         return [
  5742.             'arrayLoungesByDay' => $arrayLoungesByDay,
  5743.             'arrayLoungesInFile' => $arrayLoungesInFile
  5744.         ];
  5745.     }
  5746.     /**
  5747.      * Obtiene proveedores de Catering con la lógica de ordenamiento específica.
  5748.      */
  5749.     private function getCateringSuppliers(EntityManagerInterface $em): array
  5750.     {
  5751.         $caterings $em->createQueryBuilder()
  5752.             ->select('p')
  5753.             ->from(Supplier::class, 'p')
  5754.             ->where('p.tags LIKE :tags')
  5755.             ->andWhere('p.company <> :company')
  5756.             ->orderBy('p.company''ASC')
  5757.             ->setParameters([
  5758.                 'tags' => '%CATERING%'// Aseguramos el wildcard si es necesario o se mantiene estricto según lógica original
  5759.                 'company' => 'HIGO & TRIGO, S.L.'
  5760.             ])
  5761.             ->getQuery()
  5762.             ->getResult();
  5763.         // Agregamos Higo & Trigo al principio (Hardcoded ID según código original)
  5764.         $catHigoTrigo $em->getRepository(Supplier::class)->find(4765);
  5765.         if ($catHigoTrigo) {
  5766.             array_unshift($caterings$catHigoTrigo);
  5767.         }
  5768.         return $caterings;
  5769.     }
  5770.     /**
  5771.      * Lógica optimizada para facturas. Evita consultas dentro del bucle.
  5772.      */
  5773.     private function calculateInvoicesData(int $reservationIdReservation $reserva, ?Client $clientEntityManagerInterface $em): array
  5774.     {
  5775.         $invoices $em->getRepository(ReservationInvoice::class)->findByReservationId($reservationId);
  5776.         $invoicesRec $em->getRepository(ReservationInvoiceRec::class)->findByReservationId($reservationId);
  5777.         // Merge de facturas normales y rectificativas
  5778.         $allInvoicesEntities array_merge($invoices$invoicesRec);
  5779.         // --- INICIO PRE-CARGA PARA RESOLVER N+1 ---
  5780.         $depositInvoiceIds = [];
  5781.         $invoiceToRecIds = [];
  5782.         foreach ($allInvoicesEntities as $item) {
  5783.             if ($item->getType() === 'Invoice Deposit') {
  5784.                 $depositInvoiceIds[] = $item->getId();
  5785.             } elseif (in_array($item->getType(), ['Invoice Rec''Invoice Deposit Rec'], true) && $item->getId()) {
  5786.                 $invoiceToRecIds[] = $item->getInvoiceToRec();
  5787.             }
  5788.         }
  5789.         $depositInvoiceIds array_filter(array_unique($depositInvoiceIds));
  5790.         $invoiceToRecIds array_filter(array_unique($invoiceToRecIds));
  5791.         $paymentItemsByInvoiceId = [];
  5792.         $invoiceElementItemsByPaymentId = [];
  5793.         $invoicesById = [];
  5794.         if (!empty($depositInvoiceIds)) {
  5795.             $qbPayments $em->createQueryBuilder();
  5796.             $paymentItems $qbPayments->select('p')
  5797.                 ->from(ReservationPaymentsClient::class, 'p')
  5798.                 ->where($qbPayments->expr()->in('p.invoiceId'':invoiceIds'))
  5799.                 ->setParameter('invoiceIds'$depositInvoiceIds)
  5800.                 ->getQuery()
  5801.                 ->getResult();
  5802.             $paymentIds = [];
  5803.             foreach ($paymentItems as $paymentItem) {
  5804.                 // Emulamos el comportamiento de findOneBy asignando solo la primera coincidencia
  5805.                 if (!isset($paymentItemsByInvoiceId[$paymentItem->getInvoiceId()])) {
  5806.                     $paymentItemsByInvoiceId[$paymentItem->getInvoiceId()] = $paymentItem;
  5807.                     $paymentIds[] = $paymentItem->getId();
  5808.                 }
  5809.             }
  5810.             $paymentIds array_filter(array_unique($paymentIds));
  5811.             if (!empty($paymentIds)) {
  5812.                 $qbItems $em->createQueryBuilder();
  5813.                 $invoiceElementItems $qbItems->select('i')
  5814.                     ->from(ReservationInvoiceItems::class, 'i')
  5815.                     ->where($qbItems->expr()->in('i.payControlId'':paymentIds'))
  5816.                     ->setParameter('paymentIds'$paymentIds)
  5817.                     ->getQuery()
  5818.                     ->getResult();
  5819.                 $invoiceIdsToFetch = [];
  5820.                 foreach ($invoiceElementItems as $invoiceElementItem) {
  5821.                     if (!isset($invoiceElementItemsByPaymentId[$invoiceElementItem->getPayControlId()])) {
  5822.                         $invoiceElementItemsByPaymentId[$invoiceElementItem->getPayControlId()] = $invoiceElementItem;
  5823.                         $invoiceIdsToFetch[] = $invoiceElementItem->getInvoiceId();
  5824.                     }
  5825.                 }
  5826.                 $invoiceIdsToFetch array_filter(array_unique($invoiceIdsToFetch));
  5827.                 if (!empty($invoiceIdsToFetch)) {
  5828.                     $qbInvoices $em->createQueryBuilder();
  5829.                     $fetchedInvoices $qbInvoices->select('inv')
  5830.                         ->from(ReservationInvoice::class, 'inv')
  5831.                         ->where($qbInvoices->expr()->in('inv.id'':invoiceIds'))
  5832.                         ->setParameter('invoiceIds'$invoiceIdsToFetch)
  5833.                         ->getQuery()
  5834.                         ->getResult();
  5835.                     foreach ($fetchedInvoices as $inv) {
  5836.                         $invoicesById[$inv->getId()] = $inv;
  5837.                     }
  5838.                 }
  5839.             }
  5840.         }
  5841.         if (!empty($invoiceToRecIds)) {
  5842.             $qbInvoicesRec $em->createQueryBuilder();
  5843.             $fetchedInvoicesToRec $qbInvoicesRec->select('inv')
  5844.                 ->from(ReservationInvoice::class, 'inv')
  5845.                 ->where($qbInvoicesRec->expr()->in('inv.id'':invoiceToRecIds'))
  5846.                 ->setParameter('invoiceToRecIds'$invoiceToRecIds)
  5847.                 ->getQuery()
  5848.                 ->getResult();
  5849.             foreach ($fetchedInvoicesToRec as $inv) {
  5850.                 $invoicesById[$inv->getId()] = $inv;
  5851.             }
  5852.         }
  5853.         // --- FIN PRE-CARGA ---
  5854.         $sumNet 0.0;
  5855.         $sumVat 0.0;
  5856.         $sumTotal 0.0;
  5857.         $allInvoicedData = [];
  5858.         foreach ($allInvoicesEntities as $item) {
  5859.             // Lógica de Balance para Invoice Deposit utilizando datos cacheados
  5860.             if ($item->getType() === 'Invoice Deposit') {
  5861.                 $paymentItem $paymentItemsByInvoiceId[$item->getId()] ?? null;
  5862.                 if ($paymentItem) {
  5863.                     $invoiceElementItem $invoiceElementItemsByPaymentId[$paymentItem->getId()] ?? null;
  5864.                     if ($invoiceElementItem) {
  5865.                         $invoiceOfItem $invoicesById[$invoiceElementItem->getInvoiceId()] ?? null;
  5866.                         if ($invoiceOfItem?->getType() === 'Invoice') {
  5867.                             $item->setBalance(0);
  5868.                         }
  5869.                     }
  5870.                 }
  5871.             }
  5872.             // Factura rectificativa relacionada utilizando datos cacheados
  5873.             $invoiceToRec null;
  5874.             if (in_array($item->getType(), ['Invoice Rec''Invoice Deposit Rec'], true) && $item->getId()) {
  5875.                 $invoiceToRec $invoicesById[$item->getInvoiceToRec()] ?? null;
  5876.             }
  5877.             $clientInvoice = [
  5878.                 'name' => $item->getClientName(),
  5879.                 'address' => $item->getClientAddress(),
  5880.                 'clientDocument' => $item->getClientDocument(),
  5881.             ];
  5882.             $allInvoicedData[] = [
  5883.                 'dateAt' => $item->getDateAt(),
  5884.                 'type' => $item->getType(),
  5885.                 'id' => $item->getId(),
  5886.                 'invoiceToRec' => $invoiceToRec,
  5887.                 'clientType' => $item->getClientType(),
  5888.                 'reservationId' => $item->getReservationId(),
  5889.                 'number' => $item->getNumber(),
  5890.                 'totalNet' => $item->getTotalNet(),
  5891.                 'total' => $item->getTotal(),
  5892.                 'vat' => $item->getVat(),
  5893.                 'balance' => $item->getBalance(),
  5894.                 'client' => $clientInvoice,  // Reutilizamos el cliente ya cargado
  5895.                 'reservation' => $reserva// Reutilizamos la reserva ya cargada
  5896.             ];
  5897.             // Cálculos acumulativos
  5898.             $isDeposit in_array($item->getType(), ['Invoice Deposit''Invoice Deposit Rec'], true);
  5899.             if (!$isDeposit) {
  5900.                 // Las facturas rectificativas suelen tener valores negativos en DB, por lo que sumar es correcto.
  5901.                 $sumNet += $item->getTotalNet();
  5902.                 $sumVat += $item->getVat();
  5903.                 $sumTotal += $item->getTotal();
  5904.             }
  5905.             // Si es depósito, se suma 0 (no computa), por lo que no hacemos nada.
  5906.         }
  5907.         return [
  5908.             'allInvoiced' => $allInvoicedData,
  5909.             'resultados' => [
  5910.                 'totalNeto' => $sumNet,
  5911.                 'vat' => $sumVat,
  5912.                 'total' => $sumTotal,
  5913.             ]
  5914.         ];
  5915.     }
  5916.     /**
  5917.      * Filtra pagos no facturados.
  5918.      */
  5919.     private function filterUninvoicedPayments(int $reservationId, array $paymentsEntityManagerInterface $em): array
  5920.     {
  5921.         $notInvoiced = [];
  5922.         foreach ($payments as $payment) {
  5923.             // Esto sigue siendo una consulta en bucle, pero es difícil de optimizar sin cambiar la lógica de InvoiceItems.
  5924.             // Se mantiene por seguridad "sin inventar", pero idealmente InvoiceItems debería cargarse en bloque.
  5925.             $isInvoiced $em->getRepository(ReservationInvoiceItems::class)->findBy([
  5926.                 'reservationId' => $reservationId,
  5927.                 'payControlId' => $payment->getId()
  5928.             ]);
  5929.             if (empty($isInvoiced)) {
  5930.                 $notInvoiced[] = $payment;
  5931.             }
  5932.         }
  5933.         return $notInvoiced;
  5934.     }
  5935.     /**
  5936.      * Obtiene usuarios activos y añade freelancers.
  5937.      */
  5938.     private function getAllActiveUsersAndFreelancers(EntityManagerInterface $em): array
  5939.     {
  5940.         $users $em->createQueryBuilder()
  5941.             ->select('u')
  5942.             ->from(User::class, 'u')
  5943.             ->where('u.status = :status')
  5944.             ->andWhere('u.team = :team')
  5945.             ->orderBy('u.name''ASC')
  5946.             ->setParameter('status'1)
  5947.             ->setParameter('team'16)
  5948.             ->getQuery()
  5949.             ->getResult();
  5950.         $freeLances = []; // $em->getRepository(ExternalUser::class)->findAll();
  5951.         // Lcl Freelance logic removed
  5952.         return $users;
  5953.     }
  5954.     /**
  5955.      * Calcula la fecha de la próxima alerta de correo.
  5956.      */
  5957.     private function getNextMailAlertDate(int $reservationIdEntityManagerInterface $em): ?\DateTimeInterface
  5958.     {
  5959.         $alert $em->getRepository(ReservationMailAlertClient::class)->findOneByReservationId($reservationId);
  5960.         if (!$alert) {
  5961.             return null;
  5962.         }
  5963.         if (!$alert->getAlertSended()) {
  5964.             return $alert->getAlertDateTime();
  5965.         }
  5966.         if (!$alert->getCancelSended()) {
  5967.             return $alert->getCancelDateTime();
  5968.         }
  5969.         return null;
  5970.     }
  5971.     /**
  5972.      * Obtiene depósitos y calcula sumas por proforma.
  5973.      */
  5974.     private function getDepositsAndProformas(int $reservationIdEntityManagerInterface $em): array
  5975.     {
  5976.         $depositsAll $em->getRepository(ReservationDeposit::class)->findByReservationId($reservationId);
  5977.         $proformaIds = [];
  5978.         $proformas = [];
  5979.         foreach ($depositsAll as $d) {
  5980.             $p $d->getProformaDeposit();
  5981.             if ($p && !$p->getInvoice()) {
  5982.                 $pid $p->getId();
  5983.                 $proformaIds[$pid] = true;
  5984.                 $proformas[$pid] = $p;
  5985.             }
  5986.         }
  5987.         $ids array_keys($proformaIds);
  5988.         $sums = [];
  5989.         if (!empty($ids)) {
  5990.             // Asumiendo que sumsByProformaIds maneja un array vacío correctamente, si no, el if protege.
  5991.             $sums $em->getRepository(ReservationDeposit::class)->sumsByProformaIds($ids);
  5992.         }
  5993.         return [
  5994.             'depositsAll' => $depositsAll,
  5995.             'sumsByProforma' => $sums,
  5996.             'proformas' => $proformas
  5997.         ];
  5998.     }
  5999.     /**
  6000.      * Helper para parsear los formatos de hora manuales del input.
  6001.      * Devuelve array con 'hour', 'min' y 'formatted' (HH:mm).
  6002.      */
  6003.     /**
  6004.      * Resuelve el nombre del servicio y el ID del asistente.
  6005.      */
  6006.     private function resolveAgentAndName(ReservationService $service, array $dataEntityManagerInterface $em): void
  6007.     {
  6008.         // ID 15 parece ser "Personal" o similar en tu lógica de negocio
  6009.         if ($service->getServiceCatId() == 15 && array_key_exists('agent'$data)) {
  6010.             $agentId = (int) $data['agent'];
  6011.             if ($agentId 0) {
  6012.                 $user $em->getRepository(User::class)->find($agentId);
  6013.                 if ($user) {
  6014.                     $service->setName(trim($user->getName() . ' ' $user->getLastName()));
  6015.                     $service->setAssistantId($agentId);
  6016.                     return;
  6017.                 }
  6018.             }
  6019.             // Fallback si viene 'agent' pero es 0 o no se encuentra usuario
  6020.             $service->setName($data['name'] ?? null);
  6021.             $service->setAssistantId(null);
  6022.         } else {
  6023.             // No es categoría 15 o no viene agente
  6024.             $service->setName($data['name'] ?? null);
  6025.         }
  6026.     }
  6027.     /**
  6028.      * Parsea valores monetarios manejando comas y puntos.
  6029.      */
  6030.     private function parseCurrency(?string $inputfloat $fallbackbool $onlyComma false): float
  6031.     {
  6032.         if ($input === null) {
  6033.             return 0.0;
  6034.         }
  6035.         if ($onlyComma) {
  6036.             // Caso especial para comisiones: solo reemplaza coma por punto
  6037.             $val str_replace(',''.'$input);
  6038.         } else {
  6039.             // Caso general: elimina puntos (miles), cambia coma a punto (decimal)
  6040.             $val str_replace(['.'','], ['''.'], $input);
  6041.         }
  6042.         return is_numeric($val) ? (float) $val $fallback;
  6043.     }
  6044.     /**
  6045.      * Maneja la lógica compleja de sincronización para Catering y AV.
  6046.      */
  6047.     private function handleSynchronization(
  6048.         Reservation $reserva,
  6049.         ReservationService $service,
  6050.         Supplier $supplier,
  6051.         bool $mcatering,
  6052.         bool $mav,
  6053.         array $htFiles// Array de HtFile encontrados
  6054.         array $aveFiles// Array de AveFiles encontrados
  6055.         $user,
  6056.         SyncronizationsCateringService $cateringService,
  6057.         SyncronizationsAVService $avService,
  6058.         EntityManagerInterface $em,
  6059.         AppConfigManager $configManager
  6060.     ): void {
  6061.         $companyName $supplier->getCompany();
  6062.         if (!$companyName) {
  6063.             return;
  6064.         }
  6065.         $mode $configManager->getSettings()->workflow->reservationMode;
  6066.         // --- CATERING ---
  6067.         if ($mcatering) {
  6068.             // Verificamos si este proveedor es de tipo Catering buscando en SettingsCompany
  6069.             // Optimización: Usamos una consulta simple, idealmente esto se cachearía a nivel de clase si son pocos settings.
  6070.             $isCatering $em->getRepository(SettingsCompany::class)->findOneBy([
  6071.                 'businessType' => BusinessTypeSettingsCompanyConstants::CATERING,
  6072.                 'company' => $companyName
  6073.             ]);
  6074.             if ($isCatering) {
  6075.                 $dto = new SyncronizationsCateringDTO();
  6076.                 $dto->setDateStart($service->getDateInAt());
  6077.                 $dto->setDateEnd($service->getDateOutAt());
  6078.                 $dto->setReservation($reserva);
  6079.                 if (empty($htFiles)) {
  6080.                     // Crear expediente HT solo si NO estamos en modo Automático (que ya los crea al iniciar)
  6081.                     // O si estamos en modo Clásico (implícito)
  6082.                     if ($mode !== ReservationWorkflowMode::ON_RESERVATION_CREATION) {
  6083.                         $dto->setClient($reserva->getClient());
  6084.                         $dto->setClientContName($reserva->getClientContact());
  6085.                         $dto->setUser($user);
  6086.                         $dto->setTitle($reserva->getTitle());
  6087.                         $dto->setPax($reserva->getPax());
  6088.                         $dto->setDescription($reserva->getDescription());
  6089.                         $dto->setContactUnregistered($reserva->getContactUnregistered());
  6090.                         $dto->setNameContactUnregistered($reserva->getNameContactUnregistered());
  6091.                         $dto->setPhoneContactUnregistered($reserva->getPhoneContactUnregistered());
  6092.                         $cateringService->syncVenues($dto);
  6093.                     }
  6094.                 } else {
  6095.                     // Actualizar fechas
  6096.                     $cateringService->updateCateringDate($dto);
  6097.                 }
  6098.             }
  6099.         }
  6100.         // --- AUDIOVISUAL ---
  6101.         if ($mav) {
  6102.             $isAV $em->getRepository(SettingsCompany::class)->findOneBy([
  6103.                 'businessType' => BusinessTypeSettingsCompanyConstants::AUDIOVISUAL,
  6104.                 'company' => $companyName
  6105.             ]);
  6106.             if ($isAV) {
  6107.                 $dto = new SyncronizationsAVDTO();
  6108.                 $dto->setDateStart($service->getDateInAt());
  6109.                 $dto->setDateEnd($service->getDateOutAt());
  6110.                 $dto->setReservation($reserva);
  6111.                 if (empty($aveFiles)) {
  6112.                     // Crear expediente AV - Misma lógica
  6113.                     if ($mode !== ReservationWorkflowMode::ON_RESERVATION_CREATION) {
  6114.                         $dto->setClient($reserva->getClient());
  6115.                         $dto->setUser($user);
  6116.                         $dto->setTitle($reserva->getTitle());
  6117.                         $dto->setPax($reserva->getPax());
  6118.                         $dto->setDescription($reserva->getDescription());
  6119.                         $avService->syncVenues($dto);
  6120.                     }
  6121.                 } else {
  6122.                     // Actualizar fechas
  6123.                     $avService->updateAVDate($dto);
  6124.                 }
  6125.             }
  6126.         }
  6127.     }
  6128.     private function handleUnregisteredContact($formReservation $reservaUser $userEntityManagerInterface $em): void
  6129.     {
  6130.         // 1. Ahora leemos los datos directamente de la entidad Reserva
  6131.         // (Como quitamos mapped=>false, el form ya los ha puesto aquí)
  6132.         $email $reserva->getContactUnregistered();
  6133.         $name $reserva->getNameContactUnregistered();
  6134.         $phone $reserva->getPhoneContactUnregistered();
  6135.         // Obtener el objeto Cliente del formulario
  6136.         $client $form->get('client')->getData();
  6137.         $contactHandled false;
  6138.         // 2. Si hay datos escritos a mano, tienen PRIORIDAD
  6139.         if ($client && !empty($email) && !empty($name)) {
  6140.             // Verificamos si ya existe ese email en la tabla de contactos
  6141.             $existClientContact $em->getRepository(ClientContact::class)->findOneBy(['email' => $email]);
  6142.             if ($existClientContact) {
  6143.                 // CASO A: Ya existía -> Solo vinculamos su ID
  6144.                 $reserva->setClientContact($existClientContact->getId());
  6145.             } else {
  6146.                 // CASO B: No existía -> Lo creamos en la tabla de contactos para el futuro
  6147.                 $newContact = new ClientContact();
  6148.                 $newContact->setClientId($client->getId());
  6149.                 $newContact->setTypeclient('Business Travel');
  6150.                 $newContact->setAssignedAgent($user->getId());
  6151.                 $newContact->setName($name);
  6152.                 $newContact->setLastName('');
  6153.                 $newContact->setPosition(''); // Evitamos error SQL "position cannot be null"
  6154.                 $newContact->setSituation('CLIENT');
  6155.                 $newContact->setEmail($email);
  6156.                 $newContact->setPhone($phone ?? '');
  6157.                 // Auditoría
  6158.                 $newContact->setCreatedId($user->getId());
  6159.                 $newContact->setUpdatedId($user->getId());
  6160.                 if (method_exists($newContact'setCreated')) {
  6161.                     $newContact->setCreated(new \DateTime());
  6162.                 }
  6163.                 $em->persist($newContact);
  6164.                 $em->flush(); // Guardamos para obtener el ID
  6165.                 // Vinculamos el nuevo ID a la reserva
  6166.                 $reserva->setClientContact($newContact->getId());
  6167.             }
  6168.             $contactHandled true;
  6169.         }
  6170.         // 3. Si NO escribió nada a mano, miramos el desplegable (campo oculto clientContact)
  6171.         if (!$contactHandled) {
  6172.             $manualContactId $form->get('clientContact')->getData();
  6173.             // Si viene un ID válido del selector
  6174.             if (!empty($manualContactId) && $manualContactId !== '0') {
  6175.                 $reserva->setClientContact((int) $manualContactId);
  6176.             }
  6177.         }
  6178.     }
  6179.     /**
  6180.      * Lógica específica cuando el estado es "Bloqueo"
  6181.      */
  6182.     private function handleBlockStatus($formReservation $reservaUser $userEntityManagerInterface $em): void
  6183.     {
  6184.         $status $reserva->getStatus();
  6185.         if ($status === 'Bloqueo') {
  6186.             // 1. Calcular fecha límite si no existe
  6187.             if (!$reserva->getDays()) {
  6188.                 $daysBlock $reserva->getDaysBlock() ?? 7// Valor por defecto
  6189.                 $dateLimit = (new \DateTime())->modify("+$daysBlock days");
  6190.                 $reserva->setDays($dateLimit);
  6191.             }
  6192.             // 2. Envío de Correos (Simplificado manteniendo tu lógica)
  6193.             // NOTA: Aquí deberías refactorizar para usar un Servicio de Mailing, 
  6194.             // pero mantengo la llamada a $this->sendMail() y lógica local por restricción del prompt.
  6195.             if ($reserva->getClient() || $reserva->getClientContact() || $form->get('contactUnregistered')->getData()) {
  6196.                 // ... Tu lógica de envío de correo de bloqueo ...
  6197.                 // $this->sendMail(...) 
  6198.             }
  6199.             // 3. Modificar fecha de notificación (Next Mail Alert)
  6200.             $newDateAlert $form->get('dateNextMailAlert')->getData(); // Campo mapped => false o true en tu type nuevo
  6201.             if ($newDateAlert && $newDateAlert > new \DateTime('now')) {
  6202.                 $alertRepo $em->getRepository(ReservationMailAlertClient::class);
  6203.                 $nextAlert $alertRepo->findOneByReservationId($reserva->getId());
  6204.                 if ($nextAlert) {
  6205.                     $newAlertDt = clone $newDateAlert;
  6206.                     $newAlertDt->setTime(150);
  6207.                     if ($nextAlert->getAlertSended() == 0) {
  6208.                         $newCancelDt = (clone $newAlertDt)->modify('+2 days');
  6209.                         $nextAlert->setAlertDateTime($newAlertDt);
  6210.                         $nextAlert->setCancelDateTime($newCancelDt);
  6211.                     } else {
  6212.                         // Solo modificar cancelación
  6213.                         $nextAlert->setCancelDateTime($newAlertDt);
  6214.                     }
  6215.                     $em->persist($nextAlert);
  6216.                 }
  6217.             }
  6218.         } else {
  6219.             // Si NO es bloqueo, limpiar la fecha límite
  6220.             if ($reserva->getDays()) {
  6221.                 $reserva->setDays(null);
  6222.             }
  6223.         }
  6224.     }
  6225.     /**
  6226.      * Maneja el envío de correo de cancelación si existía una alerta previa
  6227.      */
  6228.     private function handleCancellationAlert(int $idReservation $reservaEntityManagerInterface $em): void
  6229.     {
  6230.         $alert $em->getRepository(ReservationMailAlertClient::class)->findOneByReservationId($id);
  6231.         if ($alert) {
  6232.             $agent $em->getRepository(User::class)->find($alert->getAgentId());
  6233.             // Configurar datos del correo
  6234.             $mailTo $alert->getClientMail();
  6235.             $mailFrom $alert->getAgentMail();
  6236.             $subject 'Notificación de Bloqueo - Reserva de espacio en Venues';
  6237.             $body 'Estimado cliente,<br><br>Nos ponemos en contacto con usted para informarle de que su reserva ha sido cancelada.<br><br>Reserva: ' $reserva->getId() . ' - ' $reserva->getTitle();
  6238.             // Llamada a tu método existente
  6239.             // $this->sendMail($mailFrom, $mailTo, $subject, $body);
  6240.             // Actualizar la entidad de alerta
  6241.             $alert->setOldReservationId($alert->getReservationId());
  6242.             $alert->setReservationId(0);
  6243.             $alert->setCancelSended(1);
  6244.             $em->persist($alert);
  6245.         }
  6246.     }
  6247.     /**
  6248.      * Recalcula fecha inicio y fin basado en las salas (Lounges)
  6249.      */
  6250.     /**
  6251.      * Gestiona la creación o actualización del DocContract basado en el modelo seleccionado.
  6252.      */
  6253.     private function handleContractLogic(
  6254.         ?DocContractModel $selectedModel,
  6255.         ?DocContract $currentDocContract,
  6256.         Reservation $reserva,
  6257.         User $user,
  6258.         EntityManagerInterface $em
  6259.     ): void {
  6260.         // Si no se seleccionó nada, no hacemos nada (o podrías decidir borrar el contrato si existía)
  6261.         if (!$selectedModel) {
  6262.             return;
  6263.         }
  6264.         // Verificamos si ha cambiado el modelo o si no existía contrato previo
  6265.         $modelHasChanged = !$currentDocContract || ($currentDocContract->getModel()?->getId() !== $selectedModel->getId());
  6266.         if ($modelHasChanged) {
  6267.             // Opción A: Actualizar el contrato existente (para mantener el ID y no llenar la BD de basura)
  6268.             // Opción B: Crear uno nuevo siempre (si necesitas histórico estricto). 
  6269.             // Usaremos Opción A (Actualizar o Crear si no existe) por eficiencia.
  6270.             if (!$currentDocContract) {
  6271.                 $currentDocContract = new DocContract();
  6272.                 $currentDocContract->setReservation($reserva);
  6273.                 $currentDocContract->setCreatedAt(new \DateTime());
  6274.                 $currentDocContract->setCreatedId($user->getId());
  6275.             }
  6276.             // Actualizamos los datos con la nueva plantilla
  6277.             $currentDocContract->setModel($selectedModel);
  6278.             // Copiamos el texto de la plantilla al contrato real
  6279.             // Ajusta 'getContractualDocument()' al método real de tu entidad DocContractModel
  6280.             if (method_exists($selectedModel'getContractualDocument')) {
  6281.                 $currentDocContract->setContractualDocument($selectedModel->getContractualDocument());
  6282.             }
  6283.             // Datos de auditoría / actualización
  6284.             $currentDocContract->setUpdatedAt(new \DateTime());
  6285.             $currentDocContract->setUpdatedId($user->getId());
  6286.             $currentDocContract->setDateAt(new \DateTime()); // Fecha del contrato = ahora
  6287.             $em->persist($currentDocContract);
  6288.         }
  6289.     }
  6290. }