src/Controller/EntrepriseController.php line 728

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\CSPE;
  4. use App\Entity\Note;
  5. use App\Entity\User;
  6. use App\Entity\Rappel;
  7. use App\Entity\Contact;
  8. use App\Entity\Contrat;
  9. use App\Entity\GasMeter;
  10. use App\Entity\Entreprise;
  11. use App\Entity\EspaceClient;
  12. use App\Entity\ElectricMeter;
  13. use App\Form\EntrepriseType;
  14. use App\Form\ContratType;
  15. use App\Form\UserEntrepriseType;
  16. use App\Service\PricingService;
  17. use App\Repository\EntrepriseRepository;
  18. use Symfony\Contracts\HttpClient\HttpClientInterface;
  19. use Doctrine\Persistence\ManagerRegistry;
  20. use Doctrine\ORM\EntityManagerInterface;
  21. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  22. use Symfony\Component\HttpFoundation\Request;
  23. use Symfony\Component\HttpFoundation\Response;
  24. use Symfony\Component\HttpFoundation\JsonResponse;
  25. use Symfony\Component\Routing\Annotation\Route;
  26. use Symfony\Component\Security\Core\Exception\InvalidCsrfTokenException;
  27. use Psr\Log\LoggerInterface;
  28. class EntrepriseController extends AbstractController
  29. {
  30.     private $pricingService;
  31.     private $logger;
  32.     public function __construct(PricingService $pricingServiceLoggerInterface $logger)
  33.     {
  34.         $this->pricingService $pricingService;
  35.         $this->logger $logger;
  36.     }
  37.     /**
  38.      * @Route("/entreprise", name="app_entreprise")
  39.      */
  40.     // ...
  41.     public function index(ManagerRegistry $doctrine): Response
  42.     {
  43.     $em $doctrine->getManager();
  44.     // ---- ENTREPRISES ----
  45.     /** @var Entreprise[] $entreprises */
  46.     $entreprises $em->getRepository(Entreprise::class)->findAll();
  47.     $entrepriseIds array_map(fn($e)=>$e->getId(), $entreprises);
  48.     // Map Entreprise -> Users 
  49.     $allUserIds = [];
  50.     foreach ($entreprises as $e) {
  51.         foreach ((array)$e->getUtilisateur() as $uid) {
  52.             if ($uid !== null && $uid !== ''$allUserIds[(int)$uid] = true;
  53.             $eid $e->getId();
  54.         }
  55.     }
  56.     $allUserIds array_keys($allUserIds);
  57.     $usersById = [];
  58.     if ($allUserIds) {
  59.         $users $em->createQueryBuilder()
  60.             ->select('u.id, u.username')
  61.             ->from(User::class, 'u')
  62.             ->where('u.id IN (:ids)')->setParameter('ids'$allUserIds)
  63.             ->getQuery()->getArrayResult();
  64.         foreach ($users as $u) {
  65.             $usersById[(int)$u['id']] = $u['username'];
  66.         }
  67.     }
  68.     // Contacts pour toutes les entreprises en 1 requête
  69.     $contactsByEntreprise = [];
  70.     if ($entrepriseIds) {
  71.         $rows $em->createQueryBuilder()
  72.             ->select('c.entreprise_id AS eid, c.nom AS nom, c.prenom AS prenom')
  73.             ->from(Contact::class, 'c')
  74.             ->where('c.entreprise_id IN (:ids)')->setParameter('ids'$entrepriseIds)
  75.             ->getQuery()->getArrayResult();
  76.         foreach ($rows as $r) {
  77.             $eid = (int)$r['eid'];
  78.             $contactsByEntreprise[$eid][] = trim(($r['nom'] ?? '').' '.($r['prenom'] ?? ''));
  79.         }
  80.     }
  81.     // Compteurs élec/gaz pour toutes les entreprises en 2 requêtes
  82.     $elecByEntreprise $gazByEntreprise = [];
  83.     $electricMeters $em->createQueryBuilder()
  84.         ->select('em.entreprise_id AS eid, em.PDL AS pdl')
  85.         ->from(ElectricMeter::class, 'em')
  86.         ->where('em.entreprise_id IN (:ids)')->setParameter('ids',$entrepriseIds)
  87.         ->getQuery()->getArrayResult();
  88.     foreach ($electricMeters as $r) {
  89.         $elecByEntreprise[(int)$r['eid']][] = $r['pdl'];
  90.     }
  91.     $gasMeters $em->createQueryBuilder()
  92.         ->select('gm.entreprise_id AS eid, gm.PDL AS pdl')
  93.         ->from(GasMeter::class, 'gm')
  94.         ->where('gm.entreprise_id IN (:ids)')->setParameter('ids',$entrepriseIds)
  95.         ->getQuery()->getArrayResult();
  96.     foreach ($gasMeters as $r) {
  97.         $gazByEntreprise[(int)$r['eid']][] = $r['pdl'];
  98.     }
  99.     // Construire le tableau ENTREPRISES
  100.     $array_entreprises = [];
  101.     foreach ($entreprises as $e) {
  102.         $eid $e->getId();
  103.         $usernames = [];
  104.         foreach ((array)$e->getUtilisateur() as $uid) {
  105.             $uid = (int)$uid;
  106.             if (isset($usersById[$uid])) $usernames[] = $usersById[$uid];
  107.         }
  108.         $entreprise_contacts = isset($contactsByEntreprise[$eid]) ? implode(' '$contactsByEntreprise[$eid]) : '';
  109.         $allPdls implode(' 'array_merge($elecByEntreprise[$eid] ?? [], $gazByEntreprise[$eid] ?? []));
  110.         $array_entreprises[] = [
  111.             $e->getRaisonSociale(),
  112.             $e->getCommune(),
  113.             $e->getSiret(),
  114.             $entreprise_contacts,
  115.             implode(', '$usernames),
  116.             '<div class="d-flex justify-content-center gap-2">
  117.                 <a href="'.$this->generateUrl('app_entreprise_details',['id' => $eid]).'" class="btn btn-sm btn-primary"><i class="fa-solid fa-eye"></i></a>
  118.                 <a href="'.$this->generateUrl('app_entreprise_edit',['id' => $eid]).'" class="btn btn-sm btn-warning"><i class="fa-solid fa-screwdriver-wrench"></i></a>
  119.                 <a href="'.$this->generateUrl('app_entreprise_suppr',['id' => $eid]).'" class="btn btn-sm btn-danger"><i class="fa-solid fa-trash"></i></a>
  120.             </div>',
  121.             $allPdls,
  122.             $e->getNaf(),
  123.             $eid,
  124.         ];
  125.         
  126.     }
  127.     // ---- CONTRATS ----
  128.     /** @var Contrat[] $contrats */
  129.     $contrats $em->getRepository(Contrat::class)->findAll();
  130.     // Préparer détection type (liste PDL elec/gaz en 2 requêtes scalaires)
  131.     $electricPDLs array_column(
  132.         $em->createQueryBuilder()->select('em.PDL AS p')->from(ElectricMeter::class,'em')->getQuery()->getScalarResult(),
  133.         'p'
  134.     );
  135.     $gasPDLs array_column(
  136.         $em->createQueryBuilder()->select('gm.PDL AS p')->from(GasMeter::class,'gm')->getQuery()->getScalarResult(),
  137.         'p'
  138.     );
  139.     $isElec array_fill_keys($electricPDLstrue);
  140.     $isGaz  array_fill_keys($gasPDLstrue);
  141.     // ---- PDLs (élec/gaz) + last contrat pour CHAQUE PDL en 1 requête ----
  142.     // 1) récupérer tous les PDL connus des compteurs
  143.     $allMeterPDLs array_merge($electricPDLs$gasPDLs);
  144.     $allMeterPDLs array_values(array_unique(array_filter($allMeterPDLs)));
  145.     // Map Entreprise (id => raison sociale) pour éviter des find()
  146.     $rsById = [];
  147.     foreach ($entreprises as $e) { $rsById[$e->getId()] = $e->getRaisonSociale(); }
  148.     // 2) récupérer TOUS les contrats pour ces PDL, triés pdl, dateDebut DESC
  149.     $contractsByPdl   = [];
  150.     $lastContratByPdl = [];  
  151.     if ($allMeterPDLs) {
  152.         $allC $em->createQueryBuilder()
  153.             ->select('c.id, c.pdl, c.date_debut AS dateDebut, c.date_fin AS dateFin, c.fournisseur, e.id AS eid')
  154.             ->from(Contrat::class, 'c')
  155.             ->leftJoin('c.entreprise''e')
  156.             ->where('c.pdl IN (:pdls)')->setParameter('pdls'$allMeterPDLs)
  157.             ->orderBy('c.pdl''ASC')
  158.             ->addOrderBy('c.date_debut''DESC')
  159.             ->getQuery()->getArrayResult();
  160.         foreach ($allC as $row) {
  161.             $p = (string)$row['pdl'];
  162.             $eid $row['eid'] ?? null;
  163.             $cid = isset($row['id']) ? (int)$row['id'] : null;
  164.             
  165.             $contractsByPdl[$p][] = [
  166.                 'id'          => (int)$row['id'],
  167.                 'entreprise'  => $eid && isset($rsById[$eid]) ? $rsById[$eid] : 'entreprise supprimée',
  168.                 'eid'         => $eid,
  169.                 'dateDebut'   => $row['dateDebut'] instanceof \DateTimeInterface $row['dateDebut']->format('d/m/Y') : '',
  170.                 'dateFin'     => $row['dateFin']   instanceof \DateTimeInterface $row['dateFin']->format('d/m/Y')   : '',
  171.                 'fournisseur' => $row['fournisseur'] ?? '',
  172.                 'viewUrl'   => $eid $this->generateUrl('app_entreprise_details', ['id' => $eid]) : null,
  173.                 'editUrl'   => ($eid && $cid) ? $this->generateUrl('app_entreprise_edit_contrat', [
  174.                                     'entrepriseId' => $eid'id' => $cid
  175.                                 ]) : null,
  176.                 'deleteUrl' => ($eid && $cid) ? $this->generateUrl('app_entreprise_delete_contrat', [
  177.                                     'entrepriseId' => $eid'id' => $cid
  178.                         ]) : null,
  179.             ];
  180.             // Mémoriser le plus récent par PDL (premier vu car trié date_debut DESC)
  181.             if (!isset($lastContratByPdl[$p])) {
  182.                 $lastContratByPdl[$p] = $row;
  183.             }
  184.         }
  185.     }
  186.     // Table CONTRATS (pas de continue: on garde "entreprise supprimée")
  187.     $array_contrats = [];
  188.     foreach ($contrats as $contrat) {
  189.         $ent $contrat->getEntreprise();
  190.         $raisonSociale $ent ? ($rsById[$ent->getId()] ?? 'entreprise supprimée') : 'entreprise supprimée';
  191.         $pdl $contrat->getPdl();
  192.         $profil ''$fournisseur $contrat->getFournisseur() ?? '';
  193.         // On essaye de prendre profil/fournisseur depuis compteur si besoin (optionnel)
  194.         if ($pdl) {
  195.             if (isset($isElec[$pdl])) {
  196.                 // si tu veux enrichir, fais-le par requête groupée comme plus haut
  197.             } elseif (isset($isGaz[$pdl])) {
  198.                 // idem
  199.             }
  200.         }
  201.         // Pastille statut
  202.         $dateFin $contrat->getDateFin();
  203.         if (!$dateFin) {
  204.             $statut '<span class="status-dot status-blue"></span>';
  205.         } else {
  206.             $daysRemaining = (int)((new \DateTime())->diff($dateFin))->format('%r%a');
  207.             $class $daysRemaining 180 'status-green' : ($daysRemaining 90 'status-orange' 'status-red');
  208.             $statut '<span class="status-dot '.$class.'"></span>';
  209.         }
  210.         // Type contrat via PDL
  211.         $type $pdl ? (isset($isElec[$pdl]) ? 'elec' : (isset($isGaz[$pdl]) ? 'gaz' '')) : '';
  212.         $actionButtons = ($ent)
  213.             ? '<div class="d-flex justify-content-center gap-2">
  214.                 <a href="'.$this->generateUrl('app_entreprise_edit_contrat', [
  215.                     'entrepriseId' => $ent->getId(),
  216.                     'id' => $contrat->getId()
  217.                 ]).'" class="btn btn-sm btn-warning" title="Modifier"><i class="fa-solid fa-screwdriver-wrench"></i></a>
  218.                 <a href="'.$this->generateUrl('app_entreprise_delete_contrat', [
  219.                     'entrepriseId' => $ent->getId(),
  220.                     'id' => $contrat->getId()
  221.                 ]).'" class="btn btn-sm btn-danger" title="Supprimer"><i class="fa-solid fa-trash"></i></a>
  222.                </div>'
  223.             '';
  224.         $array_contrats[] = [
  225.             $raisonSociale,
  226.             $contrat->getDateDebut() ? $contrat->getDateDebut()->format('d/m/Y') : null,
  227.             $contrat->getDateFin()   ? $contrat->getDateFin()->format('d/m/Y')   : null,
  228.             $profil,
  229.             $fournisseur,
  230.             $statut,
  231.             $actionButtons,
  232.             $type
  233.         ];
  234.     }
  235.     // ---- PDLs ÉLECTRIQUES  ----
  236.     $elecFull $em->createQueryBuilder()
  237.         ->select('
  238.             em.id,
  239.             em.entreprise_id AS eid,
  240.             em.adresse_compteur AS adresseCompteur,
  241.             em.PDL,
  242.             em.date_debut AS dateDebut,
  243.             em.date_fin AS dateFin,
  244.             em.Profil AS profil,
  245.             em.CAR,
  246.             em.fournisseur,
  247.             em.prix
  248.         ')
  249.         ->from(ElectricMeter::class, 'em')
  250.         ->getQuery()->getArrayResult();
  251.     $pdls_elec = [];
  252.     foreach ($elecFull as $m) {
  253.         $eid = (int)$m['eid'];
  254.         $last $lastContratByPdl[$m['PDL']] ?? null;
  255.         $lastFin null;
  256.         if ($last && !empty($last['dateFin'])) $lastFin $last['dateFin'];
  257.         elseif (!empty($m['dateFin'])) $lastFin $m['dateFin'];
  258.         $statut '<span class="status-dot status-blue"></span>';
  259.         if ($lastFin instanceof \DateTimeInterface) {
  260.             $dRest = (int)((new \DateTime())->diff($lastFin))->format('%r%a');
  261.             $class $dRest 180 'status-green' : ($dRest 90 'status-orange' 'status-red');
  262.             $statut '<span class="status-dot '.$class.'"></span>';
  263.         }
  264.         $actionButtons =
  265.             '<div class="d-flex justify-content-center gap-2">
  266.                 <a href="'.$this->generateUrl('app_electric_meter_edit',['id'=>$m['id']]).'" class="btn btn-sm btn-warning" title="Modifier"><i class="fa-solid fa-screwdriver-wrench"></i></a>
  267.                 <a href="'.$this->generateUrl('app_electric_meter_suppr',['id'=>$m['id']]).'" class="btn btn-sm btn-danger" title="Supprimer"><i class="fa-solid fa-trash"></i></a>
  268.             </div>';
  269.         $pdls_elec[] = [
  270.             $rsById[$eid] ?? '',
  271.             $m['adresseCompteur'],
  272.             $m['PDL'],
  273.             $m['dateDebut'] instanceof \DateTimeInterface $m['dateDebut']->format('d/m/Y') : '',
  274.             $lastFin instanceof \DateTimeInterface $lastFin->format('d/m/Y') : '',
  275.             $statut,
  276.             $m['profil'],
  277.             $m['CAR'],
  278.             $last['fournisseur'] ?? $m['fournisseur'] ?? '',
  279.             $m['prix'],
  280.             $actionButtons,
  281.         ];
  282.     }
  283.     // ---- PDLs GAZ  ----
  284.     $gazFull $em->createQueryBuilder()
  285.         ->select('
  286.             gm.id,
  287.             gm.entreprise_id AS eid,
  288.             gm.adresse_compteur AS adresseCompteur,
  289.             gm.PDL,
  290.             gm.date_debut AS dateDebut,
  291.             gm.date_fin   AS dateFin,
  292.             gm.profil     AS profil,
  293.             gm.CAR,
  294.             gm.fournisseur,
  295.             gm.prix
  296.         ')
  297.         ->from(GasMeter::class, 'gm')
  298.         ->getQuery()->getArrayResult();
  299.     $pdls_gaz = [];
  300.     foreach ($gazFull as $m) {
  301.         $eid = (int)$m['eid'];
  302.         $last $lastContratByPdl[$m['PDL']] ?? null;
  303.         $lastFin null;
  304.         if ($last && !empty($last['dateFin'])) $lastFin $last['dateFin'];
  305.         elseif (!empty($m['dateFin'])) $lastFin $m['dateFin'];
  306.         $statut '<span class="status-dot status-blue"></span>';
  307.         if ($lastFin instanceof \DateTimeInterface) {
  308.             $dRest = (int)((new \DateTime())->diff($lastFin))->format('%r%a');
  309.             $class $dRest 180 'status-green' : ($dRest 90 'status-orange' 'status-red');
  310.             $statut '<span class="status-dot '.$class.'"></span>';
  311.         }
  312.         $actionButtons =
  313.             '<div class="d-flex justify-content-center gap-2">
  314.                 <a href="'.$this->generateUrl('app_gas_meter_edit',['id'=>$m['id']]).'" class="btn btn-sm btn-warning" title="Modifier"><i class="fa-solid fa-screwdriver-wrench"></i></a>
  315.                 <a href="'.$this->generateUrl('app_gas_meter_suppr',['id'=>$m['id']]).'" class="btn btn-sm btn-danger" title="Supprimer"><i class="fa-solid fa-trash"></i></a>
  316.             </div>';
  317.         $pdls_gaz[] = [
  318.             $rsById[$eid] ?? '',
  319.             $m['adresseCompteur'],
  320.             $m['PDL'],
  321.             $m['dateDebut'] instanceof \DateTimeInterface $m['dateDebut']->format('d/m/Y') : '',
  322.             $lastFin instanceof \DateTimeInterface $lastFin->format('d/m/Y') : '',
  323.             $statut,
  324.             $m['profil'],
  325.             $m['CAR'],
  326.             $last['fournisseur'] ?? $m['fournisseur'] ?? '',
  327.             $m['prix'],
  328.             $actionButtons,
  329.         ];
  330.     }
  331.     // ---- INTERVALLES DE CONTRATS PAR ENTREPRISE (INDEX DE MOIS) ----
  332.     // Axe fixe : 2010-01 -> 2050-12
  333.     $ORIGIN = new \DateTime('2010-01-01 00:00:00');
  334.     $END    = new \DateTime('2050-12-31 00:00:00');
  335.     // Liste PDL gaz déjà dispo plus haut : $isGaz (array_flip des PDL gaz)
  336.     $companyMonthIntervals = []; // [eid => [[mStart, mEnd], ...] inclusifs]
  337.     /**
  338.      * Convertit une date -> index de mois depuis 2010-01 (0 = 2010-01).
  339.      */
  340.     $monthIndex = function(\DateTimeInterface $d): int {
  341.         $y = (int)$d->format('Y');
  342.         $m = (int)$d->format('n'); // 1..12
  343.         return ($y 2010) * 12 + ($m 1);
  344.     };
  345.     // Bornes de coupe
  346.     $minIndex $monthIndex($ORIGIN);
  347.     $maxIndex $monthIndex($END);
  348.     foreach ($contrats as $contrat) {
  349.         $ent $contrat->getEntreprise();
  350.         if (!$ent) { continue; }
  351.         $start $contrat->getDateDebut();
  352.         $end   $contrat->getDateFin();
  353.         if (!$start) { continue; } // sans début => on ignore
  354.         $start = (clone $start)->setTime(0,0,0);
  355.         // Gaz : +1 jour sur la date de début
  356.         $pdl $contrat->getPdl();
  357.         if ($pdl && isset($isGaz[$pdl])) {
  358.             $start->modify('+1 day');
  359.         }
  360.         // Fin ouverte => on borne à END
  361.         $end $end ? (clone $end)->setTime(0,0,0) : clone $END;
  362.         // Clamp aux bornes 2010-01..2050-12
  363.         if ($end $ORIGIN || $start $END) { continue; }
  364.         if ($start $ORIGIN) { $start = clone $ORIGIN; }
  365.         if ($end   $END)    { $end   = clone $END; }
  366.         $mA $monthIndex($start);
  367.         $mB $monthIndex($end);
  368.         // inclusif : si même mois début/fin, l’intervalle couvre ce mois
  369.         if ($mA $mB) { continue; }
  370.         $eid $ent->getId();
  371.         $companyMonthIntervals[$eid][] = [$mA$mB];
  372.     }
  373.     // Fusion par entreprise (tri + merge des contigus)
  374.     foreach ($companyMonthIntervals as $eid => $list) {
  375.         if (!$list) continue;
  376.         usort($list, fn($x,$y) => $x[0] <=> $y[0]);
  377.         $merged = [];
  378.         [$a,$b] = $list[0];
  379.         foreach ($list as [$x,$y]) {
  380.             // contigu si x <= b+1 (mois adjacents)
  381.             if ($x <= $b 1) {
  382.                 if ($y $b$b $y;
  383.             } else {
  384.                 $merged[] = [$a,$b];
  385.                 [$a,$b] = [$x,$y];
  386.             }
  387.         }
  388.         $merged[] = [$a,$b];
  389.         $companyMonthIntervals[$eid] = $merged;
  390.     }
  391.     // Infos axe fixe
  392.     $originYear 2010;
  393.     $originMonth 1;   // janvier
  394.     $endYear 2050;
  395.     $endMonth 12;
  396.     $totalMonths = ($endYear $originYear) * 12 + ($endMonth $originMonth 1); // inclusif
  397.     return $this->render('entreprise/index.html.twig', [
  398.         'entreprises' => $array_entreprises,
  399.         'contrats'    => $array_contrats,
  400.         'pdls_elec'   => $pdls_elec,
  401.         'pdls_gaz'    => $pdls_gaz,
  402.         'contracts_by_pdl' => $contractsByPdl,
  403.         
  404.     // Axe temporel fixe en mois
  405.     'origin_year'          => $originYear,
  406.     'origin_month'         => $originMonth,
  407.     'total_months'         => $totalMonths// ex: (2010-01 .. 2050-12) = 492 mois
  408.     // Intervalles fusionnés par entreprise (indices de mois)
  409.     'merged_month_intervals' => $companyMonthIntervals,
  410.     ]);
  411. }
  412.     /**
  413.      * @Route("/entreprise/calculate-value", name="app_entreprise_calculate_value", methods={"POST"})
  414.      */
  415.     public function calculateValue(Request $requestManagerRegistry $doctrine): JsonResponse
  416.     {
  417.         $this->logger->debug('Received calculate value request', [
  418.             'car' => $request->request->get('car'),
  419.             'dateDebut' => $request->request->get('dateDebut'),
  420.             'dateFin' => $request->request->get('dateFin'),
  421.             'pdl' => $request->request->get('pdl'),
  422.             'raw_request' => $request->request->all()
  423.         ]);
  424.         // Validate CSRF token
  425.         $submittedToken $request->headers->get('X-CSRF-Token');
  426.         if (!$this->isCsrfTokenValid('calculate-value'$submittedToken)) {
  427.             $this->logger->error('Invalid CSRF token');
  428.             return new JsonResponse(['error' => 'Invalid CSRF token'], 403);
  429.         }
  430.         try {
  431.             $car floatval($request->request->get('car'));
  432.             if ($car <= 0) {
  433.                 throw new \InvalidArgumentException('CAR must be greater than 0');
  434.             }
  435.             // Parse dates and set time to start of day
  436.             $dateDebut = new \DateTime($request->request->get('dateDebut'));
  437.             $dateDebut->setTime(000);
  438.             
  439.             $dateFin = new \DateTime($request->request->get('dateFin'));
  440.             $dateFin->setTime(000);
  441.             if ($dateDebut $dateFin) {
  442.                 throw new \InvalidArgumentException('Start date must be before end date');
  443.             }
  444.             // Check if this is a gas contract by looking up the PDL
  445.             $pdl $request->request->get('pdl');
  446.             $isGasContract false;
  447.             if ($pdl) {
  448.                 $gasMeter $doctrine->getRepository(GasMeter::class)->findOneBy(['PDL' => $pdl]);
  449.                 if ($gasMeter) {
  450.                     $isGasContract true;
  451.                     // For gas contracts, adjust the start date
  452.                     $dateDebut->modify('+1 day');
  453.                 }
  454.             }
  455.             // Create a temporary contract object to calculate the value
  456.             $contrat = new Contrat();
  457.             $contrat->setCar($car);
  458.             $contrat->setDateDebut($dateDebut);
  459.             $contrat->setDateFin($dateFin);
  460.             if ($pdl) {
  461.                 $contrat->setPdl($pdl);
  462.             }
  463.             // Calculate the annual value using the pricing service
  464.             $value $this->pricingService->calculateAnnualValue($contrat);
  465.             $this->logger->debug('Calculated contract value', [
  466.                 'car' => $car,
  467.                 'dateDebut' => $dateDebut->format('d/m/Y'),
  468.                 'dateFin' => $dateFin->format('d/m/Y'),
  469.                 'isGasContract' => $isGasContract,
  470.                 'value' => $value
  471.             ]);
  472.             return new JsonResponse([
  473.                 'value' => $value,
  474.                 'debug' => [
  475.                     'car' => $car,
  476.                     'dateDebut' => $dateDebut->format('d/m/Y'),
  477.                     'dateFin' => $dateFin->format('d/m/Y'),
  478.                     'isGasContract' => $isGasContract
  479.                 ]
  480.             ]);
  481.         } catch (\Exception $e) {
  482.             $this->logger->error('Error calculating contract value', [
  483.                 'error' => $e->getMessage(),
  484.                 'trace' => $e->getTraceAsString()
  485.             ]);
  486.             return new JsonResponse(['error' => 'Error calculating value: ' $e->getMessage()], 500);
  487.         }
  488.     }
  489.     /**
  490.      * @Route("/entreprise/add", name="app_entreprise_add")
  491.      */
  492.     public function add(Request $requestEntityManagerInterface $entityManager): Response
  493.     {
  494.         $entreprises = new Entreprise();
  495.         // using createQueryBuilder
  496.         $utilisateurs $entityManager->createQueryBuilder()
  497.             ->select('u')
  498.             ->from(User::class, 'u')
  499.             ->where('u.roles LIKE :roles')
  500.             ->setParameter('roles''%ROLE_TEAM%')
  501.             ->getQuery()
  502.             ->getResult();
  503.         $array_utilisateurs = array();
  504.         for ($i=0$i count($utilisateurs); $i++) { 
  505.             $array_utilisateurs[$utilisateurs[$i]->getUsername()] = $utilisateurs[$i]->getId();
  506.         }
  507.         $form $this->createForm(EntrepriseType::class, $entreprises, ['utilisateurs' => $array_utilisateurs]);
  508.         $form->handleRequest($request);
  509.         if ($form->isSubmitted() && $form->isValid()) {
  510.             $entityManager->persist($entreprises);
  511.             $entityManager->flush();
  512.             return $this->redirectToRoute('app_entreprise');
  513.         }
  514.         return $this->render('entreprise/add.html.twig', [
  515.             'entrepriseForm' => $form->createView(),
  516.             'array_utilisateurs' => $array_utilisateurs,
  517.         ]);
  518.     }
  519.     /**
  520.      * @Route("/entreprise/edit/{id}", name="app_entreprise_edit")
  521.      */
  522.     public function edit(int $idRequest $requestEntityManagerInterface $entityManagerManagerRegistry $doctrine): Response
  523.     {
  524.         $entreprise $doctrine->getRepository(Entreprise::class)->findOneBy(['id' => $id]);
  525.         $utilisateurs $entityManager->createQueryBuilder()
  526.             ->select('u')
  527.             ->from(User::class, 'u')
  528.             ->where('u.roles LIKE :roles')
  529.             ->setParameter('roles''%ROLE_TEAM%')
  530.             ->getQuery()
  531.             ->getResult();
  532.         $array_utilisateurs = array();
  533.         for ($i=0$i count($utilisateurs); $i++) { 
  534.             $array_utilisateurs[$utilisateurs[$i]->getUsername()] = $utilisateurs[$i]->getId();
  535.         }
  536.         $form $this->createForm(EntrepriseType::class, $entreprise, ['utilisateurs' => $array_utilisateurs]);
  537.         $form->handleRequest($request);
  538.         $entreprise_entity = [ 'raison_sociale' => $entreprise->getRaisonSociale(),
  539.             'siret' => $entreprise->getSiret(),
  540.             'naf' => $entreprise->getNaf(),
  541.             'rcs' => $entreprise->getRcs(),
  542.             'num_voie' => $entreprise->getNumVoie(),
  543.             'adresse' => $entreprise->getAdresse(),
  544.             'code_postal' => $entreprise->getCodePostal(),
  545.             'commune' => $entreprise->getCommune(),
  546.             'code_insee' => $entreprise->getCodeInsee(),
  547.             'statut' => $entreprise->getStatut(),
  548.             'utilisateur' => $entreprise->getUtilisateur(),
  549.         ];
  550.         if ($form->isSubmitted() && $form->isValid()) {
  551.             $entreprisesEdit $form->getData();
  552.             if($entreprisesEdit->getRaisonSociale() != null){
  553.                 $entreprise->setRaisonSociale($entreprisesEdit->getRaisonSociale());
  554.             }
  555.             if($entreprisesEdit->getSiret() != null){
  556.                 $entreprise->setSiret($entreprisesEdit->getSiret());
  557.             }
  558.             if($entreprisesEdit->getNaf() != null){
  559.                 $entreprise->setNaf($entreprisesEdit->getNaf());
  560.             }
  561.             if($entreprisesEdit->getRcs() != null){
  562.                 $entreprise->setRcs($entreprisesEdit->getRcs());
  563.             }
  564.             if($entreprisesEdit->getNumVoie() != null){
  565.                 $entreprise->setNumVoie($entreprisesEdit->getNumVoie());
  566.             }
  567.             if($entreprisesEdit->getAdresse() != null){
  568.                 $entreprise->setAdresse($entreprisesEdit->getAdresse());
  569.             }
  570.             if($entreprisesEdit->getCodePostal() != null){
  571.                 $entreprise->setCodePostal($entreprisesEdit->getCodePostal());
  572.             }
  573.             if($entreprisesEdit->getCommune() != null){
  574.                 $entreprise->setCommune($entreprisesEdit->getCommune());
  575.             }
  576.             if($entreprisesEdit->getCodeInsee() != null){
  577.                 $entreprise->setCodeInsee($entreprisesEdit->getCodeInsee());
  578.             }
  579.             if($entreprisesEdit->getStatut() != null){
  580.                 $entreprise->setStatut($entreprisesEdit->getStatut());
  581.             }
  582.             if($entreprisesEdit->getUtilisateur() != null){
  583.                 $entreprise->setUtilisateur(array_map('strval'$entreprisesEdit->getUtilisateur()));
  584.             }
  585.             $entityManager->persist($entreprise);
  586.             $entityManager->flush();
  587.             return $this->redirectToRoute('app_entreprise');
  588.         }
  589.         return $this->render('entreprise/edit.html.twig', [
  590.             'entrepriseForm' => $form->createView(),
  591.             'entreprise' => $entreprise_entity
  592.         ]);
  593.     }
  594.     /**
  595.      * @Route("/entreprise/suppr/{id}", name="app_entreprise_suppr")
  596.      */
  597.     public function suppr(int $idRequest $requestEntityManagerInterface $entityManagerManagerRegistry $doctrine): Response
  598.     {
  599.         $notes $doctrine->getRepository(Note::class)->findBy(['entreprise_id' => $id]);
  600.         for ($i=0$i count($notes); $i++) { 
  601.             $entityManager->remove($notes[$i]);
  602.             $entityManager->flush();
  603.         };
  604.         $rappels $doctrine->getRepository(Rappel::class)->findBy(['entreprise_id' => $id]);
  605.         for ($i=0$i count($rappels); $i++) { 
  606.             $entityManager->remove($rappels[$i]);
  607.             $entityManager->flush();
  608.         };
  609.         $electric_meters $doctrine->getRepository(ElectricMeter::class)->findBy(['entreprise_id' => $id]);
  610.         for ($i=0$i count($electric_meters); $i++) { 
  611.             $entityManager->remove($electric_meters[$i]);
  612.             $entityManager->flush();
  613.         };
  614.         $gas_meters $doctrine->getRepository(GasMeter::class)->findBy(['entreprise_id' => $id]);
  615.         for ($i=0$i count($gas_meters); $i++) { 
  616.             $entityManager->remove($gas_meters[$i]);
  617.             $entityManager->flush();
  618.         };
  619.         $cspes $doctrine->getRepository(CSPE::class)->findBy(['entreprise_id' => $id]);
  620.         for ($i=0$i count($cspes); $i++) { 
  621.             $entityManager->remove($cspes[$i]);
  622.             $entityManager->flush();
  623.         };
  624.         $espace_clients $doctrine->getRepository(EspaceClient::class)->findBy(['entreprise_id' => $id]);
  625.         for ($i=0$i count($espace_clients); $i++) { 
  626.             $entityManager->remove($espace_clients[$i]);
  627.             $entityManager->flush();
  628.         };
  629.         $contacts $doctrine->getRepository(Contact::class)->findBy(['entreprise_id' => $id]);
  630.         for ($i=0$i count($contacts); $i++) { 
  631.             $entityManager->remove($contacts[$i]);
  632.             $entityManager->flush();
  633.         };
  634.         $entreprise $doctrine->getRepository(Entreprise::class)->findOneBy(['id' => $id]);
  635.         $entityManager->remove($entreprise);
  636.         $entityManager->flush();
  637.         return $this->redirectToRoute('app_entreprise');
  638.     }
  639.     /**
  640.      * @Route("/entreprise/details/{id}", name="app_entreprise_details")
  641.      */
  642.     public function details(int $idManagerRegistry $doctrine): Response
  643.     {
  644.         $entreprise $doctrine->getRepository(Entreprise::class)->findOneBy(['id' => $id]);
  645.         if(!$entreprise){
  646.             return $this->redirectToRoute('app_requetes');
  647.         }
  648.         
  649.         // Get all users for this company
  650.         $userIds $entreprise->getUtilisateur();
  651.         $user_names = [];
  652.         if (!empty($userIds)) {
  653.             foreach ($userIds as $userId) {
  654.                 $user $doctrine->getRepository(User::class)->find((int)$userId);
  655.                 if ($user) {
  656.                     $user_names[] = $user->getUsername();
  657.                 }
  658.             }
  659.         }
  660.         $user_name implode(', '$user_names);
  661.         $entreprise_entity = [ 'id' => $entreprise->getId(),
  662.             'raison_sociale' => $entreprise->getRaisonSociale(),
  663.             'siret' => $entreprise->getSiret(),
  664.             'naf' => $entreprise->getNaf(),
  665.             'rcs' => $entreprise->getRcs(),
  666.             'num_voie' => $entreprise->getNumVoie(),
  667.             'adresse' => $entreprise->getAdresse(),
  668.             'code_postal' => $entreprise->getCodePostal(),
  669.             'commune' => $entreprise->getCommune(),
  670.             'code_insee' => $entreprise->getCodeInsee(),
  671.             'statut' => $entreprise->getStatut(),
  672.             'utilisateur' => $user_names,
  673.         ];
  674.         // Fetch and prepare notes data
  675.         $notes $doctrine->getRepository(Note::class)->findBy(['entreprise_id' => $id], ['date_creation' => 'DESC']);
  676.         $array_notes = array();
  677.         foreach ($notes as $note) {
  678.             $user $note->getUser();
  679.             $array_notes[] = [
  680.                 'date_creation' => $note->getDateCreation() ? $note->getDateCreation()->format('d/m/Y') : '',
  681.                 'texte' => $note->getTexte(),
  682.                 'user' => $user $user->getUsername() : 'Non défini',
  683.                 'edit_url' => $this->generateUrl('app_note_edit', ['id' => $note->getId()]),
  684.                 'delete_url' => $this->generateUrl('app_note_suppr', ['id' => $note->getId()]),
  685.             ];
  686.         }
  687.         // Fetch and prepare rappels data
  688.         $rappels $doctrine->getRepository(Rappel::class)->findBy(['entreprise_id' => $id]);
  689.         $array_rappels = array();
  690.         foreach ($rappels as $rappel) {
  691.             $array_rappels[] = [
  692.                 $rappel->getTitre(),
  693.                 $rappel->getDescription(),
  694.                 $rappel->getEcheance()->format('d/m/Y'),
  695.                 $rappel->isCompleter(),
  696.                 '<a href="'.$this->generateUrl('app_rappel_edit',['id' => $rappel->getId()]).'" type="button" class="btn btn-sm btn-primary mb-1">Modifier</a>
  697.                 <a href="'.$this->generateUrl('app_rappel_suppr',['id' => $rappel->getId()]).'" type="button" class="btn btn-sm btn-danger ">Supprimer</a>',
  698.             ];
  699.     }
  700.         // Fetch electric meters and their PDLs
  701.         $electric_meters $doctrine->getRepository(ElectricMeter::class)->findBy(['entreprise_id' => $id]);
  702.         $array_electric_meters array_map(function($meter) {
  703.             return [
  704.                 'pdl' => $meter->getPDL(),
  705.                 'id' => $meter->getId(),
  706.             ];
  707.         }, $electric_meters);
  708.         $electric_pdls array_map(function($meter) {
  709.             return $meter->getPDL();
  710.         }, $electric_meters);
  711.         // Fetch gas meters and their PDLs
  712.         $gas_meters $doctrine->getRepository(GasMeter::class)->findBy(['entreprise_id' => $id]);
  713.         $array_gas_meters array_map(function($meter) {
  714.             return [
  715.                 'pdl' => $meter->getPDL(),
  716.                 'id' => $meter->getId(),
  717.             ];
  718.         }, $gas_meters);
  719.         $gas_pdls array_map(function($meter) {
  720.             return $meter->getPDL();
  721.         }, $gas_meters);
  722.         $cspes $doctrine->getRepository(CSPE::class)->findBy(['entreprise_id' => $id]);
  723.         $array_cspes = array();
  724.         for ($i=0$i count($cspes); $i++) { 
  725.             $array_cspes[$i] = [
  726.                 $cspes[$i]->getNotes(),
  727.                 date_format($cspes[$i]->getDate(),'d/m/Y'),
  728.                 $cspes[$i]->getValeur(),
  729.                 '<a href="'.$this->generateUrl('app_cspe_edit',['id' => $cspes[$i]->getId()]).'" type="button" class="btn btn-sm btn-warning mb-1">Modifier</a>
  730.                 <a href="'.$this->generateUrl('app_cspe_suppr',['id' => $cspes[$i]->getId()]).'" type="button" class="btn btn-sm btn-danger ">Supprimer</a>',
  731.             ];
  732.         };
  733.         $espace_clients $doctrine->getRepository(EspaceClient::class)->findBy(['entreprise_id' => $id]);
  734.         $array_espace_clients = array();
  735.         for ($i=0$i count($espace_clients); $i++) {
  736.             $lien $espace_clients[$i]->getLien();
  737.             // Add http:// if no protocol specified
  738.             if (!preg_match("~^(?:f|ht)tps?://~i"$lien)) {
  739.                 $lien "http://" $lien;
  740.             }
  741.             
  742.             // Extract domain name for button text
  743.             $domain parse_url($lienPHP_URL_HOST) ?: $lien;
  744.             $domainParts explode('.'$domain);
  745.             $buttonText count($domainParts) > $domainParts[1] : $domain;
  746.             
  747.             $array_espace_clients[$i] = [
  748.                 $espace_clients[$i]->getFournisseur(),
  749.                 $espace_clients[$i]->getLogin(),
  750.                 $espace_clients[$i]->getMdp(),
  751.                 '<a href="'.$lien.'" target="_blank" type="button" class="btn btn-primary">'.$buttonText.'</a>',
  752.                 '<a href="'.$this->generateUrl('app_espace_client_edit',['id' => $espace_clients[$i]->getId()]).'" type="button" class="btn btn-sm btn-warning mb-1">Modifier</a>
  753.                 <a href="'.$this->generateUrl('app_espace_client_suppr',['id' => $espace_clients[$i]->getId()]).'" type="button" class="btn btn-sm btn-danger ">Supprimer</a>',
  754.             ];
  755.         };
  756.         $contacts $doctrine->getRepository(Contact::class)->findBy(['entreprise_id' => $id]);
  757.         $array_contacts = array();
  758.         for ($i=0$i count($contacts); $i++) { 
  759.             $array_contacts[$i] = [
  760.                 $contacts[$i]->getNom(),
  761.                 $contacts[$i]->getPrenom(),
  762.                 $contacts[$i]->getCivilite(),
  763.                 $contacts[$i]->getFonction(),
  764.                 $contacts[$i]->getFixe(),
  765.                 $contacts[$i]->getEmail(),
  766.                 $contacts[$i]->getPortable(),
  767.                 '<a href="'.$this->generateUrl('app_contact_edit',['id' => $contacts[$i]->getId()]).'" type="button" class="btn btn-sm btn-warning mb-1">Modifier</a>
  768.                 <a href="'.$this->generateUrl('app_contact_suppr',['id' => $contacts[$i]->getId()]).'" type="button" class="btn btn-sm btn-danger ">Supprimer</a>',
  769.             ];
  770.         };
  771.         $contrats $doctrine->getRepository(Contrat::class)->findBy(['entreprise' => $entreprise]);
  772.         $array_contrats = array();
  773.         foreach ($contrats as $contrat) {
  774.             $array_contrats[] = [
  775.                 "id" => $contrat->getId(),
  776.                 "duree" => $contrat->getDuree(),
  777.                 "valeur" => $contrat->getValeur(),
  778.                 "pdl" => $contrat->getPdl(),
  779.                 "car" => $contrat->getCar(),
  780.                 "prix_moyen" => $contrat->getPrixMoyen(),
  781.                 "fournisseur" => $contrat->getFournisseur(),
  782.                 "date_debut" => $contrat->getDateDebut() ? $contrat->getDateDebut()->format('d/m/Y') : '',
  783.                 "date_fin" => $contrat->getDateFin() ? $contrat->getDateFin()->format('d/m/Y') : '',
  784.                 "date_signature" => $contrat->getDateSignature() ? $contrat->getDateSignature()->format('d/m/Y') : '',
  785.                 '<a href="'.$this->generateUrl('app_entreprise_edit_contrat', ['entrepriseId' => $entreprise->getId(), 'id' => $contrat->getId()]).'" type="button" class="btn btn-sm btn-warning mb-1">Modifier</a>
  786.                 <a href="'.$this->generateUrl('app_entreprise_delete_contrat', ['entrepriseId' => $entreprise->getId(), 'id' => $contrat->getId()]).'" type="button" class="btn btn-sm btn-danger">Supprimer</a>',
  787.             ];
  788.         }
  789.         return $this->render('entreprise/details.html.twig', [
  790.             'entreprise' => $entreprise_entity,
  791.             'notes' => $array_notes,
  792.             'rappels' => $array_rappels,
  793.             'electric_meters' => $array_electric_meters,
  794.             'gas_meters' => $array_gas_meters,
  795.             'electric_pdls' => $electric_pdls,
  796.             'gas_pdls' => $gas_pdls,
  797.             'cspes' => $array_cspes,
  798.             'espace_clients' => $array_espace_clients,
  799.             'contacts' => $array_contacts,
  800.             'contrats' => $array_contrats,
  801.         ]);
  802.     }
  803.     /**
  804.      * @Route("/entreprise/electric_meter/details/{id}", name="app_electric_meter_details")
  805.      */
  806.     public function electricMeterDetails(Request $requestint $idManagerRegistry $doctrine): JsonResponse
  807.     {
  808.         $pdl $request->query->get('pdl');
  809.         
  810.         if (!$pdl) {
  811.             return new JsonResponse(['error' => 'PDL parameter is required'], 400);
  812.         }
  813.         // First verify the entreprise exists
  814.         $entreprise $doctrine->getRepository(Entreprise::class)->find($id);
  815.         if (!$entreprise) {
  816.             return new JsonResponse(['error' => 'Entreprise not found'], 404);
  817.         }
  818.         // Find the electric meter using standard findOneBy method
  819.         $electricMeter $doctrine->getRepository(ElectricMeter::class)->findOneBy([
  820.             'entreprise_id' => $id,
  821.             'PDL' => $pdl
  822.         ]);
  823.         if (!$electricMeter) {
  824.             return new JsonResponse(['error' => 'Electric meter not found'], 404);
  825.         }
  826.         $meterDetails = [
  827.             'adresseCompteur' => $electricMeter->getAdresseCompteur(),
  828.             'PDL' => $electricMeter->getPDL(),
  829.             'dateDebut' => $electricMeter->getDateDebut() ? $electricMeter->getDateDebut()->format('d/m/Y') : '',
  830.             'dateFin' => $electricMeter->getDateFin() ? $electricMeter->getDateFin()->format('d/m/Y') : '',
  831.             'PS' => $electricMeter->getPS(),
  832.             'profil' => $electricMeter->getProfil(),
  833.             'CAR' => $electricMeter->getCAR(),
  834.             'fournisseur' => $electricMeter->getFournisseur(),
  835.             'prix' => $electricMeter->getPrix()
  836.         ];
  837.         return new JsonResponse($meterDetails);
  838.     }
  839.     /**
  840.      * @Route("/entreprise/{id}/gas-meter-details", name="app_gas_meter_details")
  841.      */
  842.     public function gasMeterDetails(Request $requestint $idManagerRegistry $doctrine): JsonResponse
  843.     {
  844.         $pdl $request->query->get('pdl');
  845.         
  846.         if (!$pdl) {
  847.             return new JsonResponse(['error' => 'PDL parameter is required'], 400);
  848.         }
  849.         // First verify the entreprise exists
  850.         $entreprise $doctrine->getRepository(Entreprise::class)->find($id);
  851.         if (!$entreprise) {
  852.             return new JsonResponse(['error' => 'Entreprise not found'], 404);
  853.         }
  854.         // Find the gas meter using standard findOneBy method
  855.         $gasMeter $doctrine->getRepository(GasMeter::class)->findOneBy([
  856.             'entreprise_id' => $id,
  857.             'PDL' => $pdl
  858.         ]);
  859.         if (!$gasMeter) {
  860.             return new JsonResponse(['error' => 'Gas meter not found'], 404);
  861.         }
  862.         $meterDetails = [
  863.             'adresseCompteur' => $gasMeter->getAdresseCompteur(),
  864.             'PDL' => $gasMeter->getPDL(),  // Added PDL field
  865.             'dateDebut' => $gasMeter->getDateDebut() ? $gasMeter->getDateDebut()->format('d/m/Y') : '',
  866.             'dateFin' => $gasMeter->getDateFin() ? $gasMeter->getDateFin()->format('d/m/Y') : '',
  867.             'profil' => $gasMeter->getProfil(),
  868.             'CAR' => $gasMeter->getCAR(),
  869.             'fournisseur' => $gasMeter->getFournisseur(),
  870.             'prix' => $gasMeter->getPrix(),
  871.         ];
  872.         return new JsonResponse($meterDetails);
  873.     }
  874.     /**
  875.      * @Route("/entreprise/infoclient", name="app_entreprise_infoclient")
  876.      */
  877.     public function infoclient(HttpClientInterface $httpClient): JsonResponse
  878.     {
  879.         // Utilisez les paramètres appropriés pour votre requête
  880.         $url 'https://api.societe.com/api/v1/infoclient';
  881.         $headers = [
  882.             'headers' => [
  883.                 'X-Authorization' => 'socapi 8938e836988619dc20be14360fba30e3',
  884.             ],
  885.         ];
  886.         // Effectuez la requête
  887.         $response $httpClient->request('GET'$url$headers);
  888.         // Renvoie la réponse JSON
  889.         return new JsonResponse($response->toArray());
  890.     }
  891.     /**
  892.      * @Route("/entreprise/info_entreprise/{numero}", name="app_entreprise_info_entreprise")
  893.      */
  894.     public function info_entreprise(HttpClientInterface $httpClientManagerRegistry $doctrine$numero): JsonResponse
  895.     {
  896.         // Vérification que l'entreprise n'est pas déjà enregistré en BDD
  897.         $entreprise $doctrine->getRepository(Entreprise::class)->findOneBy(['Siret' => $numero]);
  898.         if($entreprise !=null){
  899.             return new JsonResponse("existant");
  900.         }
  901.         $url 'https://api.societe.com/api/v1/entreprise/'.$numero.'/infoslegales';
  902.         $headers = [
  903.             'headers' => [
  904.                 'X-Authorization' => 'socapi 8938e836988619dc20be14360fba30e3',
  905.             ],
  906.         ];
  907.         // Effectuez la requête
  908.         $response $httpClient->request('GET'$url$headers);
  909.         // Renvoie la réponse JSON
  910.         return new JsonResponse($response->toArray());
  911.     }
  912.     /**
  913.      * @Route("/entreprise/{id}/new-contrat", name="app_entreprise_new_contrat")
  914.      */
  915.     public function newContrat(Request $requestEntityManagerInterface $entityManagerManagerRegistry $doctrineint $id): Response
  916.     {
  917.         $entreprise $doctrine->getRepository(Entreprise::class)->find($id);
  918.         
  919.         if (!$entreprise) {
  920.             throw $this->createNotFoundException('Entreprise not found');
  921.         }
  922.         $contrat = new Contrat();
  923.         $contrat->setEntreprise($entreprise);
  924.         $meterId $request->query->get('meterId');
  925.         $meterType $request->query->get('meterType');
  926.         if ($meterId && $meterType) {
  927.             $meter null;
  928.             if ($meterType === 'electric') {
  929.                 $meter $doctrine->getRepository(ElectricMeter::class)->find($meterId);
  930.             } elseif ($meterType === 'gas') {
  931.                 $meter $doctrine->getRepository(GasMeter::class)->find($meterId);
  932.             }
  933.             if ($meter) {
  934.                 $contrat->setPdl($meter->getPDL());
  935.                 $contrat->setCar($meter->getCAR());
  936.                 $contrat->setPrixMoyen($meter->getPrix());
  937.                 $contrat->setFournisseur($meter->getFournisseur());
  938.                 // For both types, set the dates
  939.                 $contrat->setDateDebut($meter->getDateDebut());
  940.                 $contrat->setDateFin($meter->getDateFin());
  941.                 // Calculate initial duration and value
  942.                 if ($meter->getDateDebut() && $meter->getDateFin()) {
  943.                     $dateDebut $meter->getDateDebut();
  944.                     if ($dateDebut) {
  945.                         if ($meterType === 'gas') {
  946.                             $dateDebut->modify('+1 day');
  947.                         }
  948.                     }
  949.                     $duration $this->calculateDurationInMonths($dateDebut$meter->getDateFin());
  950.                     $contrat->setDuree($duration);
  951.                     $annualValue $this->pricingService->calculateAnnualValue($contrat);
  952.                     $contrat->setValeur($annualValue);
  953.                 }
  954.             }
  955.         }
  956.         $pdlChoices $this->getPDLChoicesForEntreprise($doctrine$entreprise);
  957.         $form $this->createForm(ContratType::class, $contrat, [
  958.             'pdl_choices' => $pdlChoices
  959.         ]);
  960.         $form->handleRequest($request);
  961.         if ($form->isSubmitted() && $form->isValid()) {
  962.             // Calculate duration in months
  963.             $duration $this->calculateDurationInMonths($contrat->getDateDebut(), $contrat->getDateFin());
  964.             $contrat->setDuree($duration);
  965.             // Only calculate value if not manually set
  966.             $submittedValue $form->get('valeur')->getData();
  967.             if ($submittedValue === null || $submittedValue === 0.0) {
  968.                 $annualValue $this->pricingService->calculateAnnualValue($contrat);
  969.                 $contrat->setValeur($annualValue);
  970.             }
  971.             // Get the first user as the collaborateur (maintain backward compatibility)
  972.             $userIds $entreprise->getUtilisateur();
  973.             if (!empty($userIds)) {
  974.                 $user $doctrine->getRepository(User::class)->find((int)$userIds[0]);
  975.                 if ($user) {
  976.                     $contrat->setCollaborateur($user);
  977.                 }
  978.             }
  979.             $entityManager->persist($contrat);
  980.             $entityManager->flush();
  981.             if ($request->isXmlHttpRequest()) {
  982.                 return new JsonResponse([
  983.                     'success' => true,
  984.                     'contractId' => $contrat->getId(),
  985.                     'message' => 'Le contrat a été créé avec succès.'
  986.                 ]);
  987.             }
  988.             return $this->redirectToRoute('app_entreprise_details', ['id' => $entreprise->getId()]);
  989.         }
  990.         return $this->render('entreprise/new_contrat.html.twig', [
  991.             'entreprise' => $entreprise,
  992.             'form' => $form->createView(),
  993.         ]);
  994.     }
  995.     /**
  996.      * @Route("/entreprise/{entrepriseId}/edit-contrat/{id}", name="app_entreprise_edit_contrat")
  997.      */
  998.     public function editContrat(Request $requestEntityManagerInterface $entityManagerManagerRegistry $doctrineint $entrepriseIdint $id): Response
  999.     {
  1000.         $entreprise $doctrine->getRepository(Entreprise::class)->find($entrepriseId);
  1001.         $contrat $doctrine->getRepository(Contrat::class)->find($id);
  1002.         if (!$entreprise) {
  1003.             throw $this->createNotFoundException('Entreprise not found');
  1004.         }
  1005.         if (!$contrat) {
  1006.             throw $this->createNotFoundException('Contrat not found');
  1007.         }
  1008.         // Determine if this is a gas contract
  1009.         $isGasContract false;
  1010.         $gasMeter $doctrine->getRepository(GasMeter::class)->findOneBy([
  1011.             'entreprise_id' => $entrepriseId,
  1012.             'PDL' => $contrat->getPdl()
  1013.         ]);
  1014.         if ($gasMeter) {
  1015.             $isGasContract true;
  1016.         }
  1017.         // S'assurer que l'entreprise est définie sur le contrat
  1018.         $contrat->setEntreprise($entreprise);
  1019.         $pdlChoices $this->getPDLChoicesForEntreprise($doctrine$entreprise);
  1020.         $form $this->createForm(ContratType::class, $contrat, [
  1021.             'pdl_choices' => $pdlChoices
  1022.         ]);
  1023.         $form->handleRequest($request);
  1024.         if ($form->isSubmitted() && $form->isValid()) {
  1025.             // S'assurer que l'entreprise est toujours définie après la soumission du formulaire
  1026.             $contrat->setEntreprise($entreprise);
  1027.             // For gas contracts, ensure the start date is adjusted
  1028.             $dateDebut $contrat->getDateDebut();
  1029.             if ($dateDebut) {
  1030.                 if ($isGasContract) {
  1031.                     $dateDebut->modify('+1 day');
  1032.                 }
  1033.             }
  1034.             // Recalculate duration in months
  1035.             $duration $this->calculateDurationInMonths($dateDebut$contrat->getDateFin());
  1036.             $contrat->setDuree($duration);
  1037.             // Only calculate value if not manually set
  1038.             $submittedValue $form->get('valeur')->getData();
  1039.             if ($submittedValue === null || $submittedValue === 0.0) {
  1040.                 $annualValue $this->pricingService->calculateAnnualValue($contrat);
  1041.                 $contrat->setValeur($annualValue);
  1042.             }
  1043.             $entityManager->flush();
  1044.             return $this->redirectToRoute('app_entreprise_details', ['id' => $entreprise->getId()]);
  1045.         }
  1046.         return $this->render('entreprise/edit_contrat.html.twig', [
  1047.             'entreprise' => $entreprise,
  1048.             'contrat' => $contrat,
  1049.             'form' => $form->createView(),
  1050.         ]);
  1051.     }
  1052.     /**
  1053.      * @Route("/entreprise/{entrepriseId}/delete-contrat/{id}", name="app_entreprise_delete_contrat")
  1054.      */
  1055.     public function deleteContrat(Request $requestEntityManagerInterface $entityManagerManagerRegistry $doctrineint $entrepriseIdint $id): Response
  1056.     {
  1057.         $entreprise $doctrine->getRepository(Entreprise::class)->find($entrepriseId);
  1058.         $contrat $doctrine->getRepository(Contrat::class)->find($id);
  1059.         if (!$entreprise) {
  1060.             throw $this->createNotFoundException('Entreprise not found');
  1061.         }
  1062.         if (!$contrat) {
  1063.             throw $this->createNotFoundException('Contrat not found');
  1064.         }
  1065.         if ($this->isCsrfTokenValid('delete'.$contrat->getId(), $request->request->get('_token'))) {
  1066.             $entityManager->remove($contrat);
  1067.             $entityManager->flush();
  1068.         }
  1069.         return $this->redirectToRoute('app_entreprise_details', ['id' => $entreprise->getId()]);
  1070.     }
  1071.     private function calculateDurationInMonths(?\DateTimeInterface $dateDebut, ?\DateTimeInterface $dateFin): ?int
  1072.     {
  1073.         if (!$dateDebut || !$dateFin) {
  1074.             return null;
  1075.         }
  1076.         $interval $dateDebut->diff($dateFin);
  1077.         return $interval->12 $interval->m;
  1078.     }
  1079.     private function getPDLChoicesForEntreprise(ManagerRegistry $doctrineEntreprise $entreprise): array
  1080.     {
  1081.         $electricMeters $doctrine->getRepository(ElectricMeter::class)->findBy(['entreprise_id' => $entreprise->getId()]);
  1082.         $gasMeters $doctrine->getRepository(GasMeter::class)->findBy(['entreprise_id' => $entreprise->getId()]);
  1083.         $pdlChoices = [];
  1084.         foreach ($electricMeters as $meter) {
  1085.             $pdlChoices[$meter->getPDL()] = $meter->getPDL();
  1086.         }
  1087.         foreach ($gasMeters as $meter) {
  1088.             $pdlChoices[$meter->getPDL()] = $meter->getPDL();
  1089.         }
  1090.         return $pdlChoices;
  1091.     }
  1092.     /**
  1093.      * @Route("/entreprise/associate-user", name="app_entreprise_associate_user")
  1094.      */
  1095.     public function associateUser(Request $requestEntityManagerInterface $entityManager): Response
  1096.     {
  1097.         $this->denyAccessUnlessGranted('ROLE_COMPTA');
  1098.         try {
  1099.             $form $this->createForm(UserEntrepriseType::class);
  1100.             $form->handleRequest($request);
  1101.             if ($form->isSubmitted() && $form->isValid()) {
  1102.                 $data $form->getData();
  1103.                 $user $data['user'];
  1104.                 $entreprises $data['entreprises'];
  1105.                 // Vérification des données
  1106.                 if (!$user || !$entreprises || empty($entreprises)) {
  1107.                     throw new \InvalidArgumentException('Utilisateur et entreprises sont requis');
  1108.                 }
  1109.                 // Add ROLE_CLIENT_PRO if user doesn't have it
  1110.                 if (!$user->hasRole('ROLE_CLIENT_PRO')) {
  1111.                     $roles $user->getRoles();
  1112.                     $roles[] = 'ROLE_CLIENT_PRO';
  1113.                     $user->setRoles(array_unique($roles));
  1114.                 }
  1115.                 // Associate user with enterprises
  1116.                 foreach ($entreprises as $entreprise) {
  1117.                     if (!$user->getEntreprises()->contains($entreprise)) {
  1118.                         $user->addEntreprise($entreprise);
  1119.                         $entreprise->addUtilisateur(strval($user->getId()));
  1120.                     }
  1121.                 }
  1122.                 
  1123.                 $entityManager->persist($user);
  1124.                 $entityManager->flush();
  1125.                 $this->addFlash('success'sprintf(
  1126.                     'L\'utilisateur %s a été associé avec succès à %d entreprise(s)',
  1127.                     $user->getUsername(),
  1128.                     count($entreprises)
  1129.                 ));
  1130.                 return $this->redirectToRoute('app_entreprise');
  1131.             }
  1132.             return $this->render('entreprise/associate_user.html.twig', [
  1133.                 'form' => $form->createView(),
  1134.             ]);
  1135.         } catch (\Exception $e) {
  1136.             $this->addFlash('error''Une erreur est survenue lors de l\'association : ' $e->getMessage());
  1137.             return $this->redirectToRoute('app_entreprise_associate_user');
  1138.         }
  1139.     }
  1140. }