src/Controller/OffreCompleteController.php line 65

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Pays;
  4. use App\Entity\Zone;
  5. use App\Entity\Annee;
  6. use App\Entity\Frais;
  7. use App\Entity\Tarif;
  8. use App\Entity\Token;
  9. use App\Entity\Assurance;
  10. use App\Entity\TypeTarifs;
  11. use App\Entity\Restriction;
  12. use App\Entity\FournitureItem;
  13. use App\Service\BandeauService;
  14. use App\Entity\QuantiteBouteille;
  15. use App\Entity\FournitureCategorie;
  16. use Doctrine\ORM\EntityManagerInterface;
  17. use PhpOffice\PhpSpreadsheet\Style\Fill;
  18. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  19. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  20. use PhpOffice\PhpSpreadsheet\Style\Border;
  21. use PhpOffice\PhpSpreadsheet\Style\Alignment;
  22. use Symfony\Component\HttpFoundation\Request;
  23. use Symfony\Component\HttpFoundation\Response;
  24. use Symfony\Component\Routing\Annotation\Route;
  25. use Symfony\Component\HttpFoundation\StreamedResponse;
  26. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  27. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  28. class OffreCompleteController extends AbstractController
  29. {
  30.     private $zoneRepository;
  31.     private $paysRepository;
  32.     private $anneeRepository;
  33.     private $fraisRepository;
  34.     private $tarifRepository;
  35.     private $assuranceRepository;
  36.     private $typeTarifsRepository;
  37.     private $restrictionRepository;
  38.     private $fournitureItemRepository;
  39.     private $quantiteBouteilleRepository;
  40.     private $fournitureCategorieRepository;
  41.     private $bandeauService;
  42.     public function __construct(EntityManagerInterface $entityManagerBandeauService $bandeauService)
  43.     {
  44.         $this->zoneRepository $entityManager->getRepository(Zone::class);
  45.         $this->paysRepository $entityManager->getRepository(Pays::class);
  46.         $this->anneeRepository $entityManager->getRepository(Annee::class);
  47.         $this->fraisRepository $entityManager->getRepository(Frais::class);
  48.         $this->tarifRepository $entityManager->getRepository(Tarif::class);
  49.         $this->assuranceRepository $entityManager->getRepository(Assurance::class);
  50.         $this->typeTarifsRepository $entityManager->getRepository(TypeTarifs::class);
  51.         $this->restrictionRepository $entityManager->getRepository(Restriction::class);
  52.         $this->fournitureItemRepository $entityManager->getRepository(FournitureItem::class);
  53.         $this->quantiteBouteilleRepository $entityManager->getRepository(QuantiteBouteille::class);
  54.         $this->fournitureCategorieRepository $entityManager->getRepository(FournitureCategorie::class);
  55.         $this->bandeauService $bandeauService;
  56.     }
  57.     /**
  58.      * @Route("/offre", name="app_offre")     
  59.      */
  60.     public function index(Request $request): Response
  61.     {
  62.         $user $this->getUser();
  63.         // // Vérifier si l'utilisateur est authentifié
  64.         // if (!$user) {
  65.         //     return $this->redirectToRoute('login'); 
  66.         // }
  67.         //on regarde si le token est présent
  68.         // Vérifier le token dans l'URL
  69.         $tokenValue $request->query->get('token');
  70.         if ($tokenValue) {
  71.             $entityManager $this->getDoctrine()->getManager();
  72.             $tokenRepository $entityManager->getRepository(Token::class);
  73.             $token $tokenRepository->findOneBy(['string' => $tokenValue]);
  74.             $isvalid $token->isValid();
  75.             if (!$token or !$isvalid) {
  76.                 return $this->redirectToRoute('login');
  77.             }
  78.             if ($isvalid) {
  79.                 //si la date d'expiration est vide, on la remplit (délai une semaine)
  80.                 if ($token->getDateUse() == null) {
  81.                     $token->setDateUse(new \DateTime('@' strtotime('+1 week')));
  82.                     $entityManager->persist($token);
  83.                     $entityManager->flush();
  84.                 }
  85.             }
  86.         } else {
  87.             if (!$user) {
  88.                 return $this->redirectToRoute('login');
  89.             }
  90.             //pas de token, on vérifie que le comtpe est enadmin
  91.             if ($this->isGranted('ROLE_ADMIN')) {
  92.                 return $this->redirectToRoute('app_admin_index');
  93.             }
  94.         }
  95.         // Récupérer l'année en cours et l'année prochaine
  96.         $currentYear = (int)date('Y');
  97.         $nextYear $currentYear 1;
  98.         // Vérifier si la date actuelle est supérieure au 10 novembre de l'année en cours
  99.         $currentDate = new \DateTime();
  100.         $november10 = new \DateTime("$currentYear-11-10");
  101.         $showOffreSuivante $currentDate $november10;
  102.         $nextYearBoolean false;
  103.         // Permet de savoir si on est dans l'année suivante
  104.         $offre $request->query->get('offre');
  105.         // Si l'utilisateur a choisi l'offre suivante et si c'est possible en terme de date alors on passe à true le nextYearBoolean
  106.         if ($offre === 'suivante' && $showOffreSuivante) {
  107.             $nextYearBoolean true;
  108.         }
  109.         // Récupération des données
  110.         $zones $this->zoneRepository->findZonesForCurrentYear($nextYearBoolean);
  111.         return $this->render('offre_complete/index.html.twig', [
  112.             'controller_name' => 'OffreController',
  113.             'user' => $user,
  114.             'zones' => $zones,
  115.             'currentYear' => $currentYear,
  116.             'nextYear' => $nextYear,
  117.             'showOffreSuivante' => $showOffreSuivante,
  118.             'nextYearBoolean' => $nextYearBoolean,
  119.             'bandeau' => $this->bandeauService->displayPopup()   
  120.         ]);
  121.     }
  122.     /**
  123.      * @Route("/get_tarifs_pays/{id}", name="get_country_info", methods={"GET"})
  124.      */
  125.     public function getTarifsPays(Pays $paysEntityManagerInterface $entityManagerrequest $request): Response
  126.     {
  127.         $user $this->getUser();
  128.         //on regarde s'il un token est présent
  129.         $tokenValue $request->query->get('token');
  130.         if ($tokenValue) {
  131.             $entityManager $this->getDoctrine()->getManager();
  132.             $tokenRepository $entityManager->getRepository(Token::class);
  133.             $token $tokenRepository->findOneBy(['string' => $tokenValue]);
  134.             $isvalid $token->isValid();
  135.             if (!$isvalid) {
  136.                 return $this->redirectToRoute('login');
  137.             }
  138.         } else {
  139.             //si il n'y a pas de token
  140.             // Vérifier si l'utilisateur est authentifié
  141.             if (!$user) {
  142.                 return $this->redirectToRoute('login');
  143.             }
  144.         }
  145.         // Si le pays n'est pas trouvé, retourner une réponse 404
  146.         if (!$pays) {
  147.             return new Response("Pays non trouvé"Response::HTTP_NOT_FOUND);
  148.         }
  149.         $zone $pays->getZone();
  150.         $quantitesBouteilles $zone->getQuantitesBouteilles();
  151.         $typesTarifs $zone->getTypeTarifs();
  152.         $frais $zone->getFrais();
  153.         $informations $zone->getInformation();
  154.         $restrictions $pays->getRestrictions();
  155.         $tarifsData $this->tarifsDataConstruct($typesTarifs$quantitesBouteilles);
  156.         // Rendre un template partiel avec les informations du pays
  157.         return $this->render('tarifs/_show_tarifs.html.twig', [
  158.             'pays' => $pays,
  159.             'typesTarifs' => $typesTarifs,
  160.             'quantitesBouteilles' => $quantitesBouteilles,
  161.             'tarifsData' => $tarifsData// Matrice des tarifs organisée par type et quantité
  162.             'frais' => $frais,
  163.             'informations' => $informations,
  164.             'restrictions' => $restrictions,
  165.             'user' => $user
  166.         ]);
  167.     }
  168.     /**
  169.      * @Route("/export-tarifs/{id}", name="export_tarifs")
  170.      */
  171.     public function exportTarifs(Pays $pays): StreamedResponse
  172.     {
  173.         $user $this->getUser();
  174.         // Vérifier si l'utilisateur est authentifié
  175.         if (!$user) {
  176.             return $this->redirectToRoute('login');
  177.         }
  178.         // Si le pays n'est pas trouvé, retourner une réponse 404
  179.         if (!$pays) {
  180.             return new Response("Pays non trouvé"Response::HTTP_NOT_FOUND);
  181.         }
  182.         // Récupérer les données nécessaires 
  183.         $zone $pays->getZone();
  184.         $quantitesBouteilles $zone->getQuantitesBouteilles();
  185.         $typesTarifs $zone->getTypeTarifs();
  186.         $tarifsData $this->tarifsDataConstruct($typesTarifs$quantitesBouteilles);
  187.         // Création du fichier Excel
  188.         $spreadsheet = new Spreadsheet();
  189.         $sheet $spreadsheet->getActiveSheet();
  190.         // Style des en-têtes
  191.         $headerStyle = [
  192.             'font' => [
  193.                 'bold' => true,
  194.                 'color' => ['rgb' => 'FFFFFF'],
  195.             ],
  196.             'fill' => [
  197.                 'fillType' => Fill::FILL_SOLID,
  198.                 'startColor' => ['rgb' => 'C20E1B'],
  199.             ],
  200.             'alignment' => [
  201.                 'horizontal' => Alignment::HORIZONTAL_CENTER,
  202.                 'vertical' => Alignment::VERTICAL_CENTER,
  203.             ],
  204.         ];
  205.         // Style des cellules de données
  206.         $dataStyle = [
  207.             'alignment' => [
  208.                 'horizontal' => Alignment::HORIZONTAL_CENTER,
  209.                 'vertical' => Alignment::VERTICAL_CENTER,
  210.             ],
  211.             'borders' => [
  212.                 'bottom' => [
  213.                     'borderStyle' => Border::BORDER_THIN,
  214.                     'color' => ['rgb' => 'CCCCCC'],
  215.                 ],
  216.             ],
  217.         ];
  218.         // Style de bordure pour le tableau
  219.         $borderStyle = [
  220.             'borders' => [
  221.                 'outline' => [
  222.                     'borderStyle' => Border::BORDER_THIN,
  223.                     'color' => ['rgb' => 'C20E1B'],
  224.                 ],
  225.             ],
  226.         ];
  227.         // En-têtes du premier tableau
  228.         $sheet->setCellValue('A1''Nb de bouteilles');
  229.         $sheet->setCellValue('B1''Nb de cartons');
  230.         $columnIndex 3;
  231.         foreach ($typesTarifs as $typeTarif) {
  232.             $sheet->setCellValueByColumnAndRow($columnIndex1$typeTarif->getTitre());
  233.             $columnIndex++;
  234.         }
  235.         // Appliquer le style aux en-têtes
  236.         $sheet->getStyle("A1:" chr(64 $columnIndex 1) . "1")->applyFromArray($headerStyle);
  237.         // Fixer la largeur des colonnes à 210px
  238.         foreach (range('A'chr(64 $columnIndex 1)) as $columnID) {
  239.             $sheet->getColumnDimension($columnID)->setWidth(30); // Environ 210px
  240.             $sheet->getColumnDimension($columnID)->setAutoSize(true);
  241.         }
  242.         // Remplir les données du premier tableau (1 carton)
  243.         $rowIndex 2;
  244.         foreach ($quantitesBouteilles as $quantiteBouteille) {
  245.             if ($quantiteBouteille->getNbCartons() == 1) {
  246.                 $sheet->setCellValueByColumnAndRow(1$rowIndex$quantiteBouteille->getMinBouteille() . ' > ' $quantiteBouteille->getMaxBouteille());
  247.                 $sheet->setCellValueByColumnAndRow(2$rowIndex$quantiteBouteille->getNbCartons());
  248.                 // Remplir les tarifs par type
  249.                 $columnIndex 3;
  250.                 foreach ($typesTarifs as $typeTarif) {
  251.                     $tarif $tarifsData[$typeTarif->getId()][$quantiteBouteille->getId()] ?? 'N/A';
  252.                     $sheet->setCellValueByColumnAndRow($columnIndex$rowIndexis_numeric($tarif) ? number_format($tarif2'.'',') . ' €' 'N/A');
  253.                     $columnIndex++;
  254.                 }
  255.                 // Appliquer le style de données aux lignes de données
  256.                 $sheet->getStyle("A$rowIndex:" chr(64 $columnIndex 1) . "$rowIndex")->applyFromArray($dataStyle);
  257.                 $rowIndex++;
  258.             }
  259.         }
  260.         // Ajouter une ligne vide entre les deux tableaux
  261.         $rowIndex++;
  262.         // Remplir les données du second tableau (plusieurs cartons)
  263.         foreach ($quantitesBouteilles as $quantiteBouteille) {
  264.             if ($quantiteBouteille->getNbCartons() > 1) {
  265.                 $sheet->setCellValueByColumnAndRow(1$rowIndex$quantiteBouteille->getMinBouteille() . ' > ' $quantiteBouteille->getMaxBouteille());
  266.                 $sheet->setCellValueByColumnAndRow(2$rowIndex$quantiteBouteille->getNbCartons());
  267.                 // Remplir les tarifs par type
  268.                 $columnIndex 3;
  269.                 foreach ($typesTarifs as $typeTarif) {
  270.                     $tarif $tarifsData[$typeTarif->getId()][$quantiteBouteille->getId()] ?? 'N/A';
  271.                     $sheet->setCellValueByColumnAndRow($columnIndex$rowIndexis_numeric($tarif) ? number_format($tarif2'.'',') . ' €' 'N/A');
  272.                     $columnIndex++;
  273.                 }
  274.                 // Appliquer le style de données aux lignes de données
  275.                 $sheet->getStyle("A$rowIndex:" chr(64 $columnIndex 1) . "$rowIndex")->applyFromArray($dataStyle);
  276.                 $rowIndex++;
  277.             }
  278.         }
  279.         // Appliquer la bordure autour du tableau
  280.         $sheet->getStyle("A1:" chr(64 $columnIndex 1) . ($rowIndex 1))->applyFromArray($borderStyle);
  281.         // Création de la réponse en streaming pour le téléchargement
  282.         $response = new StreamedResponse(function () use ($spreadsheet) {
  283.             $writer = new Xlsx($spreadsheet);
  284.             $writer->save('php://output');
  285.         });
  286.         // Obtenir la date et l'heure actuelles
  287.         $dateTime = (new \DateTime())->format('Y-m-d_H-i-s');
  288.         // Définir les en-têtes de téléchargement
  289.         $response->headers->set('Content-Type''application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  290.         $response->headers->set('Content-Disposition'ResponseHeaderBag::DISPOSITION_ATTACHMENT);
  291.         $response->headers->set('Content-Disposition''attachment;filename="tarifs_' $pays->getNom() . '_' $dateTime '.xlsx"');
  292.         $response->headers->set('Cache-Control''max-age=0');
  293.         return $response;
  294.     }
  295.     /**
  296.      * @Route("/export-tarifs-global", name="export_tarifs_global")
  297.      */
  298.     public function exportTarifsGlobal(): StreamedResponse
  299.     {
  300.         $user $this->getUser();
  301.         // Vérifier si l'utilisateur est authentifié
  302.         if (!$user) {
  303.             return $this->redirectToRoute('login');
  304.         }
  305.         $zones $this->zoneRepository->findZonesForCurrentYear(false);
  306.         // Création du fichier Excel
  307.         $spreadsheet = new Spreadsheet();        
  308.         $indexFeuille 0;
  309.         foreach ($zones as $keyZone => $zone) {
  310.             
  311.             // Pour la première itération, récupération de la feuille active
  312.             // Pour les suivantes, création d'une nouvelle feuille.
  313.             if ($indexFeuille === 0) {
  314.                 $sheet $spreadsheet->getActiveSheet();
  315.             } else {
  316.                 // Crée un nouvel onglet
  317.                 $sheet $spreadsheet->createSheet();
  318.             }
  319.             $titreFeuille substr($zone->getNom(), 031); 
  320.             $sheet->setTitle($titreFeuille);            
  321.             // Récupérer les données nécessaires 
  322.             $quantitesBouteilles $zone->getQuantitesBouteilles();
  323.             $typesTarifs $zone->getTypeTarifs();
  324.             $tarifsData $this->tarifsDataConstruct($typesTarifs$quantitesBouteilles);
  325.             // Style des en-têtes
  326.             $headerStyle = [
  327.                 'font' => [
  328.                     'bold' => true,
  329.                     'color' => ['rgb' => 'FFFFFF'],
  330.                 ],
  331.                 'fill' => [
  332.                     'fillType' => Fill::FILL_SOLID,
  333.                     'startColor' => ['rgb' => 'C20E1B'],
  334.                 ],
  335.                 'alignment' => [
  336.                     'horizontal' => Alignment::HORIZONTAL_CENTER,
  337.                     'vertical' => Alignment::VERTICAL_CENTER,
  338.                 ],
  339.             ];
  340.             // Style des cellules de données
  341.             $dataStyle = [
  342.                 'alignment' => [
  343.                     'horizontal' => Alignment::HORIZONTAL_CENTER,
  344.                     'vertical' => Alignment::VERTICAL_CENTER,
  345.                 ],
  346.                 'borders' => [
  347.                     'bottom' => [
  348.                         'borderStyle' => Border::BORDER_THIN,
  349.                         'color' => ['rgb' => 'CCCCCC'],
  350.                     ],
  351.                 ],
  352.             ];
  353.             // Style de bordure pour le tableau
  354.             $borderStyle = [
  355.                 'borders' => [
  356.                     'outline' => [
  357.                         'borderStyle' => Border::BORDER_THIN,
  358.                         'color' => ['rgb' => 'C20E1B'],
  359.                     ],
  360.                 ],
  361.             ];
  362.             // En-têtes du premier tableau
  363.             $sheet->setCellValue('A1''Nb de bouteilles');
  364.             $sheet->setCellValue('B1''Nb de cartons');
  365.             $columnIndex 3;
  366.             foreach ($typesTarifs as $typeTarif) {
  367.                 $sheet->setCellValueByColumnAndRow($columnIndex1$typeTarif->getTitre());
  368.                 $columnIndex++;
  369.             }
  370.             // Appliquer le style aux en-têtes
  371.             $sheet->getStyle("A1:" chr(64 $columnIndex 1) . "1")->applyFromArray($headerStyle);
  372.             // Fixer la largeur des colonnes à 210px
  373.             foreach (range('A'chr(64 $columnIndex 1)) as $columnID) {
  374.                 $sheet->getColumnDimension($columnID)->setWidth(30); // Environ 210px
  375.                 $sheet->getColumnDimension($columnID)->setAutoSize(true);
  376.             }
  377.             // Remplir les données du premier tableau (1 carton)
  378.             $rowIndex 2;
  379.             foreach ($quantitesBouteilles as $quantiteBouteille) {
  380.                 if ($quantiteBouteille->getNbCartons() == 1) {
  381.                     $sheet->setCellValueByColumnAndRow(1$rowIndex$quantiteBouteille->getMinBouteille() . ' > ' $quantiteBouteille->getMaxBouteille());
  382.                     $sheet->setCellValueByColumnAndRow(2$rowIndex$quantiteBouteille->getNbCartons());
  383.                     // Remplir les tarifs par type
  384.                     $columnIndex 3;
  385.                     foreach ($typesTarifs as $typeTarif) {
  386.                         $tarif $tarifsData[$typeTarif->getId()][$quantiteBouteille->getId()] ?? 'N/A';
  387.                         $sheet->setCellValueByColumnAndRow($columnIndex$rowIndexis_numeric($tarif) ? number_format($tarif2'.'',') . ' €' 'N/A');
  388.                         $columnIndex++;
  389.                     }
  390.                     // Appliquer le style de données aux lignes de données
  391.                     $sheet->getStyle("A$rowIndex:" chr(64 $columnIndex 1) . "$rowIndex")->applyFromArray($dataStyle);
  392.                     $rowIndex++;
  393.                 }
  394.             }
  395.             // Ajouter une ligne vide entre les deux tableaux
  396.             $rowIndex++;
  397.             // Remplir les données du second tableau (plusieurs cartons)
  398.             foreach ($quantitesBouteilles as $quantiteBouteille) {
  399.                 if ($quantiteBouteille->getNbCartons() > 1) {
  400.                     $sheet->setCellValueByColumnAndRow(1$rowIndex$quantiteBouteille->getMinBouteille() . ' > ' $quantiteBouteille->getMaxBouteille());
  401.                     $sheet->setCellValueByColumnAndRow(2$rowIndex$quantiteBouteille->getNbCartons());
  402.                     // Remplir les tarifs par type
  403.                     $columnIndex 3;
  404.                     foreach ($typesTarifs as $typeTarif) {
  405.                         $tarif $tarifsData[$typeTarif->getId()][$quantiteBouteille->getId()] ?? 'N/A';
  406.                         $sheet->setCellValueByColumnAndRow($columnIndex$rowIndexis_numeric($tarif) ? number_format($tarif2'.'',') . ' €' 'N/A');
  407.                         $columnIndex++;
  408.                     }
  409.                     // Appliquer le style de données aux lignes de données
  410.                     $sheet->getStyle("A$rowIndex:" chr(64 $columnIndex 1) . "$rowIndex")->applyFromArray($dataStyle);
  411.                     $rowIndex++;
  412.                 }
  413.             }
  414.             // Appliquer la bordure autour du tableau
  415.             $sheet->getStyle("A1:" chr(64 $columnIndex 1) . ($rowIndex 1))->applyFromArray($borderStyle);
  416.             $indexFeuille++;
  417.         }
  418.         // Création de la réponse en streaming pour le téléchargement
  419.         $response = new StreamedResponse(function () use ($spreadsheet) {
  420.             $writer = new Xlsx($spreadsheet);
  421.             $writer->save('php://output');
  422.         });
  423.         // Obtenir la date et l'heure actuelles
  424.         $dateTime = (new \DateTime())->format('Y-m-d_H-i-s');
  425.         // Définir les en-têtes de téléchargement
  426.         $response->headers->set('Content-Type''application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  427.         $response->headers->set('Content-Disposition'ResponseHeaderBag::DISPOSITION_ATTACHMENT);
  428.         $response->headers->set('Content-Disposition''attachment;filename="tarifs_global_' $dateTime '.xlsx"');
  429.         $response->headers->set('Cache-Control''max-age=0');
  430.         return $response;
  431.     }
  432.     private function tarifsDataConstruct($typesTarifs$quantitesBouteilles)
  433.     {
  434.         $tarifsData = [];
  435.         foreach ($typesTarifs as $typeTarif) {
  436.             $tarifsData[$typeTarif->getId()] = [];
  437.             foreach ($quantitesBouteilles as $quantiteBouteille) {
  438.                 $tarif $this->tarifRepository->findOneBy([
  439.                     'typeTarifs' => $typeTarif,
  440.                     'quantiteBouteille' => $quantiteBouteille,
  441.                 ]);
  442.                 // Stocker le tarif ou null s'il n'y a pas de tarif pour cette combinaison
  443.                 $tarifsData[$typeTarif->getId()][$quantiteBouteille->getId()] = $tarif $tarif->getMontant() : null;
  444.             }
  445.         }
  446.         return $tarifsData;
  447.     }
  448. }