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

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