src/Repository/SatisfactionClientRepository.php line 97

Open in your IDE?
  1. <?php
  2. namespace App\Repository;
  3. use App\Entity\SatisfactionClient;
  4. use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
  5. use Doctrine\Persistence\ManagerRegistry;
  6. /**
  7.  * @extends ServiceEntityRepository<SatisfactionClient>
  8.  *
  9.  * @method SatisfactionClient|null find($id, $lockMode = null, $lockVersion = null)
  10.  * @method SatisfactionClient|null findOneBy(array $criteria, array $orderBy = null)
  11.  * @method SatisfactionClient[]    findAll()
  12.  * @method SatisfactionClient[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
  13.  */
  14. class SatisfactionClientRepository extends ServiceEntityRepository
  15. {
  16.     public function __construct(ManagerRegistry $registry)
  17.     {
  18.         parent::__construct($registrySatisfactionClient::class);
  19.     }
  20.     public function add(SatisfactionClient $entitybool $flush false): void
  21.     {
  22.         $this->getEntityManager()->persist($entity);
  23.         if ($flush) {
  24.             $this->getEntityManager()->flush();
  25.         }
  26.     }
  27.     public function remove(SatisfactionClient $entitybool $flush false): void
  28.     {
  29.         $this->getEntityManager()->remove($entity);
  30.         if ($flush) {
  31.             $this->getEntityManager()->flush();
  32.         }
  33.     }
  34.     /**
  35.      * @return SatisfactionClient[] Returns an array of SatisfactionClient objects
  36.      */
  37.     public function getSatisfactionClientAverageCpvByMonthYear($pointOfSale$childs$organisationId$perid): array
  38.     {
  39.         // Requête pour obtenir la moyenne totale par mois et année (sans codeCluster)
  40.         $moyenneTotaleQuery $this->createQueryBuilder('s')
  41.             ->select(
  42.                 'AVG(s.noteSatisfaction) AS moyenneTotal',
  43.                 'MONTH(s.dateContrat) AS mois',
  44.                 'YEAR(s.dateContrat) AS annee'
  45.             )
  46.             ->leftJoin('s.production''p')
  47.             ->where('s.entite = :pointOfSaleName'// Filtrer par pointOfSale
  48.             ->setParameter('pointOfSaleName'$pointOfSale->getName());
  49.         if (is_array($childs) && count($childs) > 0) {
  50.             $moyenneTotaleQuery->andWhere('p.seller IN (:childs)')
  51.                 ->leftJoin('p.seller''u')
  52.                 ->setParameter('childs'$childs);
  53.         }
  54.         if ($organisationId) {
  55.             $moyenneTotaleQuery->andWhere('p.organisation = :organisationId')
  56.                 ->setParameter('organisationId'$organisationId);
  57.         }
  58.         if ($perid) {
  59.             $moyenneTotaleQuery->andWhere('p.loginVendeurInit = :perid ')
  60.                 ->setParameter('perid'$perid);
  61.         }
  62.         $moyenneTotaleQuery->groupBy('annee, mois'// Groupement uniquement par année et mois pour la moyenne totale
  63.             ->getQuery()
  64.             ->getArrayResult();
  65.         // Requête pour obtenir la moyenne par cluster par mois, année et cluster
  66.         $moyenneParClusterQuery $this->createQueryBuilder('sc')
  67.             ->select(
  68.                 'MONTH(sc.dateContrat) AS mois',
  69.                 'YEAR(sc.dateContrat) AS annee',
  70.                 'sc.codeCluster',
  71.                 ' AVG(sc.noteSatisfaction) AS moyenneParCluster'
  72.             )
  73.             ->where('sc.entite = :pointOfSaleName'// Filtrer par pointOfSale
  74.             ->setParameter('pointOfSaleName'$pointOfSale->getName())
  75.             ->groupBy('annee, mois, sc.codeCluster'// Groupement par année, mois et codeCluster pour la moyenne par cluster
  76.             ->getQuery()
  77.             ->getArrayResult();
  78.         // Retourner les résultats
  79.         return [
  80.             'moyenneTotale' => $moyenneTotaleQuery,
  81.             'moyenneParCluster' => $moyenneParClusterQuery
  82.         ];
  83.     }
  84.     public function getSatisfactionClientAverageForSpecificMonthAndYear(
  85.         $pointOfSale,
  86.         $codeCluster,
  87.         $codeInsee,
  88.         int $mois,
  89.         int $annee,
  90.         $category,
  91.         $childs,
  92.         $organisationId,
  93.         $perid,
  94.         $sellerId,
  95.         $departement
  96.     ): array {
  97.         $qb $this->createQueryBuilder('s')
  98.             ->select('AVG(s.noteSatisfaction) AS moyenneSatisfaction')
  99.             ->leftJoin('s.production''p')
  100.             ->leftJoin('p.cluster''c')
  101.             ->andWhere('MONTH(s.dateContrat) = :mois')
  102.             ->andWhere('YEAR(s.dateContrat) = :annee')
  103.             ->setParameter('mois'$mois)
  104.             ->setParameter('annee'$annee);
  105.         // 👉 Si organisationId existe, on filtre dessus, sinon on utilise pointOfSaleName
  106.         if ($organisationId) {
  107.             $qb->andWhere('p.organisation = :organisationId')
  108.                 ->setParameter('organisationId'$organisationId);
  109.         } else {
  110.             $qb->andWhere('s.cod_poin_vent = :cpv')
  111.                 ->setParameter('cpv'$pointOfSale->getCode());
  112.         }
  113.         if ($category) {
  114.             $category array_filter(
  115.                 array_map('intval'explode(','$category)),
  116.                 fn($id) => $id 0
  117.             );
  118.             $qb->andWhere('p.category IN (:categories)')
  119.                 ->setParameter('categories'$category);
  120.         }
  121.         if (is_array($childs) && count($childs) > 0) {
  122.             $qb->andWhere('p.seller IN (:childs)')
  123.                 ->leftJoin('p.seller''u')
  124.                 ->setParameter('childs'$childs);
  125.         }
  126.         if ($perid) {
  127.             $qb->andWhere('p.loginVendeurInit = :perid')
  128.                 ->setParameter('perid'$perid);
  129.         }
  130.         if ($sellerId) {
  131.             $qb->andWhere('p.seller = :sellerId')
  132.                 ->setParameter('sellerId'$sellerId);
  133.         }
  134.         if ($codeCluster) {
  135.             $qb
  136.                 ->andWhere('c.codeCluster = :codeCluster')
  137.                 ->setParameter('codeCluster'$codeCluster);
  138.         }
  139.         if ($codeInsee) {
  140.             $qb->andWhere('p.codeInsee = :codeInsee')
  141.                 ->setParameter('codeInsee'$codeInsee);
  142.         }
  143.         if ($departement) {
  144.             // Si le département est fourni, on cherche les clusters dont le code commence par "departement-"
  145.             $qb->andWhere('c.codeCluster LIKE :prefix')
  146.                 ->setParameter('prefix'$departement '-%');
  147.         }
  148.         return $qb->getQuery()->getArrayResult();
  149.     }
  150.     public function getSatisfactionClientAverageForSpecificMonthAndYearForHistory(
  151.         $pointOfSale,
  152.         $codeCluster,
  153.         $codeInsee,
  154.         int $mois,
  155.         int $annee,
  156.         $category,
  157.         $childs,
  158.         $organisationId,
  159.         $perid,
  160.         $sellerId,
  161.         $departement
  162.     ): array {
  163.         $qb $this->createQueryBuilder('s')
  164.             ->select('AVG(s.noteSatisfaction) AS moyenneSatisfaction')
  165.             ->leftJoin('s.history''p')
  166.             ->leftJoin('p.cluster''c')
  167.             ->andWhere('MONTH(s.dateContrat) = :mois')
  168.             ->andWhere('YEAR(s.dateContrat) = :annee')
  169.             ->setParameter('mois'$mois)
  170.             ->setParameter('annee'$annee);
  171.         // 👉 Si organisationId existe, on filtre dessus, sinon on utilise pointOfSaleName
  172.         if ($organisationId) {
  173.             $qb->andWhere('p.organisation = :organisationId')
  174.                 ->setParameter('organisationId'$organisationId);
  175.         } else {
  176.             $qb->andWhere('s.cod_poin_vent = :cpv')
  177.                 ->setParameter('cpv'$pointOfSale->getCode());
  178.         }
  179.         if ($category) {
  180.             $category array_filter(
  181.                 array_map('intval'explode(','$category)),
  182.                 fn($id) => $id 0
  183.             );
  184.             $qb->andWhere('p.category IN (:categories)')
  185.                 ->setParameter('categories'$category);
  186.         }
  187.         if (is_array($childs) && count($childs) > 0) {
  188.             $qb->andWhere('p.seller IN (:childs)')
  189.                 ->leftJoin('p.seller''u')
  190.                 ->setParameter('childs'$childs);
  191.         }
  192.         if ($perid) {
  193.             $qb->andWhere('p.loginVendeurInit = :perid')
  194.                 ->setParameter('perid'$perid);
  195.         }
  196.         if ($sellerId) {
  197.             $qb->andWhere('p.seller = :sellerId')
  198.                 ->setParameter('sellerId'$sellerId);
  199.         }
  200.         if ($codeCluster) {
  201.             $qb
  202.                 ->andWhere('c.codeCluster = :codeCluster')
  203.                 ->setParameter('codeCluster'$codeCluster);
  204.         }
  205.         if ($codeInsee) {
  206.             $qb->andWhere('p.codeInsee = :codeInsee')
  207.                 ->setParameter('codeInsee'$codeInsee);
  208.         }
  209.         if ($departement) {
  210.             // Si le département est fourni, on cherche les clusters dont le code commence par "departement-"
  211.             $qb->andWhere('c.codeCluster LIKE :prefix')
  212.                 ->setParameter('prefix'$departement '-%');
  213.         }
  214.         return $qb->getQuery()->getArrayResult();
  215.     }
  216.     public function getSatisfaction(
  217.         $pointOfSale,
  218.         $codeCluster,
  219.         $codeInsee,
  220.         int $mois,
  221.         int $annee,
  222.         $category,
  223.         $childs,
  224.         $organisationId,
  225.         $perid,
  226.         $sellerId,
  227.         $departement
  228.     ): array {
  229.         $qb $this->createQueryBuilder('s')
  230.             ->select('c.codeCluster AS codeCluster, AVG(s.noteSatisfaction) AS moyenneSatisfaction')
  231.             ->leftJoin('s.production''p')
  232.             ->leftJoin('p.cluster''c')
  233.             ->andWhere('MONTH(s.dateContrat) = :mois')
  234.             ->andWhere('YEAR(s.dateContrat) = :annee')
  235.             ->setParameter('mois'$mois)
  236.             ->setParameter('annee'$annee)
  237.             ->groupBy('c.codeCluster');
  238.         if ($organisationId) {
  239.             $qb->andWhere('p.organisation = :organisationId')
  240.                 ->setParameter('organisationId'$organisationId);
  241.         } else {
  242.             $qb->andWhere('s.entite = :pointOfSaleName')
  243.                 ->setParameter('pointOfSaleName'$pointOfSale->getName());
  244.         }
  245.         if ($category) {
  246.             $category array_filter(
  247.                 array_map('intval'explode(','$category)),
  248.                 fn($id) => $id 0
  249.             );
  250.             $qb->andWhere('p.category IN (:categories)')
  251.                 ->setParameter('categories'$category);
  252.         }
  253.         if (is_array($childs) && count($childs) > 0) {
  254.             $qb->andWhere('p.seller IN (:childs)')
  255.                 ->leftJoin('p.seller''u')
  256.                 ->setParameter('childs'$childs);
  257.         }
  258.         if ($perid) {
  259.             $qb->andWhere('p.loginVendeurInit = :perid')
  260.                 ->setParameter('perid'$perid);
  261.         }
  262.         if ($sellerId) {
  263.             $qb->andWhere('p.seller = :sellerId')
  264.                 ->setParameter('sellerId'$sellerId);
  265.         }
  266.         if ($codeCluster) {
  267.             $qb->andWhere('c.codeCluster = :codeCluster')
  268.                 ->setParameter('codeCluster'$codeCluster);
  269.         }
  270.         if ($codeInsee) {
  271.             $qb->andWhere('p.codeInsee = :codeInsee')
  272.                 ->setParameter('codeInsee'$codeInsee);
  273.         }
  274.         if ($departement) {
  275.             $qb->andWhere('c.codeCluster LIKE :prefix')
  276.                 ->setParameter('prefix'$departement '-%');
  277.         }
  278.         $results $qb->getQuery()->getArrayResult();
  279.         // Créer un map [codeCluster => moyenneSatisfaction]
  280.         $satisfactionMap = [];
  281.         foreach ($results as $r) {
  282.             $satisfactionMap[$r['codeCluster']] = (float)$r['moyenneSatisfaction'];
  283.         }
  284.         return $satisfactionMap;
  285.     }
  286.     public function getSatisfactionClientAverageByMonthDayWeek(
  287.         $pointOfSale,
  288.         $codeCluster,
  289.         $departement,
  290.         $codeInsee,
  291.         int $annee,
  292.         $category,
  293.         $childs,
  294.         $organisationId,
  295.         $perid
  296.     ): array {
  297.         $conn $this->getEntityManager()->getConnection();
  298.         $sql "
  299.             SELECT 
  300.                 MONTH(s.date_contrat) AS mois,
  301.                 WEEK(s.date_contrat, 1) AS semaine,
  302.                 DATE(s.date_contrat) AS jour,
  303.                 AVG(s.note_satisfaction) AS moyenne_satisfaction
  304.             FROM satisfaction_client s
  305.             LEFT JOIN production p ON s.production_id = p.id
  306.             LEFT JOIN cluster c ON p.cluster_id = c.id
  307.             WHERE YEAR(s.date_contrat) = :annee
  308.               AND s.date_contrat IS NOT NULL
  309.         ";
  310.         $params = [
  311.             'annee' => $annee,
  312.         ];
  313.         if ($organisationId) {
  314.             $sql .= " AND p.organisation_id = :organisationId";
  315.             $params['organisationId'] = $organisationId;
  316.         } else {
  317.             $sql .= " AND s.entite = :pointOfSaleName";
  318.             $params['pointOfSaleName'] = $pointOfSale->getName();
  319.         }
  320.         // Normalisation robuste du paramètre $category
  321.         if ($category) {
  322.             $categoryArray = [];
  323.             if (is_string($category)) {
  324.                 $categoryArray array_filter(array_map('intval'explode(','$category)), fn($id) => $id 0);
  325.             } elseif (is_array($category) || $category instanceof \Traversable) {
  326.                 foreach ($category as $cat) {
  327.                     $categoryArray[] = is_object($cat) && method_exists($cat'getId') ? $cat->getId() : (int)$cat;
  328.                 }
  329.                 $categoryArray array_filter($categoryArray, fn($id) => $id 0);
  330.             }
  331.             if (!empty($categoryArray)) {
  332.                 $sql .= " AND p.category_id IN (" implode(','$categoryArray) . ")";
  333.             }
  334.         }
  335.         if (is_array($childs) && count($childs) > 0) {
  336.             $sql .= " AND p.seller_id IN (" implode(','$childs) . ")";
  337.         }
  338.         if ($perid) {
  339.             $sql .= " AND p.login_vendeur_init = :perid";
  340.             $params['perid'] = $perid;
  341.         }
  342.         if ($codeCluster) {
  343.             $sql .= " AND c.code_cluster = :codeCluster";
  344.             $params['codeCluster'] = $codeCluster;
  345.         }
  346.         if ($departement) {
  347.             $sql .= " AND c.code_cluster LIKE :prefix";
  348.             $params['prefix'] = $departement '-%';
  349.         }
  350.         if ($codeInsee) {
  351.             $sql .= " AND p.code_insee = :codeInsee";
  352.             $params['codeInsee'] = $codeInsee;
  353.         }
  354.         $sql .= " GROUP BY s.date_contrat
  355.                   ORDER BY s.date_contrat ASC";
  356.         $stmt $conn->executeQuery($sql$params);
  357.         $results $stmt->fetchAllAssociative();
  358.         // Déterminer mois courant et précédent
  359.         $currentMonth = (int)date('m');
  360.         $previousMonth $currentMonth === 12 $currentMonth 1;
  361.         // Réorganiser côté PHP
  362.         $data = [
  363.             'parMois' => [],
  364.             'parSemaine' => [],
  365.             'parJour' => [],
  366.         ];
  367.         foreach ($results as $row) {
  368.             $data['parMois'][$row['mois']][] = round((float)$row['moyenne_satisfaction'], 2);
  369.             $data['parSemaine'][$row['semaine']][] = round((float)$row['moyenne_satisfaction'], 2);
  370.             // Limiter parJour aux deux derniers mois
  371.             if ((int)$row['mois'] === $currentMonth || (int)$row['mois'] === $previousMonth) {
  372.                 $data['parJour'][$row['jour']] = round((float)$row['moyenne_satisfaction'], 2);
  373.             }
  374.         }
  375.         // Calculer la moyenne réelle pour mois et semaine
  376.         foreach (['parMois''parSemaine'] as $key) {
  377.             foreach ($data[$key] as $period => $values) {
  378.                 $data[$key][$period] = round(array_sum($values) / count($values), 2);
  379.             }
  380.         }
  381.         return $data;
  382.     }
  383.     public function getSatisfactionClientAverageByPeriod(
  384.         $pointOfSale,
  385.         $codeCluster,
  386.         $departement,
  387.         $codeInsee,
  388.         int $annee,
  389.         $category,
  390.         $childs,
  391.         $organisationId,
  392.         $perid,
  393.         string $periode 'month' // 'day' | 'week' | 'month'
  394.     ): array {
  395.         $conn $this->getEntityManager()->getConnection();
  396.         // Sélection dynamique selon la période
  397.         switch ($periode) {
  398.             case 'week':
  399.                 $selectGroup "WEEK(s.date_contrat, 1) AS periode";
  400.                 break;
  401.             case 'day':
  402.                 $selectGroup "DATE(s.date_contrat) AS periode";
  403.                 break;
  404.             case 'month':
  405.             default:
  406.                 $selectGroup "MONTH(s.date_contrat) AS periode";
  407.                 break;
  408.         }
  409.         $sql "
  410.             SELECT 
  411.                 $selectGroup,
  412.                 AVG(s.note_satisfaction) AS moyenne_satisfaction
  413.         ";
  414.         if ($organisationId) {
  415.             $sql .= ",
  416.                 po.code AS code_point,
  417.                 po.name AS nom_point
  418.             ";
  419.         }
  420.         $sql .= "
  421.             FROM satisfaction_client s
  422.             LEFT JOIN production p ON s.production_id = p.id
  423.             LEFT JOIN cluster c ON p.cluster_id = c.id
  424.             LEFT JOIN point_of_sale po ON p.point_of_sale_id = po.id
  425.             WHERE YEAR(s.date_contrat) = :annee
  426.               AND s.date_contrat IS NOT NULL
  427.         ";
  428.         $params = ['annee' => $annee];
  429.         // Filtrage organisation / point de vente
  430.         if ($organisationId) {
  431.             $sql .= " AND p.organisation_id = :organisationId";
  432.             $params['organisationId'] = $organisationId;
  433.         } else {
  434.             $sql .= " AND s.entite = :pointOfSaleName";
  435.             $params['pointOfSaleName'] = $pointOfSale->getName();
  436.         }
  437.         // Filtrage catégorie
  438.         if ($category) {
  439.             $categoryArray = [];
  440.             if (is_string($category)) {
  441.                 $categoryArray array_filter(array_map('intval'explode(','$category)), fn($id) => $id 0);
  442.             } elseif (is_array($category) || $category instanceof \Traversable) {
  443.                 foreach ($category as $cat) {
  444.                     $categoryArray[] = is_object($cat) && method_exists($cat'getId') ? $cat->getId() : (int)$cat;
  445.                 }
  446.                 $categoryArray array_filter($categoryArray, fn($id) => $id 0);
  447.             }
  448.             if (!empty($categoryArray)) {
  449.                 $sql .= " AND p.category_id IN (" implode(','$categoryArray) . ")";
  450.             }
  451.         }
  452.         if (is_array($childs) && count($childs) > 0) {
  453.             $sql .= " AND p.seller_id IN (" implode(','$childs) . ")";
  454.         }
  455.         if ($perid) {
  456.             $sql .= " AND p.login_vendeur_init = :perid";
  457.             $params['perid'] = $perid;
  458.         }
  459.         if ($codeCluster) {
  460.             $sql .= " AND c.code_cluster = :codeCluster";
  461.             $params['codeCluster'] = $codeCluster;
  462.         }
  463.         if ($departement) {
  464.             $sql .= " AND c.code_cluster LIKE :prefix";
  465.             $params['prefix'] = $departement '-%';
  466.         }
  467.         if ($codeInsee) {
  468.             $sql .= " AND p.code_insee = :codeInsee";
  469.             $params['codeInsee'] = $codeInsee;
  470.         }
  471.         // Groupement selon la période choisie
  472.         if ($organisationId) {
  473.             $sql .= " GROUP BY po.id, periode ORDER BY po.id, periode ASC";
  474.         } else {
  475.             $sql .= " GROUP BY periode ORDER BY periode ASC";
  476.         }
  477.         // Exécution
  478.         $stmt $conn->executeQuery($sql$params);
  479.         $results $stmt->fetchAllAssociative();
  480.         // Réorganisation du résultat
  481.         $data = [];
  482.         foreach ($results as $row) {
  483.             $periodeKey $row['periode'];
  484.             $moyenne round((float)$row['moyenne_satisfaction'], 2);
  485.             if ($organisationId) {
  486.                 $codePoint $row['code_point'];
  487.                 if (!isset($data[$codePoint])) {
  488.                     $data[$codePoint] = [];
  489.                 }
  490.                 $data[$codePoint][$periodeKey] = $moyenne;
  491.             } else {
  492.                 $data[$periodeKey] = $moyenne;
  493.             }
  494.         }
  495.         return $data;
  496.     }
  497.     public function getSatisfactionClientDetails(
  498.         $pointOfSale,
  499.         $yearMonth,
  500.         $codeCluster,
  501.         $note
  502.     ) {
  503.         $entityManager $this->getEntityManager();
  504.         $qb $entityManager->createQueryBuilder()
  505.             ->select('s.id,p.id AS production_id,s.orderNumber,s.noteSatisfaction,s.verbatim
  506.             ,s.rencontreConseiller,s.docSynthetique,s.entite,s.codeCluster,c.libelleCluster,s.datReponse, s.dateContrat,u.id AS seller_id,CONCAT(u.nom, \' \', u.prenom)  AS  nom_prenom')
  507.             ->from('App\Entity\SatisfactionClient''s')
  508.             ->leftJoin('App\Entity\Cluster''c''WITH''c.codeCluster = s.codeCluster')
  509.             ->leftJoin('App\Entity\Production''p''WITH''p.id = s.production')
  510.             ->leftJoin('App\Entity\User''u''WITH''u.id = p.seller')
  511.             ->where('s.entite = :pointOfSaleName')
  512.             ->setParameter('pointOfSaleName'$pointOfSale->getName());
  513.         if ($yearMonth) {
  514.             $qb
  515.                 ->andWhere('MONTH(s.dateContrat) = :mois')
  516.                 ->andWhere('YEAR(s.dateContrat) = :annee')
  517.                 ->setParameter('mois'explode('-'$yearMonth)[1])
  518.                 ->setParameter('annee'explode('-'$yearMonth)[0])
  519.             ;
  520.         }
  521.         if ($codeCluster) {
  522.             $qb->andWhere('s.codeCluster = :codeCluster')
  523.                 ->setParameter('codeCluster'$codeCluster);
  524.         }
  525.         if ($note) {
  526.             $qb->andWhere('s.noteSatisfaction <= :note')
  527.                 ->setParameter('note'$note);
  528.         }
  529.         return $qb->getQuery()
  530.             ->getArrayResult();
  531.     }
  532. }