src/MDS/ApiBundle/Controller/ApiProposalsClientController.php line 32

Open in your IDE?
  1. <?php
  2. declare(strict_types=1);
  3. namespace App\MDS\ApiBundle\Controller;
  4. use App\Entity\ClientContact;
  5. use App\MDS\VenuesBundle\Entity\Reservation;
  6. use App\MDS\VenuesBundle\Entity\ReservationLoungeDetails;
  7. use App\MDS\VenuesBundle\Entity\ReservationLoungeDescription;
  8. use App\MDS\VenuesBundle\Entity\ReservationLoungeSimple;
  9. use App\MDS\VenuesBundle\Entity\ReservationLoungePicture;
  10. use App\MDS\VenuesBundle\Entity\ReservationService;
  11. use App\MDS\AvexpressBundle\Entity\AvePackageTemplate;
  12. use App\MDS\AvexpressBundle\Entity\AvePackageTemplateItems;
  13. use Doctrine\ORM\EntityManagerInterface;
  14. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  15. use Symfony\Component\HttpFoundation\JsonResponse;
  16. use Symfony\Component\HttpFoundation\Request;
  17. use Symfony\Component\Routing\Annotation\Route;
  18. class ApiProposalsClientController extends AbstractController
  19. {
  20.     // PHP 8.1: Promoción de propiedades en constructor y readonly para servicios inmutables
  21.     public function __construct(
  22.         private readonly EntityManagerInterface $em
  23.     ) {}
  24.     /**
  25.      * @Route("/api/client/proposal/{token}", name="generate_token", methods={"GET"})
  26.      */
  27.     public function generateToken(Request $requeststring $token): JsonResponse
  28.     {
  29.         // Obtener reserva asociada al token
  30.         /** @var Reservation|null $reservation */
  31.         $reservation $this->em->getRepository(Reservation::class)->findOneBy(['token' => $token]);
  32.         if (!$reservation) {
  33.             throw $this->createNotFoundException('No se encontró ninguna reserva para el token proporcionado.');
  34.         }
  35.         $data = [
  36.             'reservation' => $this->formatReservation($reservation),
  37.             'options' => [],
  38.             'reservationService' => [],
  39.         ];
  40.         // --- CARGA DE PAQUETES OPTIMIZADA (Array de colecciones) ---
  41.         $avPackages $this->em->getRepository(AvePackageTemplate::class)->findAll();
  42.         $packagesByLounge = [];
  43.         foreach ($avPackages as $pkg) {
  44.             if (!$pkg->getLounges()->isInitialized()) {
  45.                 $pkg->getLounges()->initialize();
  46.             }
  47.             
  48.             $formattedPackage $this->formatPackageTemplate($pkg);
  49.             
  50.             foreach ($pkg->getLounges() as $lounge) {
  51.                 $loungeId $lounge->getId();
  52.                 if (!isset($packagesByLounge[$loungeId])) {
  53.                     $packagesByLounge[$loungeId] = [];
  54.                 }
  55.                 // Corregido: acumulamos en un array para permitir múltiples paquetes por salón
  56.                 $packagesByLounge[$loungeId][] = $formattedPackage;
  57.             }
  58.         }
  59.         // Agregar servicios de la reserva
  60.         $reservationServices $this->em->getRepository(ReservationService::class)->findBy(['reservationId' => $reservation->getId()]);
  61.         foreach ($reservationServices as $service) {
  62.             $units = ($service->getUnits() > 0) ? $service->getUnits() : 1;
  63.             $pax = ($service->getPax() > 0) ? $service->getPax() : 1;
  64.             $priceOver $service->getOver();
  65.             $price $service->getPrice();
  66.             $commission $service->getCommission();
  67.             $iva $service->getSageIva()?->getIva() ?? 0// Uso de operador nullsafe de PHP 8.1
  68.             $totalPrice = ($price $pax $units);
  69.             $priceCommission $totalPrice * ($commission 100);
  70.             $totalConComision $totalPrice $priceCommission;
  71.             $dateInAt $service->getDateInAt();
  72.             $dateOutAt $service->getDateOutAt();
  73.             $days 1;
  74.             if ($dateInAt && $dateOutAt) {
  75.                 $interval $dateInAt->diff($dateOutAt);
  76.                 $days max(1, (int) $interval->days 1);
  77.             }
  78.             
  79.             $totalConDays $totalConComision $days;
  80.             $totalConOver $totalConDays $priceOver;
  81.             $priceIva $totalConOver * ($iva 100);
  82.             $totalPriceCalculated $totalConOver $priceIva;
  83.             $data['reservationService'][] = [
  84.                 'id' => $service->getId(),
  85.                 'reservationId' => $service->getReservationId(),
  86.                 'supplierId' => $service->getSupplierId(),
  87.                 'serviceId' => $service->getServiceId(),
  88.                 'serviceCatId' => $service->getServiceCatId(),
  89.                 'serviceCatName' => $service->getServiceCatName(),
  90.                 'name' => $service->getName(),
  91.                 'price' => $service->getPrice(),
  92.                 'currency' => $service->getCurrency(),
  93.                 'units' => $units,
  94.                 'opCommission' => $service->getOpCommission(),
  95.                 'commission' => $service->getCommission(),
  96.                 'opOver' => $service->getOpOver(),
  97.                 'priceOver' => $priceOver,
  98.                 'opIva' => $service->getOpIva(),
  99.                 'iva' => $service->getSageIva(),
  100.                 'pax' => $pax,
  101.                 'hour' => $service->getHour(),
  102.                 'dateInAt' => $service->getDateInAt()?->format('Y-m-d H:i:s'),
  103.                 'dateOutAt' => $service->getDateOutAt()?->format('Y-m-d H:i:s'),
  104.                 'contcolor' => $service->getContcolor(),
  105.                 'rank' => $service->getRank(),
  106.                 'assistantId' => $service->getAssistantId(),
  107.                 'activityId' => $service->getActivityId(),
  108.                 'pay' => $service->getPay(),
  109.                 'createdAt' => $service->getCreatedAt()?->format('Y-m-d H:i:s'),
  110.                 'createdId' => $service->getCreatedId(),
  111.                 'updatedAt' => $service->getUpdatedAt()?->format('Y-m-d H:i:s'),
  112.                 'updatedId' => $service->getUpdatedId(),
  113.                 'toInvoice' => $service->getToInvoice(),
  114.                 'totalSinIva' => $totalConOver,
  115.                 'totalIva' => $priceIva,
  116.                 'totalPrice' => $totalPriceCalculated,
  117.                 'viewInfo' => $service->getViewInfo()
  118.             ];
  119.         }
  120.         // Procesar los salones
  121.         $loungeItems $this->em->getRepository(ReservationLoungeSimple::class)->findBy(['idReservation' => $reservation->getId()]);
  122.         foreach ($loungeItems as $item) {
  123.             $data['reservation']['idWebLanguage'] = $item->getLanguage() ?: 1;
  124.             $uniqueId $item->getId();
  125.             $rankQuote $item->getRankQuote();
  126.             $loungeIva $item->getSageIva();
  127.             if (empty($loungeIva) && !is_numeric($loungeIva)) {
  128.                 $loungeIva 21;
  129.             }
  130.             $loungeData $this->formatLoungeData($item$uniqueId$loungeIva);
  131.             // --- ASIGNACIÓN DE MULTIPLES PAQUETES ---
  132.             // Modificado: Ahora 'avPackages' siempre devuelve un array con todos los elementos mapeados
  133.             $loungeId $loungeData['loungeId'];
  134.             $loungeData['avPackages'] = ($loungeId && isset($packagesByLounge[$loungeId])) 
  135.                 ? $packagesByLounge[$loungeId
  136.                 : [];
  137.             if (!isset($data['options'][$rankQuote])) {
  138.                 $data['options'][$rankQuote] = [];
  139.             }
  140.             $data['options'][$rankQuote][] = $loungeData;
  141.         }
  142.         return new JsonResponse($data);
  143.     }
  144.     /**
  145.      * Formato datos packages
  146.      */
  147.     private function formatPackageTemplate(AvePackageTemplate $template): array
  148.     {
  149.         $items $this->em->getRepository(AvePackageTemplateItems::class)->findBy(['packId' => $template->getId()]);
  150.         return [
  151.             'id'          => $template->getId(),
  152.             'name'        => $template->getName(),
  153.             'description' => $template->getDescription(),
  154.             'totalPrice'  => $template->getTotalNetPrice(),
  155.             'isFeatured'  => $template->isFeatured(), 
  156.             'lounges'     => array_map(fn($lounge) => [
  157.                 'id'   => $lounge->getId(),
  158.                 'name' => $lounge->getName()
  159.             ], $template->getLounges()->toArray()),
  160.             'items'       => array_map(fn(AvePackageTemplateItems $item) => [
  161.                 'id' => $item->getId(),
  162.                 'productName' => $item->getProductName(),
  163.                 'productId' => $item->getProductId(),
  164.                 'percProductPrice' => $item->getPercProductPrice(),
  165.                 'servicePrice' => $item->getServicePrice(),
  166.                 'priceWithoutPack' => $item->getPriceWithoutPack(),
  167.                 'rankAvPack' => $item->getRankAvPack(),
  168.                 'description' => $item->getDescription(),
  169.             ], $items),
  170.         ];
  171.     }
  172.     /**
  173.      * Formatea datos de la reserva para el JSON
  174.      */
  175.     private function formatReservation(Reservation $reservation): array
  176.     {
  177.         $contactEmail null;
  178.         $clientContact $reservation->getClientContact();
  179.         if ($clientContact instanceof ClientContact) {
  180.             $contactEmail $clientContact->getEmail();
  181.             $clientContactId $clientContact->getId();
  182.         } elseif (is_numeric($clientContact)) {
  183.             $contact $this->em->getRepository(ClientContact::class)->find((int) $clientContact);
  184.             $contactEmail $contact $contact->getEmail() : null;
  185.             $clientContactId $contact $contact->getId() : null;
  186.         } else {
  187.             $contactEmail $reservation->getContactUnregistered();
  188.             $clientContactId $clientContact;
  189.         }
  190.         $client $reservation->getClient();
  191.         $clientBlock $client ? [
  192.             'id'   => method_exists($client'getId') ? $client->getId() : null,
  193.             'name' => method_exists($client'getName') ? $client->getName() : null,
  194.         ] : null;
  195.         $idProposal $this->resolveProposalId($reservation) ?? $reservation->getId();
  196.         return [
  197.             'id' => $reservation->getId(),
  198.             'title' => $reservation->getTitle(),
  199.             'client' => $clientBlock,
  200.             'createdAt' => $reservation->getCreatedAt()?->format('Y-m-d H:i:s'),
  201.             'priority' => $reservation->getPriority(),
  202.             'dateStart' => $reservation->getDateStart()?->format('Y-m-d H:i:s'),
  203.             'dateEnd' => $reservation->getDateEnd()?->format('Y-m-d H:i:s'),
  204.             'createdBy' => $reservation->getCreatedBy(),
  205.             'supplier' => $reservation->getSupplier(),
  206.             'status' => $reservation->getStatus(),
  207.             'updatedAt' => $reservation->getUpdatedAt()?->format('Y-m-d H:i:s'),
  208.             'updatedBy' => $reservation->getUpdatedBy(),
  209.             'daysBlock' => $reservation->getDaysBlock(),
  210.             'idProposal' => $idProposal,
  211.             'pax' => $reservation->getPax(),
  212.             'accessKey' => $reservation->getAccessKey(),
  213.             'description' => $reservation->getDescription(),
  214.             'clientContact' => $clientContactId,
  215.             'contactUnregistered' => $reservation->getContactUnregistered(),
  216.             'days' => $reservation->getDays(),
  217.             'contract' => $reservation->getContract(),
  218.             'nameContactUnregistered' => $reservation->getNameContactUnregistered(),
  219.             'phoneContactUnregistered' => $reservation->getPhoneContactUnregistered(),
  220.             'token' => $reservation->getToken(),
  221.             'contactEmail' => $contactEmail,
  222.         ];
  223.     }
  224.     private function formatLoungeData(ReservationLoungeSimple $item$uniqueId$loungeIva): array
  225.     {
  226.         $loungeName $item->getLoungeName();
  227.         /** @var ReservationLoungeDetails|null $detail */
  228.         $detail $this->em->getRepository(ReservationLoungeDetails::class)->findOneBy(['name' => $loungeName]);
  229.         
  230.         if (!$detail) {
  231.             $dateEnd $item->getDateEnd();
  232.             $xdateEnd $dateEnd
  233.                 ? ($dateEnd->format('H:i') === '23:59' $dateEnd->format('Y-m-d 00:00:00') : $dateEnd->format('Y-m-d H:i:s'))
  234.                 : null;
  235.             return [
  236.                 'id' => $uniqueId,
  237.                 'loungeId' => null,
  238.                 'loungeName' => $loungeName,
  239.                 'type' => $item->getType(),
  240.                 'rankQuote' => $item->getRankQuote(),
  241.                 'dateStart' => $item->getDateStart()?->format('Y-m-d H:i:s'),
  242.                 'dateEnd' => $xdateEnd,
  243.                 'pax' => $item->getPax(),
  244.                 'price' => $item->getServicePrice(),
  245.                 'loungeIva' => 0,
  246.                 'combo' => null,
  247.                 'isCombo' => 0,
  248.                 'descriptions' => [],
  249.                 'loungeDescription' => $item->getLoungeDescription(),
  250.                 'importantDescription' => empty($item->getType()) ? $item->getImportantDescription() : '',
  251.                 'importantDescGeneralText' => $item->getImportantDescGeneralText(),
  252.                 'importantDescSchedules' => $item->getImportantDescSchedules(),
  253.                 'importantDescParking' => $item->getImportantDescParking(),
  254.                 'pictures' => [],
  255.                 'comboDetails' => [],
  256.                 'loungeDetails' => null,
  257.                 'totalPrice' => $item->getServicePrice()
  258.             ];
  259.         }
  260.         $ivaPct is_numeric($loungeIva) ? (float) $loungeIva 21.0;
  261.         $ivaImporte $item->getServicePrice() * ($ivaPct 100);
  262.         $comboIds $detail->getCombo();
  263.         return [
  264.             'id' => $uniqueId,
  265.             'loungeId' => $detail->getId(),
  266.             'loungeName' => $detail->getName(),
  267.             'type' => $item->getType(),
  268.             'rankQuote' => $item->getRankQuote(),
  269.             'dateStart' => $item->getDateStart()?->format('Y-m-d H:i:s'),
  270.             'dateEnd' => $item->getDateEnd()?->format('Y-m-d H:i:s'),
  271.             'pax' => $item->getPax(),
  272.             'price' => $item->getServicePrice(),
  273.             'loungeIva' => $ivaImporte,
  274.             'combo' => $comboIds,
  275.             'isCombo' => $comboIds 0,
  276.             'descriptions' => $this->getDescriptions($detail),
  277.             'loungeDescription' => $item->getLoungeDescription(),
  278.             'importantDescription' => empty($item->getType()) ? $item->getImportantDescription() : '',
  279.             'importantDescGeneralText' => $item->getImportantDescGeneralText(),
  280.             'importantDescSchedules' => $item->getImportantDescSchedules(),
  281.             'importantDescParking' => $item->getImportantDescParking(),
  282.             'pictures' => $this->getPictures($detail),
  283.             'comboDetails' => $comboIds $this->getComboDetails($comboIds) : [],
  284.             'loungeDetails' => $this->getLoungeDetails($detail->getId()),
  285.             'totalPrice' => $item->getServicePrice() + $ivaImporte
  286.         ];
  287.     }
  288.     private function getDescriptions(ReservationLoungeDetails $loungeDetail): array
  289.     {
  290.         $descriptions = [];
  291.         $result $this->em->getRepository(ReservationLoungeDescription::class)->findBy(['loungeId' => $loungeDetail->getId()]);
  292.         foreach ($result as $description) {
  293.             $descriptions[] = [
  294.                 'language' => $description->getLanguage(),
  295.                 'description' => $description->getDescription(),
  296.                 'createdAt' => $description->getCreatedAt()?->format('Y-m-d H:i:s'),
  297.                 'updatedAt' => $description->getUpdatedAt()?->format('Y-m-d H:i:s'),
  298.             ];
  299.         }
  300.         return $descriptions;
  301.     }
  302.     private function getPictures(ReservationLoungeDetails $loungeDetail): array
  303.     {
  304.         $pictures = [];
  305.         $result $this->em->getRepository(ReservationLoungePicture::class)->findBy(['loungeId' => $loungeDetail->getId()]);
  306.         foreach ($result as $picture) {
  307.             $pictures[] = [
  308.                 'id' => $picture->getId(),
  309.                 'title' => $picture->getTitle(),
  310.                 'imageLarge' => $picture->getImageLarge(),
  311.                 'imageMedium' => $picture->getImageMedium(),
  312.                 'imageSmall' => $picture->getImageSmall(),
  313.                 'createdAt' => $picture->getCreatedAt()?->format('Y-m-d H:i:s'),
  314.                 'updatedAt' => $picture->getUpdatedAt()?->format('Y-m-d H:i:s'),
  315.             ];
  316.         }
  317.         return $pictures;
  318.     }
  319.     private function getComboDetails(string $comboIds): array
  320.     {
  321.         $comboDetails = [];
  322.         $comboIdArray explode(','$comboIds);
  323.         foreach ($comboIdArray as $comboId) {
  324.             $comboDetail $this->em->getRepository(ReservationLoungeDetails::class)->find($comboId);
  325.             if ($comboDetail) {
  326.                 $comboDetails[] = [
  327.                     'id' => $comboDetail->getId(),
  328.                     'loungeName' => $comboDetail->getName(),
  329.                     'meters' => $comboDetail->getMeters(),
  330.                     'length' => $comboDetail->getLength(),
  331.                     'width' => $comboDetail->getWidth(),
  332.                     'height' => $comboDetail->getHeight(),
  333.                     'capSchool' => $comboDetail->getCapSchool(),
  334.                     'capTheater' => $comboDetail->getCapTheater(),
  335.                     'capCocktail' => $comboDetail->getCapCocktail(),
  336.                     'capBanquet' => $comboDetail->getCapBanquet(),
  337.                     'capImperial' => $comboDetail->getCapImperial(),
  338.                     'rankLounge' => $comboDetail->getRankLounge(),
  339.                     'descriptions' => $this->getDescriptions($comboDetail),
  340.                     'pictures' => $this->getPictures($comboDetail),
  341.                 ];
  342.             }
  343.         }
  344.         return $comboDetails;
  345.     }
  346.     private function getLoungeDetails(int $id): ?array
  347.     {
  348.         $loungeDetail $this->em->getRepository(ReservationLoungeDetails::class)->findOneBy(['id' => $id]);
  349.         if (!$loungeDetail) {
  350.             return null;
  351.         }
  352.         return [
  353.             'id' => $loungeDetail->getId(),
  354.             'name' => $loungeDetail->getName(),
  355.             'meters' => $loungeDetail->getMeters(),
  356.             'length' => $loungeDetail->getLength(),
  357.             'width' => $loungeDetail->getWidth(),
  358.             'height' => $loungeDetail->getHeight(),
  359.             'capSchool' => $loungeDetail->getCapSchool(),
  360.             'capTheater' => $loungeDetail->getCapTheater(),
  361.             'capCocktail' => $loungeDetail->getCapCocktail(),
  362.             'capBanquet' => $loungeDetail->getCapBanquet(),
  363.             'capImperial' => $loungeDetail->getCapImperial(),
  364.             'rankLounge' => $loungeDetail->getRankLounge(),
  365.             'createdAt' => $loungeDetail->getCreatedAt()?->format('Y-m-d H:i:s'),
  366.             'updatedAt' => $loungeDetail->getUpdatedAt()?->format('Y-m-d H:i:s'),
  367.         ];
  368.     }
  369.     private function resolveProposalId(Reservation $reservation): ?int
  370.     {
  371.         if (method_exists($reservation'getProposal')) {
  372.             $proposal $reservation->getProposal();
  373.             if (is_object($proposal) && method_exists($proposal'getId')) {
  374.                 return $proposal->getId();
  375.             }
  376.         }
  377.         foreach (['getIdProposal''getProposalId'] as $m) {
  378.             if (method_exists($reservation$m)) {
  379.                 $val $reservation->$m();
  380.                 return is_numeric($val) ? (int) $val null;
  381.             }
  382.         }
  383.         return null;
  384.     }
  385. }