src/Controller/AbsenceStatsController.php line 255

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Exams;
  4. use App\Entity\Quarter;
  5. use App\Entity\TheClass;
  6. use App\Repository\AbsenceRepository;
  7. use App\Repository\AbsenceBlameConfigRepository;
  8. use App\Repository\AbsenceExclusionConfigRepository;
  9. use App\Repository\AbsencePunishConfigRepository;
  10. use App\Repository\AbsenceRetainedConfigRepository;
  11. use App\Repository\AbsenceWarningConfigRepository;
  12. use App\Repository\DisciplineExclusionRepository;
  13. use App\Repository\ExamsRepository;
  14. use App\Repository\GlobalDisciplineEnabledConfigRepository;
  15. use App\Repository\JustifyAbsenceRepository;
  16. use App\Repository\LateRepository;
  17. use App\Repository\QuarterRepository;
  18. use App\Repository\StudentRepository;
  19. use App\Service\CurrentSchoolYearService;
  20. use App\Service\GenerateSpatiePdf;
  21. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  22. use Symfony\Component\HttpFoundation\Response;
  23. use Symfony\Component\Routing\Annotation\Route;
  24. #[Route('/discProff/absence-stats/class/{class}')]
  25. class AbsenceStatsController extends AbstractController
  26. {
  27.     // ── SÉQUENCE ──────────────────────────────────────────────────────────────
  28.     #[Route('/exam/{exam}'name'app_absence_stats_exam'methods: ['GET'])]
  29.     public function byExam(
  30.         TheClass $classExams $exam,
  31.         StudentRepository $studentRepo,
  32.         AbsenceRepository $absenceRepo,
  33.         JustifyAbsenceRepository $justifiedAbsenceRepo,
  34.         LateRepository $lateRepo,
  35.         GlobalDisciplineEnabledConfigRepository $globalRepo,
  36.         AbsenceWarningConfigRepository $warningRepo,
  37.         AbsenceBlameConfigRepository $blameRepo,
  38.         AbsenceRetainedConfigRepository $retainedRepo,
  39.         AbsencePunishConfigRepository $punishRepo,
  40.         AbsenceExclusionConfigRepository $exclusionConfigRepo,
  41.         DisciplineExclusionRepository $exclusionRepo,
  42.         CurrentSchoolYearService $yearService
  43.     ): Response {
  44.         $year   $yearService->getCurrent();
  45.         $school $this->getUser()->getSchool();
  46.         $rows $this->buildRows(
  47.             $studentRepo->findByClass($class->getId(), $school->getId(), $year),
  48.             $school$year$classnull'exam'$exam,
  49.             $absenceRepo$justifiedAbsenceRepo$lateRepo,
  50.             $globalRepo$warningRepo$blameRepo$retainedRepo,
  51.             $punishRepo$exclusionConfigRepo$exclusionRepo
  52.         );
  53.         return $this->render('absence_stats/index.html.twig', [
  54.             'class'  => $class,
  55.             'exam'   => $exam,
  56.             'year'   => $year,
  57.             'rows'   => $rows,
  58.             'mode'   => 'exam',
  59.             'title'  => $exam->getName(),
  60.         ]);
  61.     }
  62.     #[Route('/exam/{exam}/pdf'name'app_absence_stats_exam_pdf'methods: ['GET'])]
  63.     public function byExamPdf(
  64.         TheClass $classExams $exam,
  65.         StudentRepository $studentRepo,
  66.         AbsenceRepository $absenceRepo,
  67.         JustifyAbsenceRepository $justifiedAbsenceRepo,
  68.         LateRepository $lateRepo,
  69.         GlobalDisciplineEnabledConfigRepository $globalRepo,
  70.         AbsenceWarningConfigRepository $warningRepo,
  71.         AbsenceBlameConfigRepository $blameRepo,
  72.         AbsenceRetainedConfigRepository $retainedRepo,
  73.         AbsencePunishConfigRepository $punishRepo,
  74.         AbsenceExclusionConfigRepository $exclusionConfigRepo,
  75.         DisciplineExclusionRepository $exclusionRepo,
  76.         CurrentSchoolYearService $yearService,
  77.         GenerateSpatiePdf $pdfService
  78.     ): Response {
  79.         $year   $yearService->getCurrent();
  80.         $school $this->getUser()->getSchool();
  81.         $rows $this->buildRows(
  82.             $studentRepo->findByClass($class->getId(), $school->getId(), $year),
  83.             $school$year$classnull'exam'$exam,
  84.             $absenceRepo$justifiedAbsenceRepo$lateRepo,
  85.             $globalRepo$warningRepo$blameRepo$retainedRepo,
  86.             $punishRepo$exclusionConfigRepo$exclusionRepo
  87.         );
  88.         $html $this->renderView('absence_stats/pdf.html.twig', [
  89.             'class' => $class'exam' => $exam'year' => $year,
  90.             'school' => $school'rows' => $rows,
  91.             'mode' => 'exam''title' => $exam->getName(),
  92.         ]);
  93.         return $pdfService->downloadResponse($html'absences-' $exam->getName() . '-' $class->getName() . '.pdf'true);
  94.     }
  95.     // ── TRIMESTRE ─────────────────────────────────────────────────────────────
  96.     #[Route('/quarter/{quarter}'name'app_absence_stats_quarter'methods: ['GET'])]
  97.     public function byQuarter(
  98.         TheClass $classQuarter $quarter,
  99.         StudentRepository $studentRepo,
  100.         AbsenceRepository $absenceRepo,
  101.         JustifyAbsenceRepository $justifiedAbsenceRepo,
  102.         LateRepository $lateRepo,
  103.         GlobalDisciplineEnabledConfigRepository $globalRepo,
  104.         AbsenceWarningConfigRepository $warningRepo,
  105.         AbsenceBlameConfigRepository $blameRepo,
  106.         AbsenceRetainedConfigRepository $retainedRepo,
  107.         AbsencePunishConfigRepository $punishRepo,
  108.         AbsenceExclusionConfigRepository $exclusionConfigRepo,
  109.         DisciplineExclusionRepository $exclusionRepo,
  110.         CurrentSchoolYearService $yearService
  111.     ): Response {
  112.         $year   $yearService->getCurrent();
  113.         $school $this->getUser()->getSchool();
  114.         $rows $this->buildRows(
  115.             $studentRepo->findByClass($class->getId(), $school->getId(), $year),
  116.             $school$year$class$quarter'quarter'null,
  117.             $absenceRepo$justifiedAbsenceRepo$lateRepo,
  118.             $globalRepo$warningRepo$blameRepo$retainedRepo,
  119.             $punishRepo$exclusionConfigRepo$exclusionRepo
  120.         );
  121.         return $this->render('absence_stats/index.html.twig', [
  122.             'class'   => $class,
  123.             'quarter' => $quarter,
  124.             'year'    => $year,
  125.             'rows'    => $rows,
  126.             'mode'    => 'quarter',
  127.             'title'   => $quarter->getName(),
  128.         ]);
  129.     }
  130.     #[Route('/quarter/{quarter}/pdf'name'app_absence_stats_quarter_pdf'methods: ['GET'])]
  131.     public function byQuarterPdf(
  132.         TheClass $classQuarter $quarter,
  133.         StudentRepository $studentRepo,
  134.         AbsenceRepository $absenceRepo,
  135.         JustifyAbsenceRepository $justifiedAbsenceRepo,
  136.         LateRepository $lateRepo,
  137.         GlobalDisciplineEnabledConfigRepository $globalRepo,
  138.         AbsenceWarningConfigRepository $warningRepo,
  139.         AbsenceBlameConfigRepository $blameRepo,
  140.         AbsenceRetainedConfigRepository $retainedRepo,
  141.         AbsencePunishConfigRepository $punishRepo,
  142.         AbsenceExclusionConfigRepository $exclusionConfigRepo,
  143.         DisciplineExclusionRepository $exclusionRepo,
  144.         CurrentSchoolYearService $yearService,
  145.         GenerateSpatiePdf $pdfService
  146.     ): Response {
  147.         $year   $yearService->getCurrent();
  148.         $school $this->getUser()->getSchool();
  149.         $rows $this->buildRows(
  150.             $studentRepo->findByClass($class->getId(), $school->getId(), $year),
  151.             $school$year$class$quarter'quarter',null,
  152.             $absenceRepo$justifiedAbsenceRepo$lateRepo,
  153.             $globalRepo$warningRepo$blameRepo$retainedRepo,
  154.             $punishRepo$exclusionConfigRepo$exclusionRepo
  155.         );
  156.         $html $this->renderView('absence_stats/pdf.html.twig', [
  157.             'class' => $class'quarter' => $quarter'year' => $year,
  158.             'school' => $school'rows' => $rows,
  159.             'mode' => 'quarter''title' => $quarter->getName(),
  160.         ]);
  161.         return $pdfService->downloadResponse($html'absences-' $quarter->getName() . '-' $class->getName() . '.pdf'true);
  162.     }
  163.     // ── ANNUEL ────────────────────────────────────────────────────────────────
  164.     #[Route('/annual'name'app_absence_stats_annual'methods: ['GET'])]
  165.     public function byAnnual(
  166.         TheClass $class,
  167.         StudentRepository $studentRepo,
  168.         AbsenceRepository $absenceRepo,
  169.         JustifyAbsenceRepository $justifiedAbsenceRepo,
  170.         LateRepository $lateRepo,
  171.         GlobalDisciplineEnabledConfigRepository $globalRepo,
  172.         AbsenceWarningConfigRepository $warningRepo,
  173.         AbsenceBlameConfigRepository $blameRepo,
  174.         AbsenceRetainedConfigRepository $retainedRepo,
  175.         AbsencePunishConfigRepository $punishRepo,
  176.         AbsenceExclusionConfigRepository $exclusionConfigRepo,
  177.         DisciplineExclusionRepository $exclusionRepo,
  178.         CurrentSchoolYearService $yearService
  179.     ): Response {
  180.         $year   $yearService->getCurrent();
  181.         $school $this->getUser()->getSchool();
  182.         $rows $this->buildRows(
  183.             $studentRepo->findByClass($class->getId(), $school->getId(), $year),
  184.             $school$year$classnull'annual'null,
  185.             $absenceRepo$justifiedAbsenceRepo$lateRepo,
  186.             $globalRepo$warningRepo$blameRepo$retainedRepo,
  187.             $punishRepo$exclusionConfigRepo$exclusionRepo
  188.         );
  189.         return $this->render('absence_stats/index.html.twig', [
  190.             'class' => $class,
  191.             'year'  => $year,
  192.             'rows'  => $rows,
  193.             'mode'  => 'annual',
  194.             'title' => 'Bilan Annuel',
  195.         ]);
  196.     }
  197.     #[Route('/annual/pdf'name'app_absence_stats_annual_pdf'methods: ['GET'])]
  198.     public function byAnnualPdf(
  199.         TheClass $class,
  200.         StudentRepository $studentRepo,
  201.         AbsenceRepository $absenceRepo,
  202.         JustifyAbsenceRepository $justifiedAbsenceRepo,
  203.         LateRepository $lateRepo,
  204.         GlobalDisciplineEnabledConfigRepository $globalRepo,
  205.         AbsenceWarningConfigRepository $warningRepo,
  206.         AbsenceBlameConfigRepository $blameRepo,
  207.         AbsenceRetainedConfigRepository $retainedRepo,
  208.         AbsencePunishConfigRepository $punishRepo,
  209.         AbsenceExclusionConfigRepository $exclusionConfigRepo,
  210.         DisciplineExclusionRepository $exclusionRepo,
  211.         CurrentSchoolYearService $yearService,
  212.         GenerateSpatiePdf $pdfService
  213.     ): Response {
  214.         $year   $yearService->getCurrent();
  215.         $school $this->getUser()->getSchool();
  216.         $rows $this->buildRows(
  217.             $studentRepo->findByClass($class->getId(), $school->getId(), $year),
  218.             $school$year$classnull'annual',null,
  219.             $absenceRepo$justifiedAbsenceRepo$lateRepo,
  220.             $globalRepo$warningRepo$blameRepo$retainedRepo,
  221.             $punishRepo$exclusionConfigRepo$exclusionRepo
  222.         );
  223.         $html $this->renderView('absence_stats/pdf.html.twig', [
  224.             'class' => $class'year' => $year'school' => $school,
  225.             'rows' => $rows'mode' => 'annual''title' => 'Bilan Annuel',
  226.         ]);
  227.         return $pdfService->downloadResponse($html'absences-annuel-' $class->getName() . '.pdf'true);
  228.     }
  229.     // ── HELPER PRIVÉ ──────────────────────────────────────────────────────────
  230.     private function buildRows(
  231.         array $students$school$yearTheClass $class,
  232.         ?Quarter $quarterstring $mode, ?\App\Entity\Exams $exam null,
  233.         AbsenceRepository $absenceRepo,
  234.         JustifyAbsenceRepository $justifiedAbsenceRepo,
  235.         LateRepository $lateRepo,
  236.         GlobalDisciplineEnabledConfigRepository $globalRepo,
  237.         AbsenceWarningConfigRepository $warningRepo,
  238.         AbsenceBlameConfigRepository $blameRepo,
  239.         AbsenceRetainedConfigRepository $retainedRepo,
  240.         AbsencePunishConfigRepository $punishRepo,
  241.         AbsenceExclusionConfigRepository $exclusionConfigRepo,
  242.         DisciplineExclusionRepository $exclusionRepo
  243.     ): array {
  244.         $global $globalRepo->findOneBy(['school' => $school'year' => $year]);
  245.         $rows   = [];
  246.         foreach ($students as $student) {
  247.             $sid $student->getId();
  248.             // ── Absences ──
  249.             if ($mode === 'exam') {
  250.                 $totalAbsence     $absenceRepo->countByExamAndByStudent($sid$exam->getId(), $school->getId(), $year)[0]['total'];
  251.                 $justifiedAbsence $justifiedAbsenceRepo->countByExamAndByStudent($sid$exam->getId(), $school->getId())[0]['total'];
  252.                 $lates            $lateRepo->findBy(['student' => $student'year' => $year'school' => $school'exam' => $exam]);
  253.             } elseif ($mode === 'quarter' && $quarter !== null) {
  254.                 $totalAbsence     $absenceRepo->countByQuarterAndByStudent($sid$quarter->getId(), $school->getId(), $year)[0]['total'];
  255.                 $justifiedAbsence $justifiedAbsenceRepo->countByQuarterAndByStudent($sid$quarter->getId(), $school->getId())[0]['total'];
  256.                 $lates            $lateRepo->findByStudentAndByQuarter($sid$quarter->getId(), $school->getId(), $year);
  257.             } else {
  258.                 // annuel
  259.                 $totalAbsence     $absenceRepo->countAllByStudent($sid$school->getId(), $year)[0]['total'];
  260.                 $justifiedAbsence $justifiedAbsenceRepo->countAllByStudent($sid$school->getId())[0]['total'];
  261.                 $lates            $lateRepo->findBy(['student' => $student'year' => $year'school' => $school]);
  262.             }
  263.             $injustified $totalAbsence $justifiedAbsence;
  264.             // ── Retards ──
  265.             $lateHours 0;
  266.             foreach ($lates as $l) {
  267.                 $interval   $l->getStartTime()->diff($l->getEndTime());
  268.                 $lateHours += ($interval->60 $interval->i) / 60;
  269.             }
  270.             // ── Discipline ──
  271.             $warningNumber 0;
  272.             if ($global->isWarning()) {
  273.                 foreach ($warningRepo->findBy(['school' => $school'year' => $year]) as $w) {
  274.                     if ($injustified >= $w->getStart() && $injustified <= $w->getEnd()) { $warningNumber += $w->getWarning(); }
  275.                 }
  276.             }
  277.             $blameNumber 0;
  278.             if ($global->isBlame()) {
  279.                 foreach ($blameRepo->findBy(['school' => $school'year' => $year]) as $b) {
  280.                     if ($injustified >= $b->getStart() && $injustified <= $b->getEnd()) { $blameNumber += $b->getBlame(); }
  281.                 }
  282.             }
  283.             $retainedNumber 0;
  284.             if ($global->isRetained()) {
  285.                 foreach ($retainedRepo->findBy(['school' => $school'year' => $year]) as $r) {
  286.                     if ($injustified >= $r->getStart() && $injustified <= $r->getEnd()) { $retainedNumber += $r->getRetained(); }
  287.                 }
  288.             }
  289.             $punishNumber 0;
  290.             if ($global->isPunish()) {
  291.                 foreach ($punishRepo->findBy(['school' => $school'year' => $year]) as $p) {
  292.                     if ($injustified >= $p->getStart() && $injustified <= $p->getEnd()) { $punishNumber += $p->getPunish(); }
  293.                 }
  294.             }
  295.             $exclusionNumber 0;
  296.             foreach ($exclusionConfigRepo->findBy(['school' => $school'year' => $year]) as $d) {
  297.                 if ($injustified >= $d->getStart() && $injustified <= $d->getEnd()) { $exclusionNumber += $d->getDayForInterval(); }
  298.             }
  299.             $criteria = ['school' => $school'classe' => $class'year' => $year'student' => $student];
  300.             if ($mode === 'quarter' && $quarter !== null) {
  301.                 $criteria['quarter'] = $quarter;
  302.             } else {
  303.                 $criteria['annual'] = true;
  304.             }
  305.             foreach ($exclusionRepo->findBy($criteria) as $exclu) {
  306.                 $exclusionNumber += $exclu->getNumber();
  307.             }
  308.             $rows[] = [
  309.                 'student'          => $student,
  310.                 'totalAbsence'     => $totalAbsence,
  311.                 'justifiedAbsence' => $justifiedAbsence,
  312.                 'injustified'      => $injustified,
  313.                 'lateHours'        => round($lateHours1),
  314.                 'warningNumber'    => $warningNumber,
  315.                 'blameNumber'      => $blameNumber,
  316.                 'retainedNumber'   => $retainedNumber,
  317.                 'punishNumber'     => $punishNumber,
  318.                 'exclusionNumber'  => $exclusionNumber,
  319.             ];
  320.         }
  321.         // Trier par nombre d'absences injustifiées décroissant
  322.         usort($rows, fn($a$b) => $b['injustified'] <=> $a['injustified']);
  323.         return $rows;
  324.     }
  325. }