src/Controller/SimulateurController.php line 119

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Dompdf\Dompdf;
  4. use Dompdf\Options;
  5. use App\Entity\Pays;
  6. use App\Entity\Zone;
  7. use App\Entity\Annee;
  8. use App\Entity\Frais;
  9. use App\Entity\Tarif;
  10. use App\Entity\Assurance;
  11. use App\Entity\TypeTarifs;
  12. use App\Entity\Restriction;
  13. use App\Entity\FournitureItem;
  14. use App\Service\BandeauService;
  15. use App\Entity\QuantiteBouteille;
  16. use App\Service\CalculTaxeService;
  17. use App\Entity\FournitureCategorie;
  18. use App\Entity\ZoneDepartementsPoids;
  19. use Doctrine\ORM\EntityManagerInterface;
  20. use PhpOffice\PhpSpreadsheet\Style\Fill;
  21. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  22. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  23. use PhpOffice\PhpSpreadsheet\Style\Border;
  24. use PhpOffice\PhpSpreadsheet\Style\Alignment;
  25. use Symfony\Component\HttpFoundation\Request;
  26. use Symfony\Component\HttpFoundation\Response;
  27. use Symfony\Component\Routing\Annotation\Route;
  28. use Symfony\Component\HttpFoundation\JsonResponse;
  29. use Symfony\Component\HttpFoundation\StreamedResponse;
  30. use Symfony\Component\HttpFoundation\ResponseHeaderBag;
  31. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  32. class SimulateurController extends AbstractController
  33. {
  34.     private $zoneRepository;
  35.     private $paysRepository;
  36.     private $anneeRepository;
  37.     private $fraisRepository;
  38.     private $tarifRepository;
  39.     private $assuranceRepository;
  40.     private $typeTarifsRepository;
  41.     private $restrictionRepository;
  42.     private $fournitureItemRepository;
  43.     private $quantiteBouteilleRepository;
  44.     private $fournitureCategorieRepository;
  45.     private $montantDeliveredDutyPaid;
  46.     private $ZoneDepartementsPoidsRepository;
  47.     private $aRoyaumeUniId;
  48.     private $aSuisseId;
  49.     private $aNorvegeId;
  50.     private $aAustralieId;
  51.     private $aNouvelleZelandeId;
  52.     private $aSingapourId;
  53.     private $aCoreeSudId;
  54.     private $aJaponId;
  55.     private $aTaiwanId;
  56.     private $bandeauService;
  57.     private $calculTaxeService;
  58.     public function __construct(EntityManagerInterface $entityManagerCalculTaxeService $calculTaxeServiceBandeauService $bandeauService)
  59.     {
  60.         $this->montantDeliveredDutyPaid 19;
  61.         $this->calculTaxeService $calculTaxeService;
  62.         $this->zoneRepository $entityManager->getRepository(Zone::class);
  63.         $this->paysRepository $entityManager->getRepository(Pays::class);
  64.         $this->anneeRepository $entityManager->getRepository(Annee::class);
  65.         $this->fraisRepository $entityManager->getRepository(Frais::class);
  66.         $this->tarifRepository $entityManager->getRepository(Tarif::class);
  67.         $this->assuranceRepository $entityManager->getRepository(Assurance::class);
  68.         $this->typeTarifsRepository $entityManager->getRepository(TypeTarifs::class);
  69.         $this->restrictionRepository $entityManager->getRepository(Restriction::class);
  70.         $this->fournitureItemRepository $entityManager->getRepository(FournitureItem::class);
  71.         $this->quantiteBouteilleRepository $entityManager->getRepository(QuantiteBouteille::class);
  72.         $this->fournitureCategorieRepository $entityManager->getRepository(FournitureCategorie::class);
  73.         $this->ZoneDepartementsPoidsRepository $entityManager->getRepository(ZoneDepartementsPoids::class);
  74.         $this->aRoyaumeUniId = [303132];
  75.         $this->aSuisseId = [50];
  76.         $this->aNorvegeId = [33];
  77.         $this->aAustralieId = [51];
  78.         $this->aNouvelleZelandeId = [57];
  79.         $this->aSingapourId = [58];
  80.         $this->aCoreeSudId = [52];
  81.         $this->aJaponId = [55];
  82.         $this->aTaiwanId = [38];
  83.         $this->bandeauService $bandeauService;
  84.     }
  85.     /**
  86.      * @Route("/simulateur", name="app_simulateur")     
  87.      */
  88.     public function index(Request $request): Response
  89.     {
  90.         $user $this->getUser();
  91.         // Vérifier si l'utilisateur est authentifié
  92.         if (!$user) {
  93.             return $this->redirectToRoute('login');
  94.         }
  95.         if ($this->isGranted('ROLE_ADMIN')) {
  96.             return $this->redirectToRoute('app_admin_index');
  97.         }
  98.         // Récupérer l'année en cours
  99.         $currentYear = (int)date('Y');
  100.         // Récupération des données
  101.         $zones $this->zoneRepository->findZonesForCurrentYear();
  102.         return $this->render('simulateur/newSimulateur.html.twig', [
  103.             'controller_name' => 'SimulateurController',
  104.             'user' => $user,
  105.             'zones' => $zones,
  106.             'currentYear' => $currentYear,
  107.             'bandeau' => $this->bandeauService->displayPopup()
  108.         ]);
  109.     }
  110.     /**
  111.      * @Route("/get_construct_simulateur/{id}", name="get_construct_simulateur", methods={"GET"})
  112.      */
  113.     public function getConstructSimulateur(Pays $paysEntityManagerInterface $entityManager): Response
  114.     {
  115.         $user $this->getUser();
  116.         // Vérifier si l'utilisateur est authentifié
  117.         if (!$user) {
  118.             return $this->redirectToRoute('login');
  119.         }
  120.         // Si le pays n'est pas trouvé, retourner une réponse 404
  121.         if (!$pays) {
  122.             return new Response("Pays non trouvé"Response::HTTP_NOT_FOUND);
  123.         }
  124.         $zone $pays->getZone();
  125.         $isUsa $zone->isIsUsa();
  126.         // Récupération des assurances
  127.         $assuranceDeBase =  $this->assuranceRepository->findOneByAssuranceBase(true);
  128.         $assurances $this->assuranceRepository->findAll();
  129.         // On récupère les emballages (si c'est une zone boolean USA alors il faut afficher uniquement les emballages compatible USA)
  130.         $emballages null;
  131.         if ($isUsa == null or $isUsa == 0) {
  132.             $emballages $this->fournitureCategorieRepository->findAll();
  133.         } else {
  134.             $emballages $this->fournitureCategorieRepository->findByCompatibleUsa(true);
  135.         }
  136.         $caisseEnBois true;
  137.         // On test si la zone ne peut pas envoyer de caisse en bois en option
  138.         if ($zone->getCaisseBoisMontantBouteilleSix() == null) {
  139.             $caisseEnBois false;
  140.         }
  141.         $typesTarifs $zone->getTypeTarifs();
  142.         $frais $zone->getFrais();
  143.         // Rendre un template partiel avec les informations du pays
  144.         return $this->render('simulateur/_show_simulateur.html.twig', [
  145.             'pays' => $pays,
  146.             'typesTarifs' => $typesTarifs,
  147.             'emballages' => $emballages,
  148.             'frais' => $frais,
  149.             'caisseEnBois' => $caisseEnBois,
  150.             'assuranceDeBase' => $assuranceDeBase,
  151.             'assurances' => $assurances
  152.         ]);
  153.     }
  154.     /**
  155.      * @Route("/calc_simulateur/{id}", name="calc_simulateur", methods={"POST"})
  156.      */
  157.     public function calcSimulateur(Request $requestPays $pays): Response
  158.     {
  159.         $user $this->getUser();
  160.         // Vérifier si l'utilisateur est authentifié
  161.         if (!$user) {
  162.             return $this->redirectToRoute('login');
  163.         }
  164.         // Si le pays n'est pas trouvé, retourner une réponse 404
  165.         if (!$pays) {
  166.             return new Response("Pays non trouvé"Response::HTTP_NOT_FOUND);
  167.         }
  168.         // Récupérer et décoder les données JSON envoyées
  169.         $data json_decode($request->getContent(), true);
  170.         // Assurez-vous que les données sont valides
  171.         if (!isset($data['recap']) || !is_array($data['recap'])) {
  172.             return new JsonResponse(['error' => 'Invalid data'], 400);
  173.         }
  174.         $aReturnDonnee $this->genereAllCalc($data$pays);
  175.         $montantTransport $aReturnDonnee["montantTransport"];
  176.         $montantEmballage $aReturnDonnee["montantEmballage"];
  177.         $montantAssurance $aReturnDonnee["montantAssurance"];
  178.         $montantTaxe $aReturnDonnee["montantTaxe"];
  179.         $montantOptions $aReturnDonnee["montantOptions"];
  180.         $montantCaisseEnBois $aReturnDonnee["montantCaisseEnBois"];
  181.         $montantSurPalette $aReturnDonnee["montantSurPalette"];
  182.         $montantTotal $aReturnDonnee["montantTotal"];
  183.         $isAssujettiTva $aReturnDonnee["isAssujettiTva"];
  184.         $errors $aReturnDonnee["errors"];
  185.         return $this->render('simulateur/_affichage_complet_simulateur.html.twig', [
  186.             'montantTransport' => $montantTransport,
  187.             'montantEmballage' => $montantEmballage,
  188.             'montantAssurance' => $montantAssurance,
  189.             'montantTaxe' => $montantTaxe,
  190.             'montantOptions' => $montantOptions,
  191.             'montantCaisseEnBois' => $montantCaisseEnBois,
  192.             'montantSurPalette' => $montantSurPalette,
  193.             'montantTotal' => $montantTotal,
  194.             'isAssujettiTva' => $isAssujettiTva,
  195.             'errors' => $errors
  196.         ]);
  197.     }
  198.     /**
  199.      * @Route("/generate-pdf/{id}", name="generate_pdf_simu", methods={"POST"})
  200.      */
  201.     public function generatePdf(Request $requestPays $pays): Response
  202.     {
  203.         $user $this->getUser();
  204.         // Vérifier si l'utilisateur est authentifié
  205.         if (!$user) {
  206.             return $this->redirectToRoute('login');
  207.         }
  208.         // Si le pays n'est pas trouvé, retourner une réponse 404
  209.         if (!$pays) {
  210.             return new Response("Pays non trouvé"Response::HTTP_NOT_FOUND);
  211.         }
  212.         // Récupérer et décoder les données JSON envoyées
  213.         $data json_decode($request->getContent(), true);
  214.         // Assurez-vous que les données sont valides
  215.         if (!isset($data['recap']) || !is_array($data['recap'])) {
  216.             return new JsonResponse(['error' => 'Invalid data'], 400);
  217.         }
  218.         $aReturnDonnee $this->genereAllCalc($data$pays);
  219.         $assuranceDeBase =  $this->assuranceRepository->findOneByAssuranceBase(true);
  220.         // On récupére le total des bouteilles
  221.         $totalBottles $this->calculateTotalBottles($data['recap']);
  222.         $volumeBottles $this->calculateVolumeBottles($data['recap']);
  223.         // Créer une instance Dompdf
  224.         $options = new Options();
  225.         $options->set('defaultFont''Arial');
  226.         $options->set('isRemoteEnabled'true);
  227.         $options->set('enable_html5_parser'true);
  228.         $dompdf = new Dompdf($options);
  229.         // Récupérer les données de la page
  230.         $html $this->renderView('pdf/export_simulateur.html.twig', [
  231.             'pays' => $pays->getNom(),
  232.             'montantTransport' => $aReturnDonnee['montantTransport'],
  233.             'montantEmballage' => $aReturnDonnee['montantEmballage'],
  234.             'montantAssurance' => $aReturnDonnee['montantAssurance'],
  235.             'montantTaxe' => $aReturnDonnee['montantTaxe'],
  236.             'montantValeur' => $aReturnDonnee['montantValeur'],
  237.             'montantOptions' => $aReturnDonnee['montantOptions'],
  238.             'montantCaisseEnBois' => $aReturnDonnee['montantCaisseEnBois'],
  239.             'montantTotal' => $aReturnDonnee['montantTotal'],
  240.             'isAssujettiTva' => $aReturnDonnee['isAssujettiTva'],
  241.             'errors' => $aReturnDonnee['errors'],
  242.             'montantSurPalette' => $aReturnDonnee['montantSurPalette'],
  243.             'nomAssurrance' => $aReturnDonnee['nomAssurrance'],
  244.             'nomEmballage' => $aReturnDonnee['nomEmballage'],
  245.             'totalBottles' => $totalBottles,
  246.             'volumeBottles' => $volumeBottles,
  247.             'assuranceDeBase' => $assuranceDeBase,
  248.             'assuranceComp' => $aReturnDonnee["assuranceComp"],
  249.             'nomLivraison' => $aReturnDonnee["nomLivraison"],
  250.             'descLivraison' => $aReturnDonnee["descLivraison"],
  251.             'poidsSurPalette' => $aReturnDonnee["poidsSurPalette"],
  252.             'departementSurPalettetext' => $aReturnDonnee["departementSurPalettetext"],
  253.         ]);
  254.         // Charger le HTML dans Dompdf
  255.         $dompdf->loadHtml($html);
  256.         // (Facultatif) Définir les dimensions du papier
  257.         $dompdf->setPaper('A4''portrait');
  258.         // Générer le PDF
  259.         $dompdf->render();
  260.         // Retourner le PDF sous forme de réponse HTTP
  261.         return new Response($dompdf->output(), 200, [
  262.             'Content-Type' => 'application/pdf',
  263.             'Content-Disposition' => 'inline; filename="page.pdf"',
  264.         ]);
  265.     }
  266.     public function genereAllCalc($data$pays)
  267.     {
  268.         // On récupère la zone
  269.         $zone $pays->getZone();
  270.         // On récupère le boolean pour assujetti à la tva ou non
  271.         $isAssujettiTva $zone->isAssujettiTva();
  272.         $errors = array();
  273.         $recap $data['recap']; // Tableau des volumes et quantités
  274.         $checkedAssurances $data['checkedAssurances']; // Tableau récap des assurances check
  275.         $checkedEmballages $data['checkedEmballages']; // Tableau récap des emballages check
  276.         $checkedLivraisons $data['checkedLivraisons']; // Tableau récap des livraisons check
  277.         $checkedDeliveredDutyPaid $data['checkedDeliveredDutyPaid']; // // Check option DDP
  278.         $checkedCaisseEnBois $data['checkedCaisseEnBois']; // Check option caisse en bois
  279.         $checkedSurPalette $data['checkedSurPalette']; // Check option sur palette
  280.         $montantValeur $data['montantValeur'];
  281.         $poidsSurPalette $data['poidsSurPalette']; //poids palette
  282.         $departementSurPalette $data['departementSurPalette']; //département palette
  283.         $departementSurPalettetext $data['departementSurPalettetext']; //département palette text
  284.         $montantTransport 0;
  285.         $montantEmballage 0;
  286.         $montantAssurance 0;
  287.         $montantTaxe 0;
  288.         $montantOptions 0;
  289.         $montantCaisseEnBois 0;
  290.         $montantSurPalette 0;
  291.         // Espace variables pour PDF
  292.         $nomAssurrance "";
  293.         $nomEmballage "";
  294.         $assuranceComp "";
  295.         $nomLivraison "";
  296.         $descLivraison "";
  297.         // On récupére le total des bouteilles
  298.         $calculateTotalBottles $this->calculateTotalBottles($recap);
  299.         // Traitement de l'asssurance
  300.         if (!empty($checkedAssurances)) {
  301.             $assuranceIdFront $checkedAssurances[0];
  302.             $assuranceComp $this->assuranceRepository->findOneById($assuranceIdFront);
  303.             $montantAssurance $montantValeur * ($assuranceComp->getTaux() / 100);
  304.             $nomAssurrance $assuranceComp->getTitre();
  305.         }
  306.         if (!empty($checkedEmballages)) {
  307.             $emballageIdFront $checkedEmballages[0];
  308.             $emballageChoisi $this->fournitureCategorieRepository->findOneById($emballageIdFront);
  309.             // Trier par nbBouteille
  310.             $itemsByNbBouteille $this->fournitureItemRepository->findPartByCategorieAndNbBouteilleDesc($emballageIdFront);
  311.             // Trier par nbMagnum
  312.             $itemsByNbMagnum $this->fournitureItemRepository->findPartByCategorieAndNbMagnumDesc($emballageIdFront);
  313.             // Trier par nbJeroboam
  314.             $itemsByNbJeroboam $this->fournitureItemRepository->findPartByCategorieAndNbJeroboamDesc($emballageIdFront);
  315.             $tableauReturnTarifs $this->calculateTarifs($recap$itemsByNbBouteille$itemsByNbMagnum$itemsByNbJeroboam);
  316.             $montantEmballage $tableauReturnTarifs['montant_total'];
  317.             $nomEmballage $emballageChoisi->getTitre() . ' - ' $emballageChoisi->getSousTitre() . ' - ' $emballageChoisi->getMarque();
  318.         }
  319.         $zone $pays->getZone();
  320.         if (!empty($checkedLivraisons)) {
  321.             $livraisonIdFront $checkedLivraisons[0];
  322.             $typeTarif $this->typeTarifsRepository->findOneById($livraisonIdFront);
  323.             $nomLivraison $typeTarif->getTitre();
  324.             $descLivraison $typeTarif->getDescription();
  325.             // On récupère les quantités bouteilles potentielles
  326.             $quantiteBouteilleLaPlusProche $this->quantiteBouteilleRepository->findPartByBottleCountAndZone($calculateTotalBottles$zone->getId());
  327.             if ($pays->getNom() == "France") {
  328.                 $message "Il n'est pas possible d'envoyer cette quantité de bouteilles pour ce pays et avec cet emballage. 
  329.                 Vous pouvez  configurer le <a href='#' id='transport_palette'>transport par palette</a>.
  330.                 <br> Sinon, vous pouvez consulter l'offre complète avec les différentes restrictions ci-dessous.";
  331.             } else {
  332.                 $message "Il n'est pas possible d'envoyer cette quantité de bouteilles pour ce pays et avec cet emballage. <br> Vous pouvez consulter l'offre complète avec les différentes restrictions ci-dessous.";
  333.             }
  334.             if ($quantiteBouteilleLaPlusProche == null) {
  335.                 if ($calculateTotalBottles 0) { 
  336.                     //si france, on regarde si l'option palette a été utilisée
  337.                     if ($pays->getNom() == "France") {
  338.                         if ($checkedSurPalette) {
  339.                             //si le poids et le département sont remplis (France seulement)
  340.                             if (!empty($poidsSurPalette) and (!empty($departementSurPalette))) {
  341.                                 $montantSurPalette $this->getMontantPaletteByDepartement($poidsSurPalette$departementSurPalette);
  342.                                 //si le montent existe on écrase montantTransport
  343.                                 $montantTransport $montantSurPalette;
  344.                             } else {
  345.                                 $errors[] = $message;
  346.                             }
  347.                         } else {
  348.                             $errors[] = $message;
  349.                         }
  350.                     } else {
  351.                         $errors[] = $message;
  352.                     }
  353.                 }
  354.             } else {
  355.                 $montantTransportObject $this->tarifRepository->findPartByTypeTarifAndQuantiteBouteille($typeTarif->getId(), $quantiteBouteilleLaPlusProche[0]->getId());
  356.                 $montantTransport $montantTransportObject->getMontant();
  357.             }
  358.         }
  359.         if ($checkedCaisseEnBois) {
  360.             $totalBouteillesClassiques $this->calculateTotalBottlesClassique($recap);
  361.             /*
  362.             * lots_of_12
  363.             * lots_of_6
  364.             * remaining_bottles
  365.             * total_costs        
  366.             */
  367.             $aCaisseEnBoisCalcul $this->calculateCaisseEnBois($totalBouteillesClassiques$zone->getCaisseBoisMontantBouteillesDouze(), $zone->getCaisseBoisMontantBouteilleSix());
  368.             $montantCaisseEnBois $aCaisseEnBoisCalcul["total_costs"];
  369.         }
  370.         if ($checkedDeliveredDutyPaid) {
  371.             $montantOptions $montantOptions $this->montantDeliveredDutyPaid;
  372.         }
  373.         if ($checkedSurPalette) {
  374.             //si le poids et le département sont remplis (France seulement)
  375.             if (!empty($poidsSurPalette) and (!empty($departementSurPalette))) {
  376.                 $montantSurPalette $this->getMontantPaletteByDepartement($poidsSurPalette$departementSurPalette);
  377.                 //si le montent existe on écrase montantTransport
  378.                 $montantTransport $montantSurPalette;
  379.             }
  380.         }
  381.         $montantTaxe $this->handleCountryById($pays->getId(), $montantValeur$calculateTotalBottles$montantTransport);
  382.         if ($montantTaxe == null) {
  383.             $montantTaxe 0;
  384.         } else {
  385.             $montantTaxe $montantTaxe["montantAvecMarge"];
  386.         }
  387.         $montantTotal $montantTransport $montantEmballage $montantAssurance $montantTaxe $montantOptions $montantCaisseEnBois/* + $montantSurPalette*/;
  388.         $aReturnDonnee = array();
  389.         $aReturnDonnee["montantTransport"] = $montantTransport;
  390.         $aReturnDonnee["montantEmballage"] = $montantEmballage;
  391.         $aReturnDonnee["montantAssurance"] = $montantAssurance;
  392.         $aReturnDonnee["montantTaxe"] = $montantTaxe;
  393.         $aReturnDonnee["montantOptions"] = $montantOptions;
  394.         $aReturnDonnee["montantCaisseEnBois"] = $montantCaisseEnBois;
  395.         $aReturnDonnee["montantTotal"] = $montantTotal;
  396.         $aReturnDonnee["isAssujettiTva"] = $isAssujettiTva;
  397.         $aReturnDonnee["errors"] = $errors;
  398.         $aReturnDonnee["nomAssurrance"] = $nomAssurrance;
  399.         $aReturnDonnee["nomEmballage"] = $nomEmballage;
  400.         $aReturnDonnee["montantSurPalette"] = $montantSurPalette;
  401.         $aReturnDonnee["montantValeur"] = $montantValeur;
  402.         $aReturnDonnee["assuranceComp"] = $assuranceComp;
  403.         $aReturnDonnee["nomLivraison"] = $nomLivraison;
  404.         $aReturnDonnee["descLivraison"] = $descLivraison;
  405.         $aReturnDonnee["poidsSurPalette"] = $poidsSurPalette;
  406.         $aReturnDonnee["departementSurPalettetext"] = $departementSurPalettetext;
  407.         return $aReturnDonnee;
  408.     }
  409.     // Fonction permettant de calculer le nombre de bouteilles (3L = 4, 1.5L = 2, 0.75L = 1, 0.5L = 1)
  410.     function calculateTotalBottles(array $recap): int
  411.     {
  412.         // Définitions des équivalences volume => nombre de bouteilles
  413.         $volumeToBottleCount = [
  414.             "0.5" => 1,
  415.             "0.75" => 1,
  416.             "1.5" => 2,
  417.             "3" => 4
  418.         ];
  419.         $totalBottles 0;
  420.         // Parcourir le tableau de récap
  421.         foreach ($recap as $volume => $quantity) {
  422.             // Vérifier si le volume existe dans les équivalences
  423.             if (isset($volumeToBottleCount[$volume])) {
  424.                 // Multiplier la quantité par le nombre de bouteilles correspondant au volume
  425.                 $totalBottles += $quantity $volumeToBottleCount[$volume];
  426.             }
  427.         }
  428.         return $totalBottles;
  429.     }
  430.     // Fonction permettant de retourner le tarif en fonction du poids et du departement (France seulement)
  431.     function getMontantPaletteByDepartement($poids$departement): float
  432.     {
  433.         //on va chercher le resultat dans le repository
  434.         $tarif $this->ZoneDepartementsPoidsRepository->findOneByPoidsAndDepartement($poids$departement);
  435.         if ($tarif == null) {
  436.             return 0;
  437.         }
  438.         return $tarif->getMontant();
  439.     }
  440.     // Fonction permettant de calculer le nombre de bouteilles de 0.75L
  441.     function calculateTotalBottlesClassique(array $recap): int
  442.     {
  443.         $totalBottles 0;
  444.         // Parcourir le tableau de récap
  445.         foreach ($recap as $volume => $quantity) {
  446.             // Vérifier si c'est le volume 0.75
  447.             if ($volume == "0.75") {
  448.                 $totalBottles += $quantity;
  449.             }
  450.         }
  451.         return $totalBottles;
  452.     }
  453.     // Fonction permettant de calculer le volume de bouteilles (3L = 4, 1.5L = 2, 0.75L = 1, 0.5L = 1)
  454.     function calculateVolumeBottles(array $recap): float
  455.     {
  456.         $volumeTotal 0;
  457.         // Parcourir le tableau de récap
  458.         foreach ($recap as $volume => $quantity) {
  459.             $volumeTotal += $quantity $volume;
  460.         }
  461.         return $volumeTotal;
  462.     }
  463.     // Fonction permettant de calculer les tarifs en dégressif suivant le nombre de bouteilles
  464.     function calculateTarifs($recap$itemsByNbBouteille$itemsByNbMagnum$itemsByNbJeroboam)
  465.     {
  466.         $result = [];
  467.         $totalCost 0// Montant final global
  468.         // Parcourir chaque volume dans le récapitulatif
  469.         foreach ($recap as $volume => $totalBottles) {
  470.             $volumeResult = [
  471.                 'volume' => $volume,
  472.                 'nb_bouteille' => 0,
  473.                 'nb_magnum' => 0,
  474.                 'nb_jeroboam' => 0,
  475.                 'tarif_details' => [],
  476.                 'montant_volume' => // Montant total pour ce volume
  477.             ];
  478.             // Sélectionner les items appropriés en fonction du volume
  479.             $items = [];
  480.             if ($volume == '0.75' || $volume == '0.5') {
  481.                 $items $itemsByNbBouteille;
  482.             } elseif ($volume == '1.5') {
  483.                 $items $itemsByNbMagnum;
  484.             } elseif ($volume == '3') {
  485.                 $items $itemsByNbJeroboam;
  486.             }
  487.             // Parcourir les items triés pour emballer les bouteilles
  488.             foreach ($items as $item) {
  489.                 $nbBouteillesParCarton $item->getNbBouteille() ?? $item->getNbMagnum() ?? $item->getNbJeroboam();
  490.                 $montantUnitaire $item->getMontantUnitaire();
  491.                 while ($totalBottles >= $nbBouteillesParCarton) {
  492.                     $volumeResult['tarif_details'][] = [
  493.                         'montant_unitaire' => $montantUnitaire,
  494.                         'nb_bouteilles' => $nbBouteillesParCarton
  495.                     ];
  496.                     $totalBottles -= $nbBouteillesParCarton;
  497.                     // Ajouter au montant total pour ce volume
  498.                     $volumeResult['montant_volume'] += $montantUnitaire;
  499.                     // Incrementer les compteurs correspondants
  500.                     if ($volume == '0.75' || $volume == '0.5') {
  501.                         $volumeResult['nb_bouteille'] += $nbBouteillesParCarton;
  502.                     } elseif ($volume == '1.5') {
  503.                         $volumeResult['nb_magnum'] += $nbBouteillesParCarton;
  504.                     } elseif ($volume == '3') {
  505.                         $volumeResult['nb_jeroboam'] += $nbBouteillesParCarton;
  506.                     }
  507.                 }
  508.             }
  509.             // Si des bouteilles restantes ne trouvent pas d'emballage
  510.             if ($totalBottles 0) {
  511.                 $volumeResult['tarif_details'][] = [
  512.                     'montant_unitaire' => null,
  513.                     'nb_bouteilles' => $totalBottles
  514.                 ];
  515.                 if ($volume == '0.75' || $volume == '0.5') {
  516.                     $volumeResult['nb_bouteille'] += $totalBottles;
  517.                 } elseif ($volume == '1.5') {
  518.                     $volumeResult['nb_magnum'] += $totalBottles;
  519.                 } elseif ($volume == '3') {
  520.                     $volumeResult['nb_jeroboam'] += $totalBottles;
  521.                 }
  522.             }
  523.             // Ajouter le montant de ce volume au montant total global
  524.             $totalCost += $volumeResult['montant_volume'];
  525.             $result[] = $volumeResult;
  526.         }
  527.         return [
  528.             'result' => $result,
  529.             'montant_total' => $totalCost
  530.         ];
  531.     }
  532.     // Permet de calculer le nombre de caisse en bois
  533.     function calculateCaisseEnBois($totalBottles$pricePer12$pricePer6)
  534.     {
  535.         if ($totalBottles <= 0) {
  536.             return [
  537.                 'lots_of_12' => 0,
  538.                 'lots_of_6' => 0,
  539.                 'remaining_bottles' => 0,
  540.                 'total_cost' => 0
  541.             ];
  542.         }
  543.         // Calculer les lots de 12 bouteilles
  544.         $lotsOf12 intdiv($totalBottles12);
  545.         $remainingAfter12 $totalBottles 12;
  546.         // Calculer les lots de 6 bouteilles avec le reste
  547.         $lotsOf6 intdiv($remainingAfter126);
  548.         $remainingBottles $remainingAfter12 6;
  549.         // Calculer le montant total
  550.         $totalCost = ($lotsOf12 $pricePer12) + ($lotsOf6 $pricePer6);
  551.         //dd($lotsOf12);
  552.         return [
  553.             'lots_of_12' => $lotsOf12,
  554.             'lots_of_6' => $lotsOf6,
  555.             'remaining_bottles' => $remainingBottles,
  556.             'total_costs' => $totalCost
  557.         ];
  558.     }
  559.     function handleCountryById(int $idfloat $totalInvoiceint $numberOfBottlesfloat $transportCost)
  560.     {
  561.         //fix taxe : on va chercher le min ID du pays
  562.         $pays $this->paysRepository->findOneById($id);
  563.         $old_pays $this->paysRepository->findMinIdByName($pays->getNom());
  564.         if ($old_pays != null) {
  565.             $min_id $old_pays['id'];
  566.         } else {
  567.             $min_id $id;
  568.         }
  569.         // Vérification et appel de la méthode correspondante
  570.         if (in_array($min_id$this->aRoyaumeUniId)) {
  571.             return $this->calculTaxeService->calculateRoyaumeUni($totalInvoice$numberOfBottles);
  572.         } elseif (in_array($min_id$this->aSuisseId)) {
  573.             return $this->calculTaxeService->calculateSuisse($totalInvoice$numberOfBottles);
  574.         } elseif (in_array($min_id$this->aNorvegeId)) {
  575.             return $this->calculTaxeService->calculateNorvege($totalInvoice$numberOfBottles$transportCost);
  576.         } elseif (in_array($min_id$this->aAustralieId)) {
  577.             return $this->calculTaxeService->calculateAustralie($totalInvoice$numberOfBottles$transportCost);
  578.         } elseif (in_array($min_id$this->aNouvelleZelandeId)) {
  579.             return $this->calculTaxeService->calculateNouvelleZelande($totalInvoice$numberOfBottles$transportCost);
  580.         } elseif (in_array($min_id$this->aSingapourId)) {
  581.             return $this->calculTaxeService->calculateSingapour($totalInvoice$numberOfBottles);
  582.         } elseif (in_array($min_id$this->aCoreeSudId)) {
  583.             return $this->calculTaxeService->calculateCoreeSud($totalInvoice$numberOfBottles$transportCost);
  584.         } elseif (in_array($min_id$this->aJaponId)) {
  585.             return $this->calculTaxeService->calculateJapon($totalInvoice$numberOfBottles$transportCost);
  586.         } elseif (in_array($min_id$this->aTaiwanId)) {
  587.             return $this->calculTaxeService->calculateTaiwan($totalInvoice$numberOfBottles$transportCost);
  588.         }
  589.         return null;
  590.     }
  591. }