src/Controller/ClassRoomController.php line 78

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  4. use Symfony\Component\HttpFoundation\Response;
  5. use Symfony\Component\HttpFoundation\Request;
  6. use Symfony\Component\Routing\Annotation\Route;
  7. use PhpOffice\PhpSpreadsheet\Spreadsheet;
  8. use PhpOffice\PhpSpreadsheet\Writer\Xlsx;
  9. use Symfony\Component\HttpFoundation\StreamedResponse;
  10. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
  11. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  12. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  13. use Knp\Snappy\Pdf;
  14. use Knp\Bundle\SnappyBundle\Snappy\Response\PdfResponse;
  15. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  16. use App\Repository\AttributionRepository;
  17. use Doctrine\ORM\EntityManagerInterface;
  18. use App\Repository\ClassRoomRepository;
  19. use App\Repository\SchoolYearRepository;
  20. use App\Repository\QuaterRepository;
  21. use App\Repository\SequenceRepository;
  22. use App\Repository\EvaluationRepository;
  23. use App\Repository\StudentRepository;
  24. use App\Repository\MainTeacherRepository;
  25. use App\Repository\MarkRepository;
  26. use App\Entity\ClassRoom;
  27. use App\Entity\Course;
  28. use App\Entity\SchoolYear;
  29. use App\Form\ClassRoomType;
  30. use App\Entity\Sequence;
  31. use App\Entity\Quater;
  32. use App\Repository\SubscriptionRepository;
  33. use App\Repository\InstallmentRepository;
  34. use App\Service\SchoolYearService;
  35. /**
  36. * ClassRoom controller.
  37. *
  38. * @Route("prof/rooms")
  39. */
  40. class ClassRoomController extends AbstractController
  41. {
  42. private $em;
  43. private $repo;
  44. private $scRepo;
  45. private $stdRepo;
  46. private $subRepo;
  47. private $seqRepo;
  48. private $evalRepo;
  49. private $qtRepo;
  50. private $markRepo;
  51. private $snappy;
  52. private $session;
  53. private $quaterData;
  54. private $annualMark;
  55. private $annualAbs;
  56. private $annualRanks;
  57. private $imagesExists;
  58. private Pdf $pdf;
  59. private SchoolYearService $schoolYearService;
  60. private MainTeacherRepository $mainTeacherRepo;
  61. private AttributionRepository $attRepo;
  62. private InstallmentRepository $instRepo;
  63. public function __construct(Pdf $pdf,InstallmentRepository $instRepo, AttributionRepository $attRepo, MainTeacherRepository $mainTeacherRepo, SchoolYearService $schoolYearService,MarkRepository $markRepo, QuaterRepository $qtRepo, StudentRepository $stdRepo, EvaluationRepository $evalRepo, SchoolYearRepository $scRepo, SequenceRepository $seqRepo, ClassRoomRepository $repo, SubscriptionRepository $subRepo, EntityManagerInterface $em, Pdf $snappy, SessionInterface $session)
  64. {
  65. $this->annualMark = [];
  66. $this->annualAbs = [];
  67. $this->annualRanks = [];
  68. $this->quaterData = [];
  69. $this->annualAvgArray = [];
  70. $this->sumAvg = 0;
  71. $this->em = $em;
  72. $this->pdf = $pdf;
  73. $this->repo = $repo;
  74. $this->scRepo = $scRepo;
  75. $this->attRepo = $attRepo;
  76. $this->seqRepo = $seqRepo;
  77. $this->evalRepo = $evalRepo;
  78. $this->mainTeacherRepo = $mainTeacherRepo;
  79. $this->stdRepo = $stdRepo;
  80. $this->instRepo = $instRepo;
  81. $this->qtRepo = $qtRepo;
  82. $this->subRepo = $subRepo;
  83. $this->markRepo = $markRepo;
  84. $this->snappy = $snappy;
  85. $this->session = $session;
  86. $this->schoolYearService = $schoolYearService;
  87. }
  88. /**
  89. * Lists all ClassRoomme entities.
  90. *
  91. * @Route("/", name="admin_classrooms")
  92. * @Method("GET")
  93. * @Template()
  94. */
  95. public function indexAction()
  96. {
  97. $classrooms = $this->repo->findAll();
  98. $year = $this->schoolYearService->sessionYearById();
  99. $seq = $this->seqRepo->findOneBy(array("activated" => true));
  100. $mainTeachers = $this->mainTeacherRepo->findBy(array("schoolYear" => $year));
  101. $mainTeachersMap = array();
  102. foreach($mainTeachers as $mt){
  103. $mainTeachersMap[$mt->getClassRoom()->getId()] = $mt->getTeacher();
  104. }
  105. return $this->render('classroom/index.html.twig', array(
  106. 'mainTeachers' => $mainTeachersMap,
  107. 'classrooms' => $classrooms,
  108. 'year' => $year,
  109. 'seq' => $seq ? $seq->getId() : 0,
  110. ));
  111. }
  112. // Existance de fichiers image des eleves
  113. private function fileExists(ClassRoom $classroom, SchoolYear $year): array
  114. {
  115. $imageExists = [];
  116. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year);
  117. // Répertoire absolu vers les images
  118. $baseDir = $this->getParameter('kernel.project_dir') . '/public/assets/images/student/';
  119. foreach ($studentEnrolled as $std) {
  120. $matricule = $std->getMatricule();
  121. $found = false;
  122. foreach (['jpg', 'jpeg', 'PNG'] as $ext) {
  123. $filename = $baseDir . $matricule . '.' . $ext;
  124. if (file_exists($filename)) {
  125. $found = true;
  126. break;
  127. }
  128. }
  129. $imageExists[$std->getId()] = $found;
  130. }
  131. return $imageExists;
  132. }
  133. /**
  134. * Calcule le facteur de zoom CSS (transform: scale) à appliquer sur chaque bulletin
  135. * afin qu'il tienne exactement dans 2 pages A4, quel que soit le nombre de matières.
  136. *
  137. * La valeur est transmise au template Twig sous la clé 'scale'.
  138. * Le template l'utilise via : transform: scale({{ scale | default(0.92) }});
  139. */
  140. private function computeScale(ClassRoom $room): float
  141. {
  142. // Compte le nombre total de matières programmées dans la classe
  143. $nbCourses = 0;
  144. foreach ($room->getModules() as $module) {
  145. $nbCourses += count($module->getCourses());
  146. }
  147. return match (true) {
  148. $nbCourses <= 12 => 0.95,
  149. $nbCourses <= 16 => 0.90,
  150. $nbCourses <= 20 => 0.85,
  151. default => 0.80,
  152. };
  153. }
  154. /**
  155. * Finds and displays a ClassRoomme entity.
  156. *
  157. * @Route("/{id}/show", name="admin_classrooms_show", requirements={"id"="\d+"})
  158. * @Method("GET")
  159. * @Template()
  160. */
  161. public function showAction(ClassRoom $classroom, StudentRepository $stdRepo): Response
  162. {
  163. $year = $this->schoolYearService->sessionYearById();
  164. // ── Attributions ─────────────────────────────────────────────────────────
  165. $attributions = $this->attRepo->findByYearAndByRoom($year, $classroom);
  166. $attributionsMapCourses = [];
  167. foreach ($attributions as $att) {
  168. $attributionsMapCourses[$att->getCourse()->getId()] = $att;
  169. }
  170. // ── Résultats examens officiels ───────────────────────────────────────────
  171. $officialExamResults = $this->subRepo->countByMention($year, $classroom);
  172. $mentionCategories = [];
  173. $mentionCountCategories = [];
  174. $mentionMap = [
  175. '0' => 'ECHEC', '1p' => 'PASSABLE', '1a' => 'ASSEZ-BIEN',
  176. '1b' => 'BIEN', '1t' => 'TRES-BIEN', '1e' => 'EXCELLENT',
  177. 'A' => '5 POINTS', 'B' => '4 POINTS', 'C' => '3 POINTS',
  178. 'D' => '2 POINTS', 'E' => '1 POINT',
  179. ];
  180. foreach ($officialExamResults as $exam) {
  181. $mentionCategories[] = $mentionMap[$exam['officialExamResult']] ?? $exam['officialExamResult'];
  182. $mentionCountCategories[] = $exam['count'];
  183. }
  184. // ── Évaluations par séquence ─────────────────────────────────────────────
  185. $seqs = $this->seqRepo->findSequenceThisYear($year);
  186. $evalSeqs = [];
  187. foreach ($seqs as $seq) {
  188. $evalSeqs[$seq->getId()] = $this->evalRepo->findBy([
  189. 'classRoom' => $classroom,
  190. 'sequence' => $seq,
  191. ]);
  192. }
  193. // ════════════════════════════════════════════════════════════════════════
  194. // INDEX UNIFIÉ des cours évalués (dans n'importe quelle séquence)
  195. // ════════════════════════════════════════════════════════════════════════
  196. // Clé = courseId, valeur = libellé wording
  197. $allCoursesMap = [];
  198. foreach ($evalSeqs as $seqEvals) {
  199. foreach ($seqEvals as $eval) {
  200. $cid = $eval->getCourse()->getId();
  201. if (!isset($allCoursesMap[$cid])) {
  202. $allCoursesMap[$cid] = $eval->getCourse()->getWording();
  203. }
  204. }
  205. }
  206. // Tri alphabétique pour lisibilité
  207. asort($allCoursesMap);
  208. $allCourseIds = array_keys($allCoursesMap);
  209. $allCourseLabels = array_values($allCoursesMap);
  210. // ════════════════════════════════════════════════════════════════════════
  211. // MATRICE SPARSE course × séquence
  212. // $matrix[courseId][seqId] = ['avg', 'success', 'failures', 'absents']
  213. // null si pas d'éval enregistrée pour cette combinaison
  214. // ════════════════════════════════════════════════════════════════════════
  215. $matrix = [];
  216. foreach ($allCourseIds as $cid) {
  217. foreach ($seqs as $seq) {
  218. $matrix[$cid][$seq->getId()] = null; // null par défaut
  219. }
  220. }
  221. foreach ($evalSeqs as $seqId => $seqEvals) {
  222. foreach ($seqEvals as $eval) {
  223. $cid = $eval->getCourse()->getId();
  224. $matrix[$cid][$seqId] = [
  225. 'avg' => $eval->getMoyenne() > 0 ? round($eval->getMoyenne(), 2) : null,
  226. 'success' => $eval->getSuccessH() + $eval->getSuccessF(),
  227. 'failures' => $eval->getFailluresH() + $eval->getFailluresF(),
  228. 'absents' => $eval->getAbscent(),
  229. ];
  230. }
  231. }
  232. // ════════════════════════════════════════════════════════════════════════
  233. // GRAPHIQUE 1 — Heatmap cours × séquence
  234. // Format : tableau de lignes, chaque ligne = un cours
  235. // [ {course: 'MATHS', s1: 12.5, s2: null, s3: 14, ...}, ... ]
  236. // ════════════════════════════════════════════════════════════════════════
  237. $heatmapData = [];
  238. foreach ($allCourseIds as $cid) {
  239. $row = ['course' => $allCoursesMap[$cid]];
  240. foreach ($seqs as $seq) {
  241. $sid = $seq->getId();
  242. $row['s' . $sid] = $matrix[$cid][$sid] ? $matrix[$cid][$sid]['avg'] : null;
  243. }
  244. $heatmapData[] = $row;
  245. }
  246. $seqLabels = array_map(fn($s) => $s->getWording(), $seqs);
  247. $seqIds = array_map(fn($s) => $s->getId(), $seqs);
  248. // ════════════════════════════════════════════════════════════════════════
  249. // GRAPHIQUE 2 — Évolution moyenne générale séquence par séquence
  250. // Moyenne pondérée par coeff : SUM(avg × coef) / SUM(coef) pour chaque séq
  251. // ════════════════════════════════════════════════════════════════════════
  252. $generalAvgBySeq = [];
  253. foreach ($seqs as $seq) {
  254. $sumWeighted = 0.0;
  255. $sumCoef = 0;
  256. $hasData = false;
  257. foreach ($evalSeqs[$seq->getId()] as $eval) {
  258. if ($eval->getMoyenne() > 0) {
  259. $coef = $eval->getCourse()->getCoefficient();
  260. $sumWeighted += $eval->getMoyenne() * $coef;
  261. $sumCoef += $coef;
  262. $hasData = true;
  263. }
  264. }
  265. $generalAvgBySeq[] = $hasData && $sumCoef > 0
  266. ? round($sumWeighted / $sumCoef, 2)
  267. : null;
  268. }
  269. // ════════════════════════════════════════════════════════════════════════
  270. // GRAPHIQUE 3 — Réussite vs Échec par matière (dernière séquence active)
  271. // ════════════════════════════════════════════════════════════════════════
  272. $activeSeq = $this->seqRepo->findOneBy(['activated' => true]);
  273. $successFailData = ['labels' => [], 'success' => [], 'failures' => [], 'absents' => []];
  274. if ($activeSeq && isset($evalSeqs[$activeSeq->getId()])) {
  275. foreach ($evalSeqs[$activeSeq->getId()] as $eval) {
  276. if ($eval->getMoyenne() > 0) {
  277. $successFailData['labels'][] = $eval->getCourse()->getWording();
  278. $successFailData['success'][] = $eval->getSuccessH() + $eval->getSuccessF();
  279. $successFailData['failures'][] = $eval->getFailluresH() + $eval->getFailluresF();
  280. $successFailData['absents'][] = $eval->getAbscent();
  281. }
  282. }
  283. }
  284. // ════════════════════════════════════════════════════════════════════════
  285. // GRAPHIQUE 4 — Radar : profil par trimestre
  286. // Moyenne par matière groupée par trimestre (séq 1+2 = trim1, etc.)
  287. // ════════════════════════════════════════════════════════════════════════
  288. $seqsArray = array_values($seqs);
  289. $quaterProfiles = [];
  290. $trimNames = [];
  291. // Grouper les séquences par quater
  292. $seqsByQuater = [];
  293. foreach ($seqs as $seq) {
  294. $qid = $seq->getQuater()->getId();
  295. $seqsByQuater[$qid][] = $seq;
  296. $trimNames[$qid] = $seq->getQuater()->getWording();
  297. }
  298. foreach ($seqsByQuater as $qid => $qSeqs) {
  299. $profile = [];
  300. foreach ($allCourseIds as $cid) {
  301. $sum = 0.0; $n = 0;
  302. foreach ($qSeqs as $seq) {
  303. $cell = $matrix[$cid][$seq->getId()] ?? null;
  304. if ($cell && $cell['avg'] !== null) {
  305. $sum += $cell['avg'];
  306. $n++;
  307. }
  308. }
  309. $profile[] = $n > 0 ? round($sum / $n, 2) : null;
  310. }
  311. $quaterProfiles[] = [
  312. 'label' => $trimNames[$qid],
  313. 'data' => $profile,
  314. ];
  315. }
  316. // ── Résultats ─────────────────────────────────────────────────────────────
  317. return $this->render('classroom/show.html.twig', [
  318. // Données existantes
  319. 'mainteacher' => $this->_getMainTeacher($classroom, $year),
  320. 'classroom' => $classroom,
  321. 'attributions' => $attributionsMapCourses,
  322. 'modules' => $classroom->getModules(),
  323. 'studentEnrolled' => $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year),
  324. 'fileExists' => $this->fileExists($classroom, $year),
  325. 'mentionCategories' => json_encode($mentionCategories),
  326. 'mentionCountCategories' => json_encode($mentionCountCategories),
  327. // Nouvelles données graphiques
  328. 'courseLabels' => json_encode($allCourseLabels), // libellés unifiés
  329. 'seqLabels' => json_encode($seqLabels), // ['Session 1', ...]
  330. 'seqIds' => json_encode($seqIds), // [1, 2, 3, ...]
  331. 'heatmapData' => json_encode($heatmapData), // matrice sparse
  332. 'generalAvgBySeq' => json_encode($generalAvgBySeq), // [12.4, null, 13.1, ...]
  333. 'successFailData' => json_encode($successFailData), // réussite/échec
  334. 'quaterProfiles' => json_encode($quaterProfiles), // radar trimestriel
  335. 'activeSeqLabel' => $activeSeq ? $activeSeq->getWording() : '',
  336. ]);
  337. }
  338. // Helper privé extrait pour lisibilité
  339. private function _getMainTeacher(ClassRoom $classroom, $year): ?object
  340. {
  341. foreach ($classroom->getMainTeachers() as $mainT) {
  342. if ($mainT->getSchoolYear()->getId() === $year->getId()) {
  343. return $mainT->getTeacher();
  344. }
  345. }
  346. return null;
  347. }
  348. /**
  349. * Finds and displays a ClassRoomme entity.
  350. *
  351. * @Route("/{id}/stat", name="admin_classrooms_stat", requirements={"id"="\d+"})
  352. * @Method("GET")
  353. * @Template()
  354. */
  355. public function statAction(ClassRoom $classroom)
  356. {
  357. return $this->render('classroom/show.html.twig', array());
  358. }
  359. /**
  360. * Finds and displays a ClassRoom entity.
  361. *
  362. * @Route("/{id}/reportCardsYear", name="admin_classrooms_reportcards_year", requirements={"id"="\d+"})
  363. * @Method("GET")
  364. * @Template()
  365. */
  366. public function reportCardsYearAction(ClassRoom $classroom)
  367. {
  368. set_time_limit(600);
  369. $connection = $this->em->getConnection();
  370. $year = $this->schoolYearService->sessionYearById();
  371. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year);
  372. $statement = $connection->prepare(
  373. " CREATE OR REPLACE VIEW V_STUDENT_MARK_DATA_SEQ1 AS
  374. SELECT DISTINCT eval.id as eval,crs.id as crs, room.id as room,year.id as year, std.matricule as matricule, std.image_name as profileImagePath, std.lastname as lastname, std.firstname as firstname, std.birthday as birthday, std.gender as gender,std.birthplace as birthplace , teach.full_name as teacher , modu.name as module , crs.wording as wording, crs.coefficient as coefficient,m.value as valeur, m.weight as weight, m.appreciation as appreciation
  375. FROM mark m JOIN student std ON m.student_id = std.id
  376. JOIN evaluation eval ON m.evaluation_id = eval.id
  377. JOIN class_room room ON eval.class_room_id = room.id
  378. JOIN course crs ON eval.course_id = crs.id
  379. JOIN attribution att ON att.course_id = crs.id
  380. JOIN user teach ON att.teacher_id = teach.id
  381. JOIN module modu ON modu.id = crs.module_id
  382. JOIN sequence seq ON seq.id = eval.sequence_id
  383. JOIN quater quat ON seq.quater_id = quat.id
  384. JOIN school_year year ON quat.school_year_id = year.id
  385. WHERE room.id = ? AND eval.sequence_id =1
  386. "
  387. );
  388. $statement->bindValue(1, $classroom->getId());
  389. $statement->execute();
  390. $statement = $connection->prepare(
  391. "CREATE OR REPLACE VIEW V_STUDENT_MARK_DATA_SEQ2 AS
  392. SELECT DISTINCT crs.id as crs, eval.id as eval, std.matricule as matricule, m.value as valeur, m.weight as weight, m.appreciation as appreciation
  393. FROM mark m
  394. JOIN student std ON m.student_id = std.id
  395. JOIN evaluation eval ON m.evaluation_id = eval.id
  396. JOIN course crs ON eval.course_id = crs.id
  397. WHERE eval.class_room_id = ? AND eval.sequence_id = 2
  398. ORDER BY matricule,eval; "
  399. );
  400. $statement->bindValue(1, $classroom->getId());
  401. $statement->execute();
  402. $statement = $connection->prepare(
  403. "CREATE OR REPLACE VIEW V_STUDENT_MARK_DATA_SEQ3 AS
  404. SELECT DISTINCT crs.id as crs, eval.id as eval, std.matricule as matricule, m.value as valeur, m.weight as weight, m.appreciation as appreciation
  405. FROM mark m
  406. JOIN student std ON m.student_id = std.id
  407. JOIN evaluation eval ON m.evaluation_id = eval.id
  408. JOIN course crs ON eval.course_id = crs.id
  409. WHERE eval.class_room_id =? AND eval.sequence_id = 3
  410. ORDER BY matricule,eval; "
  411. );
  412. $statement->bindValue(1, $classroom->getId());
  413. $statement->execute();
  414. $statement = $connection->prepare(
  415. "CREATE OR REPLACE VIEW V_STUDENT_MARK_DATA_SEQ4 AS
  416. SELECT DISTINCT crs.id as crs, eval.id as eval, std.matricule as matricule, m.value as valeur, m.weight as weight, m.appreciation as appreciation
  417. FROM mark m
  418. JOIN student std ON m.student_id = std.id
  419. JOIN evaluation eval ON m.evaluation_id = eval.id
  420. JOIN course crs ON eval.course_id = crs.id
  421. WHERE eval.class_room_id = ? AND eval.sequence_id = 4
  422. ORDER BY matricule,eval; "
  423. );
  424. $statement->bindValue(1, $classroom->getId());
  425. $statement->execute();
  426. $statement = $connection->prepare(
  427. "CREATE OR REPLACE VIEW V_STUDENT_MARK_DATA_SEQ5 AS
  428. SELECT DISTINCT crs.id as crs, eval.id as eval, std.matricule as matricule, m.value as valeur, m.weight as weight, m.appreciation as appreciation
  429. FROM mark m
  430. JOIN student std ON m.student_id = std.id
  431. JOIN evaluation eval ON m.evaluation_id = eval.id
  432. JOIN course crs ON eval.course_id = crs.id
  433. WHERE eval.class_room_id = ? AND eval.sequence_id = 5
  434. ORDER BY matricule,eval; "
  435. );
  436. $statement->bindValue(1, $classroom->getId());
  437. $statement->execute();
  438. $statement = $connection->prepare(
  439. " CREATE OR REPLACE VIEW V_STUDENT_MARK_DATA_SEQ6 AS
  440. SELECT DISTINCT eval.id as eval,crs.id as crs, std.matricule as matricule, m.value as valeur, m.weight as weight, m.appreciation as appreciation
  441. FROM mark m JOIN student std ON m.student_id = std.id
  442. JOIN evaluation eval ON m.evaluation_id = eval.id
  443. JOIN class_room room ON eval.class_room_id = room.id
  444. JOIN course crs ON eval.course_id = crs.id
  445. WHERE room.id = ? AND eval.sequence_id = 6
  446. ORDER BY std.matricule"
  447. );
  448. $statement->bindValue(1, $classroom->getId());
  449. $statement->execute();
  450. $dataYear = $this->em->getConnection()->executeQuery("select * from V_STUDENT_MARK_DATA_SEQ1
  451. INNER JOIN V_STUDENT_MARK_DATA_SEQ2 ON V_STUDENT_MARK_DATA_SEQ1.matricule = V_STUDENT_MARK_DATA_SEQ2.matricule
  452. INNER JOIN V_STUDENT_MARK_DATA_SEQ3 ON V_STUDENT_MARK_DATA_SEQ2.matricule = V_STUDENT_MARK_DATA_SEQ3.matricule
  453. INNER JOIN V_STUDENT_MARK_DATA_SEQ4 ON V_STUDENT_MARK_DATA_SEQ3.matricule = V_STUDENT_MARK_DATA_SEQ4.matricule
  454. INNER JOIN V_STUDENT_MARK_DATA_SEQ5 ON V_STUDENT_MARK_DATA_SEQ4.matricule = V_STUDENT_MARK_DATA_SEQ5.matricule
  455. INNER JOIN V_STUDENT_MARK_DATA_SEQ6 ON V_STUDENT_MARK_DATA_SEQ5.matricule = V_STUDENT_MARK_DATA_SEQ6.matricule
  456. ")->fetchAll();
  457. $this->snappy->setTimeout(600);
  458. $html = $this->renderView('classroom/reportcard/annual.html.twig', array(
  459. 'year' => $year,
  460. 'data' => $dataYear,
  461. 'room' => $classroom,
  462. 'year' => $year,
  463. 'students' => $studentEnrolled,
  464. ));
  465. return new Response(
  466. $this->snappy->getOutputFromHtml($html),
  467. 200,
  468. array(
  469. 'Content-Type' => 'application/pdf',
  470. 'Content-Disposition' => 'attachment; filename="BUL_ANN_' . $classroom->getName() . '.pdf"',
  471. )
  472. );
  473. }
  474. public function viewSeq(int $i){
  475. $year = $this->schoolYearService->sessionYearById();
  476. $connection = $this->em->getConnection();
  477. $statement = $connection->prepare(
  478. " CREATE OR REPLACE VIEW V_STUDENT_MARK_SEQ" . $i . " AS
  479. SELECT DISTINCT eval.id as eval,crs.id as crs, room.id as room,year.id as year, std.id as std, teach.full_name as teacher , modu.id as module,m.value as value, m.weight as weight
  480. FROM mark m JOIN student std ON m.student_id = std.id
  481. JOIN evaluation eval ON m.evaluation_id = eval.id
  482. JOIN class_room room ON eval.class_room_id = room.id
  483. JOIN course crs ON eval.course_id = crs.id
  484. JOIN attribution att ON att.course_id = crs.id
  485. JOIN user teach ON att.teacher_id = teach.id
  486. JOIN module modu ON modu.id = crs.module_id
  487. JOIN sequence seq ON seq.id = eval.sequence_id
  488. JOIN quater quat ON seq.quater_id = quat.id
  489. JOIN school_year year ON quat.school_year_id = year.id
  490. WHERE att.year_id =? AND room.id = ? AND eval.sequence_id =?
  491. ORDER BY room.id,modu.id , std; "
  492. );
  493. $statement->bindValue(1, $year->getId());
  494. $statement->bindValue(2, $classroom->getId());
  495. $statement->bindValue(3, $seq->getId());
  496. $statement->execute();
  497. }
  498. /**
  499. * Finds and displays a ClassRoom entity.
  500. *
  501. * @Route("/{id}/reportCardsApcYearapc", name="admin_class_reportcards_apc_year", requirements={"id"="\d+"})
  502. * @Method("GET")
  503. * @Template()
  504. */
  505. public function reportCards2YearAction(ClassRoom $classroom)
  506. {
  507. set_time_limit(600);
  508. $connection = $this->em->getConnection();
  509. $year = $this->schoolYearService->sessionYearById();
  510. $sequences = $this->seqRepo->findSequenceThisYear($year);
  511. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year);
  512. foreach ($sequences as $seq) {
  513. /*******************************************************************************************************************/
  514. /***************CREATION DE la VIEW DES NOTES SEQUENTIELLES, TRIMESTRIELLES ET ANNUELLES DE LA CLASSE**************/
  515. /*******************************************************************************************************************/
  516. // CAS DES NOTES SEQUENTIELLES
  517. // $this->viewSeq($i, $classroom, $seq);
  518. $this->getViewSeqData( $classroom, $seq);
  519. }
  520. // CAS DES NOTES TRIMESTRIELLES
  521. $statement = $connection->prepare(
  522. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER_1 AS
  523. SELECT DISTINCT seq1.std as std , seq1.crs as crs, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  524. FROM V_STUDENT_MARK_SEQ1 seq1
  525. LEFT JOIN V_STUDENT_MARK_SEQ2 seq2
  526. ON (seq1.std = seq2.std AND seq1.crs = seq2.crs)
  527. ORDER BY seq1.std"
  528. );
  529. $statement->execute();
  530. $statement = $connection->prepare(
  531. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER_2 AS
  532. SELECT DISTINCT seq1.std as std , seq1.crs as crs, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  533. FROM V_STUDENT_MARK_SEQ3 seq1
  534. LEFT JOIN V_STUDENT_MARK_SEQ4 seq2
  535. ON (seq1.std = seq2.std AND seq1.crs = seq2.crs)
  536. ORDER BY seq1.std"
  537. );
  538. $statement->execute();
  539. $statement = $connection->prepare(
  540. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER_3 AS
  541. SELECT DISTINCT seq1.std as std , seq1.crs as crs, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  542. FROM V_STUDENT_MARK_SEQ5 seq1
  543. LEFT JOIN V_STUDENT_MARK_SEQ6 seq2
  544. ON (seq1.std = seq2.std AND seq1.crs = seq2.crs)
  545. ORDER BY seq1.std"
  546. );
  547. $statement->execute();
  548. // CAS DES NOTES ANNUELLES
  549. $statement = $connection->prepare(
  550. "CREATE OR REPLACE VIEW ANNUAL_DATA AS
  551. SELECT DISTINCT student.id as idStd , student.matricule as matricule , student.image_name as profileImagePath,
  552. student.lastname as lastname, student.firstname as firstname, student.birthday as birthday,
  553. student.gender as gender,student.birthplace as birthplace ,
  554. class_room.name as room_name,
  555. course.wording as course, course.coefficient as coef,
  556. module.name as module,
  557. user.full_name as teacher,
  558. quat1.std,quat1.modu,
  559. quat1.value as value1, quat1.weight as weight1,
  560. quat2.value as value2, quat2.weight as weight2,
  561. quat3.value as value3,quat3.weight as weight3,
  562. greatest(quat1.weight , quat2.weight, quat3.weight ) as weight,
  563. ( quat1.value*quat1.weight+ quat2.value*quat2.weight + quat3.value*quat3.weight) /(quat1.weight+quat2.weight+quat3.weight) as value
  564. FROM student
  565. JOIN V_STUDENT_MARK_QUATER_1 quat1 ON student.id = quat1.std
  566. JOIN class_room ON class_room.id = quat1.room
  567. JOIN course ON course.id = quat1.crs
  568. JOIN module ON course.module_id = quat1.modu
  569. JOIN user ON user.full_name = quat1.teacher
  570. LEFT JOIN V_STUDENT_MARK_QUATER_2 quat2 ON quat1.std = quat2.std AND quat1.crs = quat2.crs
  571. JOIN
  572. LEFT V_STUDENT_MARK_QUATER_3 quat3 ON quat1.std = quat3.std AND quat1.crs = quat3.crs
  573. ORDER BY quat1.std, quat1.modu
  574. "
  575. );
  576. $statement->execute();
  577. $dataYear = $connection->executeQuery("SELECT * FROM ANNUAL_DATA ")->fetchAll();
  578. // For calculating ranks
  579. $statement = $connection->prepare(
  580. " CREATE OR REPLACE VIEW V_STUDENT_RANKS AS
  581. SELECT DISTINCT idStd , CAST( SUM(value*weight*coef) / sum(weight*coef) AS decimal(4,2)) as moyenne, sum(weight*coef) as totalCoef
  582. FROM ANNUAL_DATA
  583. GROUP BY idStd
  584. ORDER BY SUM(value*weight*coef) DESC"
  585. );
  586. $statement->execute();
  587. $annualAvg = $connection->executeQuery("SELECT * FROM V_STUDENT_RANKS ")->fetchAll();
  588. $rank = 0;
  589. $rankArray = [];
  590. foreach ($annualAvg as $avg) {
  591. $this->annualAvgArray[$avg['idStd']] = $avg['moyenne'];
  592. $rankArray[$avg['idStd']] = ++$rank;
  593. $this->sumAvg += $avg['moyenne'];
  594. }
  595. $this->snappy->setTimeout(600);
  596. $html = $this->renderView('classroom/reportcardYear.html.twig', array(
  597. 'year' => $year,
  598. 'data' => $dataYear,
  599. 'room' => $classroom,
  600. 'students' => $studentEnrolled,
  601. 'ranks' => $rankArray,
  602. 'means' => $this->annualAvgArray,
  603. 'genMean' => $this->sumAvg / sizeof($this->annualAvgArray),
  604. ));
  605. //return new Response($html);
  606. return new Response(
  607. $this->snappy->getOutputFromHtml($html),
  608. 200,
  609. array(
  610. 'Content-Type' => 'application/pdf',
  611. 'Content-Disposition' => 'attachment; filename="BUL_ANN_' . $classroom->getName() . '.pdf"',
  612. )
  613. );
  614. }
  615. /**
  616. * Finds and displays a Evaluation entity.
  617. *
  618. * @Route("/{room}/{seq}/pdf", name="admin_classrooms_recapitulatif", requirements={"room"="\d+","seq"="\d+"})
  619. * @Method("GET")
  620. * @Template()
  621. * @return Response
  622. */
  623. public function recapitulatifAction(ClassRoom $room, Sequence $seq)
  624. {
  625. // Année scolaire en cours
  626. $year = $this->schoolYearService->sessionYearById();
  627. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($room, $year);
  628. $html = $this->renderView('classroom/templating/recapitulatifseqvierge.html.twig', array(
  629. 'room' => $room,
  630. 'seq' => $seq,
  631. 'students' => $studentEnrolled,
  632. 'year' => $year,
  633. ));
  634. $options = [
  635. 'orientation' => 'Landscape', // Changer ici entre 'Portrait' ou 'Landscape'
  636. 'page-size' => 'A4', // Format de page
  637. ];
  638. return new Response(
  639. $this->pdf->getOutputFromHtml($html, $options),
  640. 200,
  641. array(
  642. 'Content-Type' => 'application/pdf',
  643. 'Content-Disposition' => 'inline; filename="fiche_recep_' . $room->getName() . '.pdf"'
  644. )
  645. );
  646. }
  647. /**
  648. * Finds and displays a ClassRoom entity.
  649. *
  650. * @Route("/{id}/recapitulatifseq", name="admin_classrooms_recapitulatif_seq", requirements={"id"="\d+"})
  651. * @Method("GET")
  652. * @Template()
  653. */
  654. public function recapSeqAction(ClassRoom $room, Request $request)
  655. {
  656. // set_time_limit(600);
  657. $checkedValues = $request->request->get('selected_courses');
  658. $em = $this->getDoctrine()->getManager();
  659. $year = $this->schoolYearService->sessionYearById();
  660. $seq = $this->seqRepo->findOneBy(array("activated" => true));
  661. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($room, $year);
  662. $datas = $this->markRepo->findMarksBySequenceAndClassOrderByStd($seq, $room);
  663. $html = $this->renderView('classroom/recapitulatifseq.html.twig', array(
  664. 'room' => $room,
  665. 'datas' => $datas,
  666. 'year' => $year,
  667. 'seq' => $seq,
  668. 'students' => $studentEnrolled,
  669. 'checkedValues' => $checkedValues
  670. ));
  671. return new Response($html);
  672. }
  673. /**
  674. * @Route("/create",name= "admin_classrooms_new", methods={"GET","POST"})
  675. */
  676. public function create(Request $request): Response
  677. {
  678. if (!$this->getUser()) {
  679. $this->addFlash('warning', 'You need login first!');
  680. return $this->redirectToRoute('app_login');
  681. }
  682. $schoolyear = new ClassRoom();
  683. $form = $this->createForm(ClassRoomType::class, $schoolyear);
  684. $form->handleRequest($request);
  685. if ($form->isSubmitted() && $form->isValid()) {
  686. $this->em->persist($schoolyear);
  687. $this->em->flush();
  688. $this->addFlash('success', 'ClassRoom succesfully created');
  689. return $this->redirectToRoute('admin_classrooms');
  690. }
  691. return $this->render(
  692. 'classroom/new.html.twig',
  693. ['form' => $form->createView()]
  694. );
  695. }
  696. /**
  697. * Rapport séquentiel d'enregistrement des notes.
  698. *
  699. * @Route("/{id}/evalrepport", name="admin_current_fulfilled_eval_show", requirements={"id"="\d+"})
  700. * @Method("GET")
  701. * @Template()
  702. */
  703. public function currentFullfilledEvalAction(ClassRoom $classroom)
  704. {
  705. $em = $this->getDoctrine()->getManager();
  706. $year = ($this->session->has('session_school_year') && ($this->session->get('session_school_year')!= null)) ? $this->session->get('session_school_year') : $this->scRepo->findOneBy(array("activated" => true));
  707. // Liste des séquences de l'année scolaire en cours
  708. $sequences = $em->getRepository('AppBundle:Sequence')->findSequencesBySchoolYear($year);
  709. // Liste des matières
  710. $courses = $em->getRepository('AppBundle:Course')->findProgrammedCoursesInClass($classroom);
  711. // Elèves inscrits
  712. foreach ($sequences as $seq) {
  713. // Lecture de chaque tableau de chaque ligne
  714. foreach ($courses as $course) {
  715. // Liste des évaluations
  716. $evaluation = $em->getRepository('AppBundle:Evaluation')->findOneBy(array(
  717. "classRoom" => $classroom,
  718. "sequence" => $seq, "course" => $course
  719. ));
  720. if ($evaluation != null) {
  721. $evaluations[$seq->getId()][$course->getId()] = 1;
  722. } else {
  723. $evaluations[$seq->getId()][$course->getId()] = 0;
  724. }
  725. }
  726. }
  727. return $this->render('classroom/eval_repport.html.twig', array(
  728. 'evaluations' => $evaluations,
  729. 'courses' => $courses,
  730. 'room' => $classroom,
  731. 'sequences' => $sequences,
  732. ));
  733. }
  734. /**
  735. * Displays a form to edit an existing ClassRoomme entity.
  736. *
  737. * @Route("/{id}/edit", name="admin_classrooms_edit", requirements={"id"="\d+"}, methods={"GET","PUT"})
  738. * @Template()
  739. */
  740. public function edit(Request $request, ClassRoom $room): Response
  741. {
  742. $form = $this->createForm(ClassRoomType::class, $room, [
  743. 'method' => 'PUT'
  744. ]);
  745. $form->handleRequest($request);
  746. if ($form->isSubmitted() && $form->isValid()) {
  747. $this->em->flush();
  748. $this->addFlash('success', 'ClassRoom succesfully updated');
  749. return $this->redirectToRoute('admin_classrooms');
  750. }
  751. return $this->render('classroom/edit.html.twig', [
  752. 'room' => $room,
  753. 'form' => $form->createView()
  754. ]);
  755. }
  756. /**
  757. * Deletes a ClassRoom entity.
  758. *
  759. * @Route("/{id}/delete", name="admin_classrooms_delete", requirements={"id"="\d+"}, methods={"DELETE"})
  760. */
  761. public function delete(ClassRoom $q, Request $request): Response
  762. {
  763. // if($this->isCsrfTokenValid('classrooms_deletion'.$schoolyear->getId(), $request->request->get('crsf_token') )){
  764. $this->em->remove($q);
  765. $this->em->flush();
  766. $this->addFlash('info', 'ClassRoom succesfully deleted');
  767. // }
  768. return $this->redirectToRoute('admin_classrooms');
  769. }
  770. /**
  771. * Finds and displays a ClassRoom entity.
  772. *
  773. * @Route("/{id}/fichesimple", name="admin_classrooms_fichesimple", requirements={"id"="\d+"})
  774. * @Method("GET")
  775. * @Template()
  776. */
  777. public function fichesiplmeAction(ClassRoom $classroom)
  778. {
  779. // Année scolaire en cours
  780. $year = $this->schoolYearService->sessionYearById();
  781. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year);
  782. $html = $this->renderView('classroom/templating/fiche_repport_notes.html.twig', array(
  783. 'year' => $year,
  784. 'room' => $classroom,
  785. 'students' => $studentEnrolled,
  786. ));
  787. return new Response(
  788. $this->pdf->getOutputFromHtml($html),
  789. 200,
  790. array(
  791. 'Content-Type' => 'application/pdf',
  792. 'Content-Disposition' => 'inline; filename="fiche_pv_' . $classroom->getName() . '.pdf"'
  793. )
  794. );
  795. }
  796. /**
  797. * Finds and displays a ClassRoom entity.
  798. *
  799. * @Route("/{id}/disciplinary_record", name="admin_classrooms_disciplinary_record", requirements={"id"="\d+"})
  800. * @Method("GET")
  801. * @Template()
  802. */
  803. public function ficheDisciplineAction(ClassRoom $classroom)
  804. {
  805. // Année scolaire en cours
  806. $year = $this->schoolYearService->sessionYearById();
  807. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year);
  808. $html = $this->renderView('classroom/templating/fiche_repport_disc.html.twig', array(
  809. 'year' => $year,
  810. 'room' => $classroom,
  811. 'students' => $studentEnrolled,
  812. ));
  813. return new Response(
  814. $this->pdf->getOutputFromHtml($html),
  815. 200,
  816. array(
  817. 'Content-Type' => 'application/pdf',
  818. 'Content-Disposition' => 'inline; filename="fich_disc_' . $classroom->getName() . '.pdf"'
  819. )
  820. );
  821. }
  822. /**
  823. * LISTE DES ELEVES DE LA CLASSE DANS UNE FICHE DE PRESENTATION.
  824. *
  825. * @Route("/{id}/presentation", name="admin_classrooms_presentation", requirements={"id"="\d+"})
  826. * @Method("GET")
  827. * @Template()
  828. */
  829. public function presentationAction(ClassRoom $classroom)
  830. {
  831. // Année scolaire en cours
  832. $year = $this->schoolYearService->sessionYearById();
  833. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year);
  834. $html = $this->renderView('classroom/templating/student_list.html.twig', array(
  835. 'year' => $year,
  836. 'room' => $classroom,
  837. 'students' => $studentEnrolled,
  838. ));
  839. return new Response(
  840. $this->pdf->getOutputFromHtml($html),
  841. 200,
  842. array(
  843. 'Content-Type' => 'application/pdf',
  844. 'Content-Disposition' => 'inline; filename="std_list_' . $classroom->getName() . '.pdf"'
  845. )
  846. );
  847. }
  848. /**
  849. * MOYENNE GENERALE DE LA CLASSE A UNE SEQUENCE
  850. * @Route("/{id_room}/{id_seq}/sqavg", name="admin_classrooms_avg_seq", requirements={"id_room"="\d+", "id_seq"="\d+"})
  851. * @ParamConverter("room", options={"mapping": {"id_room" : "id"}})
  852. * @ParamConverter("seq", options={"mapping": {"id_seq" : "id"}})
  853. * @Method("GET")
  854. * @Template()
  855. */
  856. public function generalSeqAverage(ClassRoom $room, Sequence $seq)
  857. {
  858. $dql = "SELECT SUM(evaluation.moyenne * course.coefficient)/SUM(course.coefficient) FROM App\Entity\Evaluation evaluation , App\Entity\Course course
  859. WHERE evaluation.course= course.id AND evaluation.sequence=?2 AND evaluation.classRoom=?1 ";
  860. $avg_seq1 = $this->em->createQuery($dql)
  861. ->setParameter(1, $room->getId())
  862. ->setParameter(2, $seq->getId())
  863. ->getSingleScalarResult();
  864. return round($avg_seq1, 2);
  865. }
  866. /**
  867. * MOYENNE GENERALE DE LA CLASSE A UN TRIMESTRE
  868. * @Route("/{id_room}/{id_quat}/qtavg", name="admin_classrooms_avg_quat", requirements={"id_room"="\d+", "id_quat"="\d+"})
  869. * @ParamConverter("room", options={"mapping": {"id_room" : "id"}})
  870. * @ParamConverter("quater", options={"mapping": {"id_quat" : "id"}})
  871. * @Method("GET")
  872. * @Template()
  873. */
  874. public function generalQuatAverage(ClassRoom $room, Quater $quater)
  875. {
  876. $dql = "SELECT SUM(evaluation.moyenne * course.coefficient)/SUM(course.coefficient) FROM App\Entity\Evaluation evaluation , App\Entity\Course course
  877. WHERE evaluation.course= course.id AND evaluation.sequence=?2 AND evaluation.classRoom=?1 ";
  878. $avg_seq = 0;
  879. foreach ($quater->getSequences() as $seq) {
  880. $avg_seq += $this->em->createQuery($dql)
  881. ->setParameter(1, $room->getId())
  882. ->setParameter(2, $seq->getId())
  883. ->getSingleScalarResult();
  884. }
  885. return round($avg_seq / 2, 2);
  886. }
  887. /**
  888. * Finds and displays a Evaluation entity.
  889. *
  890. * @Route("/{room}/pdf", name="admin_classrooms_blanc_ann", requirements={"room"="\d+"})
  891. * @Method("GET")
  892. * @Template()
  893. * @return Response
  894. */
  895. public function annualSummaryAction(ClassRoom $room)
  896. {
  897. $year = $this->schoolYearService->sessionYearById();
  898. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($room, $year);
  899. $html = $this->renderView('classroom/templating/blankAnnualForm.html.twig', array(
  900. 'room' => $room,
  901. 'students' => $studentEnrolled,
  902. 'year' => $year,
  903. ));
  904. return new Response(
  905. $this->pdf->getOutputFromHtml($html, array(
  906. 'default-header' => false
  907. )),
  908. 200,
  909. array(
  910. 'Content-Type' => 'application/pdf',
  911. 'Content-Disposition' => 'attachment; filename="recap_empty_' . $room->getName() . '.pdf"',
  912. )
  913. );
  914. }
  915. /**
  916. * Finds and displays a ClassRoom entity.
  917. *
  918. * @Route("/{id}/reportCardSeq", name="admin_classrooms_reportcards_seq", requirements={"id"="\d+"})
  919. * @Method("GET")
  920. * @Template()
  921. */
  922. public function reportCardSeqAction(ClassRoom $classroom)
  923. {
  924. set_time_limit(600);
  925. $totalNtCoef = 0;
  926. $totalCoef = 0;
  927. $em = $this->getDoctrine()->getManager();
  928. $year =$this->schoolYearService->sessionYearById();
  929. $sequence = $this->seqRepo->findOneBy(array("activated" => true));
  930. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year);
  931. // Existance des photos d'eleves
  932. $evaluations = $this->evalRepo->findSequantialExamsOfRoom($classroom->getId(), $sequence->getId());
  933. foreach ($evaluations as $ev) {
  934. $totalNtCoef += $ev->getMoyenne() * $ev->getCourse()->getCoefficient();
  935. $totalCoef += $ev->getCourse()->getCoefficient();
  936. }
  937. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year);
  938. $this->getViewSeqData($classroom, $sequence);
  939. $connection = $this->em->getConnection();
  940. $datas = $connection->executeQuery("SELECT * FROM V_STUDENT_MARK_SEQ0 ")->fetchAll();
  941. // For calculating ranks
  942. $statement = $connection->prepare(
  943. " CREATE OR REPLACE VIEW V_STUDENT_RANKS AS
  944. SELECT DISTINCT std , CAST( SUM(value*weight*coef) / sum(weight*coef) AS decimal(4,2)) as moyenne, sum(weight*coef) as totalCoef
  945. FROM V_STUDENT_MARK_SEQ0
  946. GROUP BY std
  947. ORDER BY SUM(value*weight*coef) DESC"
  948. );
  949. $statement->execute();
  950. $seqAvg = $connection->executeQuery("SELECT * FROM V_STUDENT_RANKS ")->fetchAll();
  951. $seqAvgArray = [];
  952. $sumAvg = 0;
  953. $rank = 0;
  954. $rankArray = [];
  955. foreach ($seqAvg as $avg) {
  956. $seqAvgArray[$avg['std']] = $avg['moyenne'];
  957. $rankArray[$avg['std']] = ++$rank;
  958. $sumAvg += $avg['moyenne'];
  959. }
  960. // CAS DES ABSCENCES SEQUENTIELLES
  961. $statement = $connection->prepare(
  962. " CREATE OR REPLACE VIEW V_STUDENT_ABSCENCE_SEQ AS
  963. SELECT DISTINCT seq.std as std , seq.total_hours as abscences
  964. FROM V_STUDENT_ABSCENCE_SEQ0 seq
  965. ORDER BY std "
  966. );
  967. $statement->execute();
  968. // Traitement des abscences
  969. $absences = $connection->executeQuery("SELECT * FROM V_STUDENT_ABSCENCE_SEQ ")->fetchAll();
  970. $absencesArray = [];
  971. foreach ($absences as $abs) {
  972. $absencesArray[$abs['std']] = $abs['abscences'];
  973. }
  974. $html = $this->renderView('classroom/reportcard/sequential.html.twig', array(
  975. 'year' => $year,
  976. 'datas' => $datas,
  977. 'students' => $studentEnrolled,
  978. 'sequence' => $sequence,
  979. 'quater' => $sequence->getQuater(),
  980. 'room' => $classroom,
  981. 'students' => $studentEnrolled,
  982. 'means' => $seqAvgArray,
  983. 'abscences' => $absencesArray,
  984. 'genMean' => $sumAvg / sizeof($seqAvgArray),
  985. 'ranks' => $rankArray,
  986. 'fileExists'=> $this->fileExists($classroom, $year)
  987. ));
  988. return new Response(
  989. $this->pdf->getOutputFromHtml($html),
  990. 200,
  991. array(
  992. 'Content-Type' => 'application/pdf',
  993. 'Content-Disposition' => 'inline; filename="bull_seq_' . $classroom->getName() . '.pdf"'
  994. )
  995. );
  996. }
  997. public function buildAbsViewSeq(ClassRoom $room,Sequence $seq){
  998. $connection = $this->em->getConnection();
  999. $statement = $connection->prepare(
  1000. " CREATE OR REPLACE VIEW V_STUDENT_ABSCENCE_SEQ" . $room->getId() ."_".$seq->getId()." AS
  1001. SELECT DISTINCT abs.student_id as std, sum( abs.weight) as total_hours
  1002. FROM class_room room
  1003. LEFT JOIN abscence_sheet sheet ON sheet.class_room_id = room.id AND sheet.sequence_id = ?
  1004. LEFT JOIN abscence abs ON sheet.id = abs.abscence_sheet_id
  1005. WHERE room.id = ?
  1006. GROUP BY std
  1007. ORDER BY std; "
  1008. );
  1009. $statement->bindValue(1, $seq->getId());
  1010. $statement->bindValue(2, $room->getId());
  1011. $statement->execute();
  1012. }
  1013. public function getAbsSeqFromView(ClassRoom $room,Sequence $seq){
  1014. $connection = $this->em->getConnection();
  1015. return $connection->executeQuery("SELECT * FROM V_STUDENT_ABSCENCE_SEQ".$room->getId()."_".$seq->getId()." ")->fetchAllAssociative();
  1016. }
  1017. // Vue des abscences d'eleves d'une classe durant un trimestre
  1018. public function buildAbsQuaterView(ClassRoom $room,Quater $quater){
  1019. $sequences = $this->seqRepo->findBy(array("quater" => $quater));
  1020. foreach ($sequences as $seq) {
  1021. $this->buildAbsViewSeq($room, $seq);
  1022. }
  1023. $year = $this->schoolYearService->sessionYearById();
  1024. // CAS DES ABSCENCES TRIMESTRIELLES
  1025. $query =
  1026. " CREATE OR REPLACE VIEW V_STUDENT_ABSCENCE_QUATER" . $room->getId() . "_" . $quater->getId() . " AS
  1027. SELECT DISTINCT
  1028. seq1.std AS std,
  1029. seq1.total_hours + IFNULL(seq2.total_hours, 0) AS total_hours
  1030. FROM V_STUDENT_ABSCENCE_SEQ" . $room->getId() . "_" . $sequences[0]->getId() . " seq1
  1031. LEFT JOIN V_STUDENT_ABSCENCE_SEQ" . $room->getId() . "_" . $sequences[1]->getId() . " seq2
  1032. ON seq1.std = seq2.std
  1033. UNION
  1034. SELECT DISTINCT
  1035. seq2.std AS std,
  1036. IFNULL(seq1.total_hours, 0) + seq2.total_hours AS total_hours
  1037. FROM V_STUDENT_ABSCENCE_SEQ" . $room->getId() . "_" . $sequences[1]->getId() . " seq2
  1038. LEFT JOIN V_STUDENT_ABSCENCE_SEQ" . $room->getId() . "_" . $sequences[0]->getId() . " seq1
  1039. ON seq1.std = seq2.std
  1040. ORDER BY std;
  1041. ";
  1042. $connection = $this->em->getConnection();
  1043. $connection->executeQuery($query);
  1044. }
  1045. public function getAbsQuaterFromView(ClassRoom $room, Quater $quater){
  1046. $this->buildAbsQuaterView($room, $quater);
  1047. $query = "select * from V_STUDENT_ABSCENCE_QUATER".$room->getId()."_".$quater->getId()." ;";
  1048. $connection = $this->em->getConnection();
  1049. $absences = $connection->executeQuery( $query )->fetchAll();
  1050. $absencesArray = [];
  1051. foreach ($absences as $abs) {
  1052. $absencesArray[$abs['std']] = $abs['total_hours'];
  1053. }
  1054. return $absencesArray;
  1055. }
  1056. public function getViewSeqData(ClassRoom $room,Sequence $seq){
  1057. $connection = $this->em->getConnection();
  1058. $year = $this->schoolYearService->sessionYearById();
  1059. // CAS DES NOTES SEQUENTIELLES
  1060. $statement = $connection->prepare(
  1061. " CREATE OR REPLACE VIEW V_STUDENT_MARK_SEQ".$room->getId()."_". $seq->getId(). " AS
  1062. SELECT DISTINCT eval.id as eval,crs.id as crs, crs.coefficient as coef, room.id as room, std.id as std, teach.full_name as teacher , modu.id as module,m.value as value, m.weight as weight
  1063. FROM mark m JOIN student std ON m.student_id = std.id
  1064. JOIN evaluation eval ON m.evaluation_id = eval.id
  1065. JOIN class_room room ON eval.class_room_id = room.id
  1066. JOIN course crs ON eval.course_id = crs.id
  1067. JOIN attribution att ON att.course_id = crs.id and att.year_id = ?
  1068. JOIN user teach ON att.teacher_id = teach.id
  1069. JOIN module modu ON modu.id = crs.module_id
  1070. JOIN sequence seq ON seq.id = eval.sequence_id
  1071. LEFT JOIN abscence_sheet sheet ON seq.id = sheet.sequence_id AND sheet.class_room_id = room.id
  1072. LEFT JOIN abscence abs ON sheet.id = abs.abscence_sheet_id
  1073. JOIN quater quat ON seq.quater_id = quat.id
  1074. WHERE room.id = ? AND eval.sequence_id =?
  1075. ORDER BY room.id,modu.id , std; "
  1076. );
  1077. $statement->bindValue(1, $year->getId());
  1078. $statement->bindValue(2, $room->getId());
  1079. $statement->bindValue(3, $seq->getId());
  1080. $statement->execute();
  1081. $statement = $connection->prepare(
  1082. " CREATE OR REPLACE VIEW V_STUDENT_ABSCENCE_SEQ" . $room->getId()."_". $seq->getId() . " AS
  1083. SELECT DISTINCT room.id as room, abs.student_id as std, sum( abs.weight) as total_hours
  1084. FROM class_room room
  1085. LEFT JOIN abscence_sheet sheet ON sheet.class_room_id = room.id AND sheet.sequence_id = ?
  1086. LEFT JOIN abscence abs ON sheet.id = abs.abscence_sheet_id
  1087. WHERE room.id = ?
  1088. GROUP BY std
  1089. ORDER BY room.id, std; "
  1090. );
  1091. $statement->bindValue(1, $seq->getId());
  1092. $statement->bindValue(2, $room->getId());
  1093. $statement->execute();
  1094. }
  1095. public function getViewSeqMark2024(ClassRoom $room,Sequence $seq){
  1096. $connection = $this->em->getConnection();
  1097. $year = $this->schoolYearService->sessionYearById();
  1098. // CAS DES NOTES SEQUENTIELLES
  1099. $statement = $connection->prepare(
  1100. " CREATE OR REPLACE VIEW V_STUDENT_MARK_SEQ".$room->getId()."_".$seq->getId(). " AS
  1101. SELECT DISTINCT crs.id as crs, crs.coefficient as coef, std.id as std,m.value as value, m.weight as weight, eval.mini as mini , eval.maxi as maxi
  1102. FROM mark m JOIN student std ON m.student_id = std.id
  1103. JOIN evaluation eval ON m.evaluation_id = eval.id
  1104. JOIN class_room room ON eval.class_room_id = room.id
  1105. JOIN course crs ON eval.course_id = crs.id
  1106. JOIN sequence seq ON seq.id = eval.sequence_id
  1107. WHERE room.id = ? AND eval.sequence_id =?
  1108. ORDER BY std, crs; "
  1109. );
  1110. $statement->bindValue(1, $room->getId());
  1111. $statement->bindValue(2, $seq->getId());
  1112. $statement->execute();
  1113. }
  1114. /**
  1115. * Finds and displays a ClassRoom entity.
  1116. *
  1117. * @Route("/{id}/reportCardsTrim", name="admin_classrooms_reportcards_trim", requirements={"id"="\d+"})
  1118. * @Method("GET")
  1119. * @Template()
  1120. */
  1121. public function reportCardsTrimAction(ClassRoom $room, Request $request)
  1122. {
  1123. $connection = $this->em->getConnection();
  1124. $year = $this->schoolYearService->sessionYearById();
  1125. $quater = $this->qtRepo->findOneBy(array("activated" => true));
  1126. $sequences = $this->seqRepo->findBy(array("quater" => $quater));
  1127. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($room, $year);
  1128. // Existance des photos d'eleves
  1129. $this->fileExists($classroom, $year);
  1130. /*******************************************************************************************************************/
  1131. /***************CREATION DE la VIEW DES NOTES SEQUENTIELLES, TRIMESTRIELLES DE LA CLASSE, AINSI QUE DE LA VIEW DES ABSCENCES**************/
  1132. /*******************************************************************************************************************/
  1133. foreach ($sequences as $seq) {
  1134. // CAS DES NOTES et ABSCENCES SEQUENTIELLES
  1135. $this->getViewSeqData($room, $seq);
  1136. }
  1137. // CAS DES NOTES TRIMESTRIELLES
  1138. $statement = $connection->prepare(
  1139. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER AS
  1140. SELECT DISTINCT seq1.std as std , seq1.crs as crs , seq1.coef as coef, seq1.value as value1, seq1.weight as weight1,seq2.value as value2, seq2.weight as weight2, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , seq1.teacher as teacher, seq1.module as module, seq1.room as room
  1141. FROM V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[0]->getId()." seq1
  1142. JOIN V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[1]->getId()." seq2 ON (seq1.std = seq2.std AND seq1.crs = seq2.crs )
  1143. ORDER BY std , module"
  1144. );
  1145. $statement->execute();
  1146. // CAS DES ABSCENCES TRIMESTRIELLES
  1147. $statement = $connection->prepare(
  1148. " CREATE OR REPLACE VIEW V_STUDENT_ABSCENCE_QUATER AS
  1149. SELECT DISTINCT seq1.std as std , seq1.total_hours + seq2.total_hours as abscences
  1150. FROM V_STUDENT_ABSCENCE_SEQ1 seq1
  1151. LEFT JOIN V_STUDENT_ABSCENCE_SEQ2 seq2 ON (seq1.std = seq2.std )
  1152. ORDER BY std "
  1153. );
  1154. $statement->execute();
  1155. $dataQuater = $connection->executeQuery("SELECT * FROM V_STUDENT_MARK_QUATER marks ")->fetchAll();
  1156. // For calculating ranks
  1157. $statement = $connection->prepare(
  1158. " CREATE OR REPLACE VIEW V_STUDENT_RANKS AS
  1159. SELECT DISTINCT std , CAST( SUM(value*weight*coef) / sum(weight*coef) AS decimal(4,2)) as moyenne, sum(weight*coef) as totalCoef
  1160. FROM V_STUDENT_MARK_QUATER
  1161. GROUP BY std
  1162. ORDER BY SUM(value*weight*coef) DESC"
  1163. );
  1164. $statement->execute();
  1165. $quaterAvg = $connection->executeQuery("SELECT * FROM V_STUDENT_RANKS ")->fetchAll();
  1166. $quaterAvgArray = [];
  1167. $sumAvg = 0;
  1168. $rank = 0;
  1169. $rankArray = [];
  1170. foreach ($quaterAvg as $avg) {
  1171. $quaterAvgArray[$avg['std']] = $avg['moyenne'];
  1172. $rankArray[$avg['std']] = ++$rank;
  1173. $sumAvg += $avg['moyenne'];
  1174. }
  1175. // Traitement des abscences
  1176. $absences = $connection->executeQuery("SELECT * FROM V_STUDENT_ABSCENCE_QUATER ")->fetchAll();
  1177. $absencesArray = [];
  1178. foreach ($absences as $abs) {
  1179. $absencesArray[$abs['std']] = $abs['abscences'];
  1180. }
  1181. $this->pdf->setTimeout(600);
  1182. $html = $this->renderView('classroom/reportcard/quaterly_2024.html.twig', array(
  1183. 'year' => $year,
  1184. 'data' => $dataQuater,
  1185. 'ranks' => $rankArray,
  1186. 'means' => $quaterAvgArray,
  1187. 'abscences' => $absencesArray,
  1188. 'genMean' => $sumAvg / sizeof($quaterAvgArray),
  1189. 'room' => $room,
  1190. 'quater' => $quater,
  1191. 'sequences' => $sequences,
  1192. 'students' => $studentEnrolled,
  1193. 'fileExists'=> $fileExists
  1194. ));
  1195. return new Response(
  1196. $this->pdf->getOutputFromHtml($html),
  1197. 200,
  1198. array(
  1199. 'Content-Type' => 'application/pdf',
  1200. 'Content-Disposition' => 'inline; filename="' . $room->getName() . '.pdf"'
  1201. )
  1202. );
  1203. // return new Response($html);
  1204. }
  1205. /**
  1206. * Finds and displays a ClassRoom entity.
  1207. *
  1208. * @Route("/{id}/reportCardsTrim2024", name="admin_classrooms_reportcards_trim_2024", requirements={"id"="\d+"})
  1209. * @Method("GET")
  1210. * @Template()
  1211. */
  1212. public function reportCardsTrim2024Action(ClassRoom $room, Request $request)
  1213. {
  1214. if (!$this->getUser()) {
  1215. $this->addFlash('warning', 'You need login first!');
  1216. return $this->redirectToRoute('app_login');
  1217. }
  1218. if (!$this->getUser()->isVerified()) {
  1219. $this->addFlash('warning', 'You need to have a verified account!');
  1220. return $this->redirectToRoute('app_login');
  1221. }
  1222. $copyright = $request->request->get('copyright') == "on";
  1223. $reverse = $request->request->get('reverse') == "on";
  1224. // Zoom : l'utilisateur règle entre 0.70 et 1.00 via la modale.
  1225. // 1.00 = pleine largeur A4 (défaut). Réduire si le bulletin déborde.
  1226. $scale = $request->request->get('scale')
  1227. ? max(0.70, min(1.00, (float) $request->request->get('scale')))
  1228. : 1.0;
  1229. $connection = $this->em->getConnection();
  1230. $year = $this->schoolYearService->sessionYearById();
  1231. $quater = $this->qtRepo->findOneBy(array("activated" => true));
  1232. $students = $this->stdRepo->findEnrolledStudentsThisYearInClass($room, $year);
  1233. $mainTeacher = $this->mainTeacherRepo->findOneBy(array("classRoom" => $room, "schoolYear" => $year))-> getTeacher();
  1234. // Retrieve of marks
  1235. $query = " SELECT DISTINCT student.id as student_id, student.firstname as student_firstname, student.lastname as student_last_name, student.birthday as student_birthday, student.matricule as matricule, sequence.id as sequence, course.id as course_id ,course.wording , course.coefficient, mark.value, mark.weight, mark.rank2, evaluation.mini as mini, evaluation.maxi as maxi, evaluation.competence, attribution.teacher_id, school_year.id, user.full_name
  1236. FROM sequence
  1237. JOIN evaluation ON evaluation.sequence_id = sequence.id AND evaluation.class_room_id = :room_id
  1238. JOIN course ON evaluation.course_id = course.id
  1239. JOIN attribution on attribution.course_id = course.id
  1240. JOIN user ON user.id = attribution.teacher_id
  1241. JOIN mark ON evaluation.id = mark.evaluation_id
  1242. JOIN student ON mark.student_id = student.id
  1243. JOIN quater ON sequence.quater_id = quater.id
  1244. JOIN school_year on quater.school_year_id= school_year.id and school_year.id = attribution.year_id
  1245. WHERE quater.id = :quater_id
  1246. ORDER BY student_id, course.id,sequence.id; ";
  1247. $params = [
  1248. 'quater_id' => $quater->getId(),
  1249. 'room_id' => $room->getId(), // Remplace :room_id
  1250. ];
  1251. $result = $connection->executeQuery($query, $params);
  1252. $dataMarks = $result->fetchAllAssociative();
  1253. $sequences = $this->seqRepo->findBy(array("quater" => $quater));
  1254. // Calculation of rank and general average
  1255. foreach ($sequences as $seq) {
  1256. $this->getViewSeqMark2024($room,$seq);
  1257. }
  1258. // CAS DES NOTES TRIMESTRIELLES
  1259. $query =
  1260. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER AS
  1261. SELECT DISTINCT seq1.std as std , seq1.crs as crs , seq1.coef as coef, seq1.value as value1, seq1.weight as weight1,seq2.value as value2, seq2.weight as weight2, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , (seq1.mini + seq2.mini)/2 as mini, (seq1.maxi + seq2.maxi)/2 as maxi
  1262. FROM V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[0]->getId()." seq1
  1263. LEFT JOIN V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[1]->getId()." seq2 ON (seq1.std = seq2.std AND seq1.crs = seq2.crs )
  1264. ORDER BY std ";
  1265. $connection->executeQuery($query);
  1266. $statement = $connection->prepare(
  1267. " CREATE OR REPLACE VIEW V_STUDENT_RANKS AS
  1268. SELECT DISTINCT std , CAST( SUM(value*weight*coef) / sum(weight*coef) AS decimal(4,2)) as moyenne, sum(weight*coef) as totalCoef
  1269. FROM V_STUDENT_MARK_QUATER
  1270. GROUP BY std
  1271. ORDER BY SUM(value*weight*coef) DESC"
  1272. );
  1273. $statement->execute();
  1274. $quaterAvg = $connection->executeQuery("SELECT * FROM V_STUDENT_RANKS ")->fetchAll();
  1275. $quaterAvgArray = [];
  1276. $sumAvg = 0;
  1277. $rank = 0;
  1278. $minAgv = 20;
  1279. $maxAvg = 0;
  1280. $rankArray = [];
  1281. foreach ($quaterAvg as $avg) {
  1282. $quaterAvgArray[$avg['std']] = $avg['moyenne'];
  1283. $rankArray[$avg['std']] = ++$rank;
  1284. $sumAvg += $avg['moyenne'];
  1285. if($minAgv > $avg['moyenne']){
  1286. $minAgv = $avg['moyenne'];
  1287. }
  1288. if($maxAvg < $avg['moyenne']){
  1289. $maxAvg = $avg['moyenne'];
  1290. }
  1291. }
  1292. $html = $this->renderView('classroom/reportcard/quaterly_2024.html.twig', array(
  1293. 'genMean' => $sumAvg / sizeof($quaterAvgArray),
  1294. 'ranks' => $rankArray,
  1295. 'year' => $year,
  1296. 'minAvg' => $minAgv,
  1297. 'maxAvg' => $maxAvg,
  1298. 'quater' => $quater,
  1299. 'mainTeacher' => $mainTeacher,
  1300. 'dataMarks' => $dataMarks,
  1301. 'dataAbs' => $this->getAbsQuaterFromView($room, $quater),
  1302. 'students' => $this->stdRepo->findEnrolledStudentsThisYearInClass($room, $year),
  1303. 'room' => $room,
  1304. 'fileExists' => $this->fileExists($room, $year),
  1305. 'copyright' => $copyright,
  1306. 'reverse' => $reverse,
  1307. 'scale' => $scale,
  1308. ));
  1309. return new Response(
  1310. $this->pdf->getOutputFromHtml($html),
  1311. 200,
  1312. array(
  1313. 'Content-Type' => 'application/pdf',
  1314. 'Content-Disposition' => 'inline; filename="bull_' . $quater->getId() . '.pdf"'
  1315. )
  1316. );
  1317. }
  1318. /**
  1319. * Finds and displays a ClassRoom entity.
  1320. *
  1321. * @Route("/{id}/annualavglist", name="admin_avg_list", requirements={"id"="\d+"})
  1322. * @Method("GET")
  1323. * @Template()
  1324. */
  1325. public function annualAvgList(ClassRoom $classroom, Request $request)
  1326. {
  1327. $connection = $this->em->getConnection();
  1328. $year = $this->schoolYearService->sessionYearById();
  1329. $quater = $this->qtRepo->findOneBy(array("activated" => true));
  1330. $sequences = $this->seqRepo->findSequenceThisYear($year);
  1331. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year);
  1332. /*******************************************************************************************************************/
  1333. /***************CREATION DE la VIEW DES NOTES SEQUENTIELLES, TRIMESTRIELLES DE LA CLASSE, AINSI QUE DE LA VIEW DES ABSCENCES**************/
  1334. /*******************************************************************************************************************/
  1335. foreach ($sequences as $seq) {
  1336. // CAS DES NOTES et ABSCENCES SEQUENTIELLES
  1337. $this->getViewSeqData($classroom, $seq);
  1338. $i++;
  1339. }
  1340. // CAS DES NOTES TRIMESTRIELLES1
  1341. $statement = $connection->prepare(
  1342. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER_1 AS
  1343. SELECT DISTINCT seq1.std as std , seq1.crs as crs , seq1.coef as coef, seq1.value as value1, seq1.weight as weight1,seq2.value as value2, seq2.weight as weight2, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  1344. FROM V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[0]->getId()." seq1
  1345. LEFT JOIN V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[1]->getId()." seq2 ON (seq1.std = seq2.std AND seq1.crs = seq2.crs )
  1346. ORDER BY std , modu"
  1347. );
  1348. $statement->execute();
  1349. // CAS DES NOTES TRIMESTRIELLES2
  1350. $statement = $connection->prepare(
  1351. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER_2 AS
  1352. SELECT DISTINCT seq1.std as std , seq1.crs as crs , seq1.coef as coef, seq1.value as value1, seq1.weight as weight1,seq2.value as value2, seq2.weight as weight2, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  1353. FROM V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[2]->getId()." seq1
  1354. JOIN V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[3]->getId()." seq2 ON (seq1.std = seq2.std AND seq1.crs = seq2.crs )
  1355. ORDER BY std , modu"
  1356. );
  1357. $statement->execute();
  1358. // CAS DES NOTES TRIMESTRIELLES3
  1359. $statement = $connection->prepare(
  1360. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER_3 AS
  1361. SELECT DISTINCT seq1.std as std , seq1.crs as crs , seq1.coef as coef, seq1.value as value1, seq1.weight as weight1,seq2.value as value2, seq2.weight as weight2, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  1362. FROM V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[4]->getId()." seq1
  1363. JOIN V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[5]->getId()." seq2 ON (seq1.std = seq2.std AND seq1.crs = seq2.crs )
  1364. ORDER BY std , modu"
  1365. );
  1366. $statement->execute();
  1367. $statement = $connection->prepare(
  1368. "CREATE OR REPLACE VIEW ANNUAL_DATA AS
  1369. SELECT DISTINCT student.id as idStd , student.matricule as matricule
  1370. student.lastname as lastname, student.firstname as firstname
  1371. course.wording as course, course.coefficient as coef,
  1372. module.name as module,
  1373. user.full_name as teacher,
  1374. quat1.std, quat1.modu,
  1375. quat1.value as value1, quat1.weight as weight1,
  1376. quat2.value as value2, quat2.weight as weight2,
  1377. quat3.value as value3, quat3.weight as weight3,
  1378. greatest(quat1.weight , quat2.weight, quat3.weight ) as weight,
  1379. ( quat1.value*quat1.weight+ quat2.value*quat2.weight + quat3.value*quat3.weight) /(quat1.weight+quat2.weight+quat3.weight) as value
  1380. FROM student
  1381. LEFT JOIN V_STUDENT_MARK_QUATER_1 quat1 ON student.id = quat1.std
  1382. LEFT JOIN V_STUDENT_MARK_QUATER_2 quat2 ON student.id = quat2.std AND quat1.crs = quat2.crs
  1383. LEFT JOIN V_STUDENT_MARK_QUATER_3 quat3 ON student.id = quat3.std AND quat2.crs = quat3.crs
  1384. JOIN class_room ON class_room.id = quat1.room
  1385. JOIN course ON course.id = quat1.crs
  1386. JOIN module ON course.module_id = quat1.modu
  1387. JOIN user ON user.full_name = quat1.teacher
  1388. ORDER BY quat1.std, quat1.modu
  1389. "
  1390. );
  1391. $statement->execute();
  1392. $dataYear = $connection->executeQuery("SELECT * FROM ANNUAL_DATA ")->fetchAll();
  1393. // For calculating ranks
  1394. $statement = $connection->prepare(
  1395. " CREATE OR REPLACE VIEW V_STUDENT_RANKS AS
  1396. SELECT DISTINCT idStd , CAST( SUM(value*weight*coef) / sum(weight*coef) AS decimal(4,2)) as moyenne, sum(weight*coef) as totalCoef
  1397. FROM ANNUAL_DATA
  1398. GROUP BY idStd
  1399. ORDER BY SUM(value*weight*coef) DESC"
  1400. );
  1401. $statement->execute();
  1402. $annualAvg = $connection->executeQuery("SELECT * FROM V_STUDENT_RANKS ")->fetchAll();
  1403. $rank = 0;
  1404. $rankArray = [];
  1405. foreach ($annualAvg as $avg) {
  1406. $this->annualAvgArray[$avg['idStd']] = $avg['moyenne'];
  1407. $rankArray[$avg['idStd']] = ++$rank;
  1408. $this->sumAvg += $avg['moyenne'];
  1409. }
  1410. $html = $this->renderView('classroom/avglist.html.twig', array(
  1411. 'year' => $year,
  1412. 'room' => $classroom,
  1413. 'students' => $studentEnrolled,
  1414. 'ranks' => $rankArray,
  1415. 'means' => $this->annualAvgArray,
  1416. 'genMean' => $sumAvg / sizeof($this->annualAvgArray),
  1417. ));
  1418. return new Response(
  1419. $this->snappy->getOutputFromHtml($html, [
  1420. 'page-size' => 'A4',
  1421. ]),
  1422. 200,
  1423. array(
  1424. 'Content-Type' => 'application/pdf',
  1425. 'Content-Disposition' => 'attachment; filename="BUL_ANN_' . $classroom->getName() . '.pdf"',
  1426. )
  1427. );
  1428. }
  1429. /**
  1430. * Finds and displays a ClassRoom entity.
  1431. *
  1432. * @Route("/{id}/reportCards3ApcYearApc", name="admin_class_reportcards_3_apc_year", requirements={"id"="\d+"})
  1433. * @Method("GET")
  1434. * @Template()
  1435. */
  1436. public function reportCards3YearAction(ClassRoom $classroom, Request $request)
  1437. {
  1438. $headerFontSize = $request->request->get('header_font_size');
  1439. $lineHeight = $request->request->get('line_height');
  1440. $copyright = $request->request->get('copyright')=="on";
  1441. $reverse = $request->request->get('reverse')=="on";
  1442. $connection = $this->em->getConnection();
  1443. $year = $this->schoolYearService->sessionYearById();
  1444. $quater = $this->qtRepo->findOneBy(array("activated" => true));
  1445. $sequences = $this->seqRepo->findSequenceThisYear($year);
  1446. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($classroom, $year);
  1447. // Existance des photos d'eleves
  1448. $this->fileExists($classroom, $year);
  1449. /*******************************************************************************************************************/
  1450. /***************CREATION DE la VIEW DES NOTES SEQUENTIELLES, TRIMESTRIELLES DE LA CLASSE, AINSI QUE DE LA VIEW DES ABSCENCES**************/
  1451. /*******************************************************************************************************************/
  1452. foreach ($sequences as $seq) {
  1453. // CAS DES NOTES et ABSCENCES SEQUENTIELLES
  1454. $this->getViewSeqData($classroom, $seq);
  1455. }
  1456. // CAS DES NOTES TRIMESTRIELLES1
  1457. $statement = $connection->prepare(
  1458. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER_1 AS
  1459. SELECT DISTINCT seq1.std as std , seq1.crs as crs , seq1.coef as coef, seq1.value as value1, seq1.weight as weight1,seq2.value as value2, seq2.weight as weight2, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  1460. FROM V_STUDENT_MARK_SEQ1 seq1
  1461. LEFT JOIN V_STUDENT_MARK_SEQ2 seq2 ON (seq1.std = seq2.std AND seq1.crs = seq2.crs )
  1462. ORDER BY std , modu"
  1463. );
  1464. $statement->execute();
  1465. // CAS DES ABSCENCES TRIMESTRIELLES1
  1466. $statement = $connection->prepare(
  1467. " CREATE OR REPLACE VIEW V_STUDENT_ABSCENCE_QUATER_1 AS
  1468. SELECT DISTINCT seq1.std as std , seq1.total_hours + seq2.total_hours as abscences
  1469. FROM V_STUDENT_ABSCENCE_SEQ1 seq1
  1470. LEFT JOIN V_STUDENT_ABSCENCE_SEQ2 seq2 ON (seq1.std = seq2.std )
  1471. ORDER BY std "
  1472. );
  1473. $statement->execute();
  1474. // CAS DES NOTES TRIMESTRIELLES2
  1475. $statement = $connection->prepare(
  1476. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER_2 AS
  1477. SELECT DISTINCT seq1.std as std , seq1.crs as crs , seq1.coef as coef, seq1.value as value1, seq1.weight as weight1,seq2.value as value2, seq2.weight as weight2, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  1478. FROM V_STUDENT_MARK_SEQ3 seq1
  1479. LEFT JOIN V_STUDENT_MARK_SEQ4 seq2 ON (seq1.std = seq2.std AND seq1.crs = seq2.crs )
  1480. ORDER BY std , modu"
  1481. );
  1482. $statement->execute();
  1483. // CAS DES ABSCENCES TRIMESTRIELLES2
  1484. $statement = $connection->prepare(
  1485. " CREATE OR REPLACE VIEW V_STUDENT_ABSCENCE_QUATER_2 AS
  1486. SELECT DISTINCT seq1.std as std , seq1.total_hours + seq2.total_hours as abscences
  1487. FROM V_STUDENT_ABSCENCE_SEQ3 seq1
  1488. JOIN V_STUDENT_ABSCENCE_SEQ4 seq2 ON (seq1.std = seq2.std )
  1489. ORDER BY std "
  1490. );
  1491. $statement->execute();
  1492. // CAS DES NOTES TRIMESTRIELLES3
  1493. $statement = $connection->prepare(
  1494. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER_3 AS
  1495. SELECT DISTINCT seq1.std as std , seq1.crs as crs , seq1.coef as coef, seq1.value as value1, seq1.weight as weight1,seq2.value as value2, seq2.weight as weight2, (seq1.value*seq1.weight + seq2.value*seq2.weight)/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  1496. FROM V_STUDENT_MARK_SEQ5 seq1
  1497. JOIN V_STUDENT_MARK_SEQ6 seq2 ON (seq1.std = seq2.std AND seq1.crs = seq2.crs )
  1498. ORDER BY std , modu"
  1499. );
  1500. $statement->execute();
  1501. // CAS DES ABSCENCES TRIMESTRIELLES3
  1502. $statement = $connection->prepare(
  1503. " CREATE OR REPLACE VIEW V_STUDENT_ABSCENCE_QUATER_3 AS
  1504. SELECT DISTINCT seq1.std as std , seq1.total_hours + seq2.total_hours as abscences
  1505. FROM V_STUDENT_ABSCENCE_SEQ5 seq1
  1506. LEFT JOIN V_STUDENT_ABSCENCE_SEQ6 seq2 ON (seq1.std = seq2.std )
  1507. ORDER BY std "
  1508. );
  1509. $statement->execute();
  1510. set_time_limit(600);
  1511. $statement = $connection->prepare(
  1512. "CREATE OR REPLACE VIEW ANNUAL_DATA AS
  1513. SELECT DISTINCT student.id as idStd , student.matricule as matricule , student.image_name as profileImagePath,
  1514. student.lastname as lastname, student.firstname as firstname, student.birthday as birthday,
  1515. student.gender as gender,student.birthplace as birthplace ,
  1516. class_room.name as room_name,
  1517. course.wording as course, course.coefficient as coef,
  1518. module.name as module,
  1519. user.full_name as teacher,
  1520. quat1.std, quat1.modu,
  1521. quat1.value as value1, quat1.weight as weight1,
  1522. quat2.value as value2, quat2.weight as weight2,
  1523. quat3.value as value3, quat3.weight as weight3,
  1524. greatest(quat1.weight , quat2.weight, quat3.weight ) as weight,
  1525. ( quat1.value*quat1.weight+ quat2.value*quat2.weight + quat3.value*quat3.weight) /(quat1.weight+quat2.weight+quat3.weight) as value
  1526. FROM student
  1527. LEFT JOIN V_STUDENT_MARK_QUATER_1 quat1 ON student.id = quat1.std
  1528. LEFT JOIN V_STUDENT_MARK_QUATER_2 quat2 ON student.id = quat2.std AND quat1.crs = quat2.crs
  1529. LEFT JOIN V_STUDENT_MARK_QUATER_3 quat3 ON student.id = quat3.std AND quat2.crs = quat3.crs
  1530. LEFT JOIN class_room ON class_room.id = quat1.room
  1531. JOIN course ON course.id = quat1.crs
  1532. JOIN module ON course.module_id = quat1.modu
  1533. JOIN user ON user.full_name = quat1.teacher
  1534. ORDER BY quat1.std, quat1.modu
  1535. "
  1536. );
  1537. $statement->execute();
  1538. $dataYear = $connection->executeQuery("SELECT * FROM ANNUAL_DATA ")->fetchAll();
  1539. // For calculating ranks
  1540. $statement = $connection->prepare(
  1541. " CREATE OR REPLACE VIEW V_STUDENT_RANKS AS
  1542. SELECT DISTINCT idStd , CAST( SUM(value*weight*coef) / sum(weight*coef) AS decimal(4,2)) as moyenne, sum(weight*coef) as totalCoef
  1543. FROM ANNUAL_DATA
  1544. GROUP BY idStd
  1545. ORDER BY SUM(value*weight*coef) DESC"
  1546. );
  1547. $statement->execute();
  1548. $annualAvg = $connection->executeQuery("SELECT * FROM V_STUDENT_RANKS ")->fetchAll();
  1549. $rank = 0;
  1550. $rankArray = [];
  1551. foreach ($annualAvg as $avg) {
  1552. $this->annualAvgArray[$avg['idStd']] = $avg['moyenne'];
  1553. $rankArray[$avg['idStd']] = ++$rank;
  1554. $this->sumAvg += $avg['moyenne'];
  1555. }
  1556. // CAS DES ABSCENCES ANNUELLES
  1557. $statement = $connection->prepare(
  1558. " CREATE OR REPLACE VIEW V_STUDENT_ABSCENCE_ANNUAL AS
  1559. SELECT DISTINCT q1.std as std , q1.abscences + q2.abscences + q3.abscences as abscences
  1560. FROM V_STUDENT_ABSCENCE_QUATER_1 q1
  1561. LEFT JOIN V_STUDENT_ABSCENCE_QUATER_2 q2 ON (q1.std = q2.std )
  1562. LEFT JOIN V_STUDENT_ABSCENCE_QUATER_3 q3 ON (q1.std = q3.std )
  1563. ORDER BY std "
  1564. );
  1565. $statement->execute();
  1566. // Traitement des abscences
  1567. $absences = $connection->executeQuery("SELECT * FROM V_STUDENT_ABSCENCE_ANNUAL ")->fetchAll();
  1568. $absencesArray = [];
  1569. foreach ($absences as $abs) {
  1570. $absencesArray[$abs['std']] = $abs['abscences'];
  1571. }
  1572. $html = $this->renderView('classroom/reportcard/annual.html.twig', array(
  1573. "headerFontSize" => $headerFontSize,
  1574. "lineHeight" => $lineHeight,
  1575. "copyright" => $copyright,
  1576. "reverse" => $reverse,
  1577. 'year' => $year,
  1578. 'data' => $dataYear,
  1579. 'room' => $classroom,
  1580. 'students' => $studentEnrolled,
  1581. 'abscences' => $absencesArray,
  1582. 'ranks' => $rankArray,
  1583. 'means' => $this->annualAvgArray,
  1584. 'genMean' => $this->sumAvg / sizeof($this->annualAvgArray),
  1585. 'fileExists'=> $this->imagesExist
  1586. ));
  1587. return new Response(
  1588. $this->snappy->getOutputFromHtml($html, [
  1589. 'page-size' => 'A4',
  1590. ]),
  1591. 200,
  1592. array(
  1593. 'Content-Type' => 'application/pdf',
  1594. 'Content-Disposition' => 'attachment; filename="BUL_ANN_' . $classroom->getName() . '.pdf"',
  1595. )
  1596. );
  1597. }
  1598. function ranking(ClassRoom $room, SchoolYear $year){
  1599. $connection = $this->em->getConnection();
  1600. $statement = $connection->prepare(
  1601. " CREATE OR REPLACE VIEW V_STUDENT_RANKS".$room->getId()."_".$year->getId()." AS
  1602. SELECT DISTINCT std , CAST( SUM(value*weight*coef) / sum(weight*coef) AS decimal(4,2)) as moyenne, sum(weight*coef) as totalCoef
  1603. FROM V_STUDENT_MARK_YEAR".$room->getId()."_".$year->getId()."
  1604. GROUP BY std
  1605. ORDER BY SUM(value*weight*coef) DESC"
  1606. );
  1607. $statement->execute();
  1608. $annualAvg = $connection->executeQuery("SELECT * FROM V_STUDENT_RANKS".$room->getId()."_".$year->getId()." WHERE totalCoef > 0 ;" )->fetchAll();
  1609. $this->sumAvg = 0;
  1610. $rank = 0;
  1611. foreach ($annualAvg as $avg) {
  1612. $this->annualAvgArray[$avg['std']] = $avg['moyenne'];
  1613. $this->annualRanks[$avg['std']] = ++$rank;
  1614. $this->sumAvg += $avg['moyenne'];
  1615. }
  1616. $array = array_filter($this->annualRanks, function ($v, $k) {
  1617. return $k !== '';
  1618. }, ARRAY_FILTER_USE_BOTH);
  1619. return $array;
  1620. }
  1621. /**
  1622. * Finds and displays a ClassRoom entity.
  1623. *
  1624. * @Route("/{id}/reportCards4ApcYearApc", name="admin_class_reportcards_year_2024", requirements={"id"="\d+"})
  1625. * @Method("GET")
  1626. * @Template()
  1627. */
  1628. public function reportCards2024YearAction(ClassRoom $room, Request $request)
  1629. {
  1630. // Parametres de presentation du bulletin
  1631. $copyright = $request->request->get('copyright') == "on";
  1632. $reverse = $request->request->get('reverse') == "on";
  1633. $scale = $this->computeScale($room);
  1634. $connection = $this->em->getConnection();
  1635. $year = $this->schoolYearService->sessionYearById();
  1636. $quaters = $year->getQuaters();
  1637. $sequences = $this->seqRepo->findSequenceThisYear($year);
  1638. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYearInClass($room, $year);
  1639. $mainTeacher = $this->mainTeacherRepo->findOneBy(array("classRoom" => $room, "schoolYear" => $year))-> getTeacher();
  1640. // Performance annuelles
  1641. $this->getViewYearMark2024($room, $year);
  1642. // Existance des photos d'eleves
  1643. $this->fileExists($room, $year);
  1644. // Traitement des abscences
  1645. $absencesArray = [];
  1646. $this->annualAbs = $this->getAbsYearFromView($room, $year);
  1647. foreach ($this->annualAbs as $abs) {
  1648. $absencesArray[$abs['std']] = $abs['total_hours'];
  1649. }
  1650. set_time_limit(600);
  1651. $this->getViewYearMark2024($room, $year);
  1652. // For calculating ranks
  1653. $html = $this->renderView('classroom/reportcard/annual_2024.html.twig', array(
  1654. 'copyright' => $copyright,
  1655. 'reverse' => $reverse,
  1656. 'scale' => $scale,
  1657. 'mainTeacher' => $mainTeacher,
  1658. 'year' => $year,
  1659. 'data' => $this->annualMark,
  1660. 'room' => $room,
  1661. 'students' => $studentEnrolled,
  1662. 'abscences' => $absencesArray,
  1663. 'ranks' => $this->ranking($room, $year),
  1664. 'means' => $this->annualAvgArray,
  1665. 'genMean' => $this->sumAvg / sizeof($studentEnrolled),
  1666. 'fileExists' => $this->fileExists($room, $year),
  1667. ));
  1668. return new Response(
  1669. $this->snappy->getOutputFromHtml($html, [
  1670. 'page-size' => 'A4',
  1671. ]),
  1672. 200,
  1673. array(
  1674. 'Content-Type' => 'application/pdf',
  1675. 'Content-Disposition' => 'attachment; filename="BUL_ANN_' . $room->getName() .'_'.$year->getId().'.pdf"',
  1676. )
  1677. );
  1678. }
  1679. public function getStudentQuaterMark(Array $std,Course $crs){
  1680. foreach ($this->quaterData as $data) {
  1681. if($std["id"] == $data["std"] && $crs->getId() == $data["crs"] ){
  1682. return ["seq1"=>$data["value1"], "weight1"=>$data["weight1"], "seq2"=>$data["value2"],"weight2"=>$data["weight2"],"coef"=>$data["coef"] ];
  1683. }
  1684. }
  1685. return null;
  1686. }
  1687. public function getStudentAnnualMark(Array $std,Course $crs){
  1688. foreach ($this->annualMark as $data) {
  1689. if($std["id"] == $data["std"] && $crs->getId() == $data["crs"] ){
  1690. return ["value"=>$data["value"], "weight"=>$data["weight"],"coef"=>$data["coef"] ];
  1691. }
  1692. }
  1693. return null;
  1694. }
  1695. public function getViewQuaterMark2024(ClassRoom $room,Quater $quater){
  1696. $em = $this->getDoctrine()->getManager();
  1697. $year = $this->schoolYearService->sessionYearById();
  1698. $connection = $this->em->getConnection();
  1699. $sequences = $this->seqRepo->findBy(array("quater" => $quater));
  1700. foreach ($sequences as $seq) {
  1701. $this->getViewSeqMark2024($room,$seq );
  1702. }
  1703. $query =
  1704. " CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER".$room->getId()."_".$quater->getId()." AS
  1705. SELECT DISTINCT seq1.std as std , seq1.crs as crs , seq1.coef as coef, seq1.value as value1, seq1.weight as weight1,seq2.value as value2, seq2.weight as weight2, (COALESCE(seq1.value*seq1.weight,0) + COALESCE(seq2.value*seq2.weight,0))/(seq1.weight+seq2.weight) as value, greatest(seq1.weight , seq2.weight ) as weight , (seq1.mini + seq2.mini)/2 as mini, (seq1.maxi + seq2.maxi)/2 as maxi
  1706. FROM V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[0]->getId()." seq1
  1707. LEFT JOIN V_STUDENT_MARK_SEQ".$room->getId()."_".$sequences[1]->getId()." seq2 ON (seq1.std = seq2.std AND seq1.crs = seq2.crs )
  1708. ORDER BY std ";
  1709. $connection->executeQuery($query);
  1710. $query = "SELECT * FROM V_STUDENT_MARK_QUATER".$room->getId()."_".$quater->getId();
  1711. $this->quaterData = $connection->fetchAllAssociative($query);
  1712. }
  1713. // Vues des performances d'eleves d'une classe en une annee scolaire
  1714. public function getViewYearMark2024(ClassRoom $room, SchoolYear $year){
  1715. $em = $this->getDoctrine()->getManager();
  1716. $connection = $this->em->getConnection();
  1717. $quaters = $year->getQuaters();
  1718. foreach ($quaters as $quater) {
  1719. $this->getViewQuaterMark2024($room,$quater );
  1720. }
  1721. $query = "
  1722. CREATE OR REPLACE VIEW V_STUDENT_MARK_YEAR" . $room->getId() . "_" . $year->getId() . " AS
  1723. SELECT DISTINCT
  1724. `user`.full_name,
  1725. course.wording,
  1726. qt1.std AS std,
  1727. qt1.crs AS crs,
  1728. qt1.coef AS coef,
  1729. qt1.value AS value1,
  1730. qt1.weight AS weight1,
  1731. qt2.value AS value2,
  1732. qt2.weight AS weight2,
  1733. qt3.value AS value3,
  1734. qt3.weight AS weight3,
  1735. (
  1736. COALESCE(qt1.value, 0) * COALESCE(qt1.weight, 0) +
  1737. COALESCE(qt2.value, 0) * COALESCE(qt2.weight, 0) +
  1738. COALESCE(qt3.value, 0) * COALESCE(qt3.weight, 0)
  1739. ) /
  1740. NULLIF(
  1741. COALESCE(qt1.weight, 0) + COALESCE(qt2.weight, 0) + COALESCE(qt3.weight, 0),
  1742. 0
  1743. ) AS `value`,
  1744. GREATEST(
  1745. COALESCE(qt1.weight, 0),
  1746. COALESCE(qt2.weight, 0),
  1747. COALESCE(qt3.weight, 0)
  1748. ) AS weight,
  1749. (
  1750. COALESCE(qt1.mini, 0) + COALESCE(qt2.mini, 0) + COALESCE(qt3.mini, 0)
  1751. ) / 3 AS mini,
  1752. (
  1753. COALESCE(qt1.maxi, 0) + COALESCE(qt2.maxi, 0) + COALESCE(qt3.maxi, 0)
  1754. ) / 3 AS maxi,
  1755. RANK() OVER (
  1756. PARTITION BY course.id
  1757. ORDER BY ((
  1758. COALESCE(qt1.value, 0) * COALESCE(qt1.weight, 0) +
  1759. COALESCE(qt2.value, 0) * COALESCE(qt2.weight, 0) +
  1760. COALESCE(qt3.value, 0) * COALESCE(qt3.weight, 0)
  1761. ) /
  1762. NULLIF(
  1763. COALESCE(qt1.weight, 0) + COALESCE(qt2.weight, 0) + COALESCE(qt3.weight, 0),
  1764. 0
  1765. )) DESC
  1766. ) AS `rank`
  1767. FROM course
  1768. JOIN attribution att
  1769. ON att.course_id = course.id AND att.year_id = " . $year->getId() . "
  1770. JOIN `user`
  1771. ON `user`.id = att.teacher_id
  1772. JOIN V_STUDENT_MARK_QUATER" . $room->getId() . "_" . $quaters[0]->getId() . " qt1
  1773. ON course.id = qt1.crs
  1774. LEFT JOIN V_STUDENT_MARK_QUATER" . $room->getId() . "_" . $quaters[1]->getId() . " qt2
  1775. ON qt1.std = qt2.std AND qt1.crs = qt2.crs
  1776. LEFT JOIN V_STUDENT_MARK_QUATER" . $room->getId() . "_" . $quaters[2]->getId() . " qt3
  1777. ON qt1.std = qt3.std AND qt1.crs = qt3.crs
  1778. ORDER BY qt1.std
  1779. ";
  1780. $connection->executeQuery($query);
  1781. $query = "SELECT * FROM V_STUDENT_MARK_YEAR".$room->getId()."_".$year->getId();
  1782. $this->annualMark = $connection->fetchAllAssociative($query);
  1783. }
  1784. // Vues des abscences d'eleves d'une classe en une annee scolaire
  1785. public function buildAbsYearView(ClassRoom $room, SchoolYear $year){
  1786. $connection = $this->em->getConnection();
  1787. $quaters = $year->getQuaters();
  1788. // Construction de la vue des abscences annuelles de la classe pour l'annee
  1789. foreach($quaters as $quater){
  1790. $this->buildAbsQuaterView($room, $quater);
  1791. }
  1792. $query =
  1793. "CREATE OR REPLACE VIEW V_STUDENT_ABSCENCE_YEAR" . $room->getId() . "_" . $year->getId() . " AS
  1794. SELECT DISTINCT qt1.std AS std,
  1795. COALESCE(qt1.total_hours, 0) + COALESCE(qt2.total_hours, 0) + COALESCE(qt3.total_hours, 0) AS total_hours
  1796. FROM V_STUDENT_ABSCENCE_QUATER" . $room->getId() . "_" . $quaters[0]->getId() . " qt1
  1797. LEFT JOIN V_STUDENT_ABSCENCE_QUATER" . $room->getId() . "_" . $quaters[1]->getId() . " qt2 ON qt1.std = qt2.std
  1798. LEFT JOIN V_STUDENT_ABSCENCE_QUATER" . $room->getId() . "_" . $quaters[2]->getId() . " qt3 ON qt1.std = qt3.std
  1799. UNION
  1800. SELECT DISTINCT qt2.std AS std,
  1801. COALESCE(qt1.total_hours, 0) + COALESCE(qt2.total_hours, 0) + COALESCE(qt3.total_hours, 0) AS total_hours
  1802. FROM V_STUDENT_ABSCENCE_QUATER" . $room->getId() . "_" . $quaters[1]->getId() . " qt2
  1803. LEFT JOIN V_STUDENT_ABSCENCE_QUATER" . $room->getId() . "_" . $quaters[0]->getId() . " qt1 ON qt1.std = qt2.std
  1804. LEFT JOIN V_STUDENT_ABSCENCE_QUATER" . $room->getId() . "_" . $quaters[2]->getId() . " qt3 ON qt2.std = qt3.std
  1805. UNION
  1806. SELECT DISTINCT qt3.std AS std,
  1807. COALESCE(qt1.total_hours, 0) + COALESCE(qt2.total_hours, 0) + COALESCE(qt3.total_hours, 0) AS total_hours
  1808. FROM V_STUDENT_ABSCENCE_QUATER" . $room->getId() . "_" . $quaters[2]->getId() . " qt3
  1809. LEFT JOIN V_STUDENT_ABSCENCE_QUATER" . $room->getId() . "_" . $quaters[0]->getId() . " qt1 ON qt1.std = qt3.std
  1810. LEFT JOIN V_STUDENT_ABSCENCE_QUATER" . $room->getId() . "_" . $quaters[1]->getId() . " qt2 ON qt2.std = qt3.std
  1811. ORDER BY std;";
  1812. $connection->executeQuery($query);
  1813. }
  1814. public function getAbsYearFromView(ClassRoom $room, SchoolYear $year){
  1815. $connection = $this->em->getConnection();
  1816. $this->buildAbsYearView($room, $year);
  1817. $query = "SELECT * FROM V_STUDENT_ABSCENCE_YEAR".$room->getId()."_".$year->getId();
  1818. return $connection->fetchAllAssociative($query);
  1819. }
  1820. /**
  1821. * Finds and displays a ClassRoom entity.
  1822. *
  1823. * @Route("/{id}/recapitulatiftrim", name="admin_classrooms_recapitulatif_trim", requirements={"id"="\d+"})
  1824. * @Method("GET")
  1825. * @Template()
  1826. */
  1827. public function recapTrimAction(ClassRoom $room, Request $request)
  1828. {
  1829. $checkedValues = $request->request->get('selected_courses');
  1830. set_time_limit(600);
  1831. $em = $this->getDoctrine()->getManager();
  1832. $year = $this->schoolYearService->sessionYearById();
  1833. $connection = $this->em->getConnection();
  1834. $quater = $this->qtRepo->findOneBy(array("activated" => true));
  1835. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYear($room, $year->getId());
  1836. $this->getViewQuaterMark2024($room, $quater);
  1837. $result = [];
  1838. foreach ($studentEnrolled as $std) { // Parcourir les étudiants inscrits
  1839. $result[$std["id"]] = []; // Initialiser un sous-tableau pour chaque étudiant
  1840. foreach ($room->getModules() as $module) { // Parcourir les modules de la salle
  1841. foreach ($module->getCourses() as $crs) {
  1842. if(in_array($crs->getId(), $checkedValues))
  1843. {
  1844. // Collecter les note de chaque combinaison étudiant/module
  1845. $result[$std["id"]][$crs->getId()] = $this->getStudentQuaterMark($std, $crs); // Remplacer 'null' par la donnée que vous voulez associer
  1846. }
  1847. }
  1848. }
  1849. }
  1850. $mainTeacher = $this->mainTeacherRepo->findOneBy(array("classRoom" => $room, "schoolYear" => $year))-> getTeacher();
  1851. $options = [
  1852. 'orientation' => 'Landscape', // Spécifie l'orientation paysage
  1853. 'page-size' => 'A4', // Taille de page A4
  1854. 'margin-top' => '10mm', // Marges pour personnaliser l'apparence
  1855. 'margin-bottom' => '10mm',
  1856. 'margin-left' => '10mm',
  1857. 'margin-right' => '10mm'
  1858. ];
  1859. $html = $this->renderView('classroom/recapitulatiftrimWithMoy.html.twig', array(
  1860. 'year' => $year,
  1861. 'datas' => $result,
  1862. 'room' => $room,
  1863. 'quater' => $quater,
  1864. 'checkedValues'=>$checkedValues,
  1865. 'students' => $studentEnrolled,
  1866. 'mainTeacher' => $mainTeacher
  1867. ));
  1868. return new Response(
  1869. $this->pdf->getOutputFromHtml($html, $options),
  1870. 200,
  1871. array(
  1872. 'Content-Type' => 'application/pdf',
  1873. 'Content-Disposition' => 'inline; filename="recap_trim' . $quater->getId().'_'.$room->getName() . '.pdf"'
  1874. )
  1875. );
  1876. }
  1877. /**
  1878. * Finds and displays a ClassRoom entity.
  1879. *
  1880. * @Route("/{id}/recapitulatifannexcel", name="admin_classrooms_recapitulatif_ann_excel", requirements={"id"="\d+"})
  1881. * @Method("GET")
  1882. * @Template()
  1883. */
  1884. public function recapAnnExcelAction(ClassRoom $room, Request $request)
  1885. {
  1886. $checkedValues = $request->request->get('selected_courses');
  1887. $em = $this->getDoctrine()->getManager();
  1888. $year = $this->schoolYearService->sessionYearById();
  1889. $this->getViewYearMark2024($room, $year);
  1890. $studentEnrolled = $this->stdRepo->findEnrolledStudentsThisYear($room, $year->getId());
  1891. $result = [];
  1892. $courses = [];
  1893. // Préparation des données
  1894. foreach ($studentEnrolled as $std) {
  1895. $result[$std["id"]]['student'] = $std["lastname"]." ". $std["firstname"];
  1896. $result[$std["id"]]['gender'] = $std["gender"];
  1897. $result[$std["id"]]['birthday'] = $std["birthday"];
  1898. foreach ($room->getModules() as $module) {
  1899. foreach ($module->getCourses() as $crs) {
  1900. if (in_array($crs->getId(), $checkedValues)) {
  1901. $courses[$crs->getId()] = $crs->getWording();
  1902. $result[$std["id"]][$crs->getId()] = $this->getStudentAnnualMark($std, $crs);
  1903. }
  1904. }
  1905. }
  1906. }
  1907. // Générer le fichier Excel
  1908. $spreadsheet = new Spreadsheet();
  1909. $sheet = $spreadsheet->getActiveSheet();
  1910. // En-têtes de colonnes (lignes 1)
  1911. $sheet->setCellValue('A1', 'Élève');
  1912. $sheet->setCellValue('B1', 'Sexe');
  1913. $sheet->setCellValue('C1', 'Age');
  1914. $colIndex = 4;
  1915. foreach ($courses as $courseId => $courseName) {
  1916. $sheet->setCellValueByColumnAndRow($colIndex, 1, $courseName);
  1917. $colIndex++;
  1918. }
  1919. $sheet->setCellValueByColumnAndRow($colIndex, 1, "MOYENNE");
  1920. // Remplir les données
  1921. $rowIndex = 2;
  1922. foreach ($result as $studentData) {
  1923. $sheet->setCellValueByColumnAndRow(1, $rowIndex, $studentData['student']);
  1924. // Récupère la valeur brute (0 ou 1)
  1925. $rawGender = $studentData['gender'];
  1926. // Mappe en libellé
  1927. $genderLabel = ((int) $rawGender === 1)
  1928. ? 'Femme'
  1929. : 'Homme';
  1930. // Écris “Homme” ou “Femme” dans la cellule
  1931. $sheet->setCellValueByColumnAndRow(2, $rowIndex, $genderLabel);
  1932. // On crée un objet DateTime pour la date de naissance
  1933. $birthDate = $studentData['birthday'];
  1934. $sheet->setCellValueByColumnAndRow(3, $rowIndex, $birthDate);
  1935. $colIndex = 4;
  1936. $totalMackCoef =0;
  1937. $totalCoef =0;
  1938. foreach ($courses as $courseId => $courseName) {
  1939. // Si la donnée est absente, on utilise des zéros par défaut
  1940. $data = $studentData[$courseId] ?? ['value' => 0, 'weight' => 0, 'coef' => 0];
  1941. $mark = $data['value'] * $data['weight'];
  1942. $coef = $data['coef'];
  1943. $totalMackCoef += $mark * $coef;
  1944. $totalCoef += $coef;
  1945. $sheet->setCellValueByColumnAndRow($colIndex, $rowIndex, $mark);
  1946. $colIndex++;
  1947. }
  1948. $moy = $totalCoef>0 ? $totalMackCoef/$totalCoef : "#";
  1949. $sheet->setCellValueByColumnAndRow($colIndex, $rowIndex, $moy);
  1950. $rowIndex++;
  1951. }
  1952. // Retourner le fichier Excel en téléchargement
  1953. $writer = new Xlsx($spreadsheet);
  1954. $filename = 'recapitulatif_' . $room->getName() . '_' . date('Ymd_His') . '.xlsx';
  1955. $response = new StreamedResponse(function () use ($writer) {
  1956. $writer->save('php://output');
  1957. });
  1958. $response->headers->set('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
  1959. $response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');
  1960. $response->headers->set('Cache-Control', 'max-age=0');
  1961. return $response;
  1962. }
  1963. public function officialExam()
  1964. {
  1965. // Retrieve student categories from the corresponding repository
  1966. $categoriesStudent = $this->getDoctrine()->getRepository(CategStudent::class)->findAll();
  1967. // Initialize arrays for student categories, mentions, and counters
  1968. $studentCategories = [];
  1969. $mentionCategories = [];
  1970. $studentCountCategories = [];
  1971. $mentionCountCategories = [];
  1972. // Fill the arrays with data from student categories
  1973. foreach ($categoriesStudent as $category) {
  1974. $studentCategories[] = $category->getName();
  1975. $mentionCategories[] = $category->getMention();
  1976. $studentCountCategories[] = $category->getCountStudent();
  1977. $mentionCountCategories[] = $category->getCountMention();
  1978. }
  1979. // Render the Twig template and pass the data in JSON format
  1980. return $this->render('admin/class_room/show.html.twig', [
  1981. 'studentCategories' => json_encode($studentCategories),
  1982. 'mentionCategories' => json_encode($mentionCategories),
  1983. 'studentCountCategories' => json_encode($studentCountCategories),
  1984. 'mentionCountCategories' => json_encode($mentionCountCategories),
  1985. ]);
  1986. }
  1987. /**
  1988. * @Route("/classroom/insolvents", name="admin_classroom_insolvents")
  1989. */
  1990. public function listInsolventStudents(): Response
  1991. {
  1992. $year = $this->schoolYearService->sessionYearById();
  1993. $paymentPlan = $year->getPaymentPlan();
  1994. // List of student subscriptions for the class
  1995. $subscriptions = $this->subRepo->findBy(array("schoolYear" => $year), array("classRoom"=>"ASC"));
  1996. $insolventSub = [];
  1997. foreach($subscriptions as $sub){
  1998. if($year->paymentThresholdAmount($sub->getClassRoom()) > $sub->getStudent()->getPaymentsSum($year) ){
  1999. $insolventSub[] = $sub;
  2000. }
  2001. }
  2002. $html = $this->render('school_year/templating/insolvent_students_list.html.twig', [
  2003. 'students' => $insolventSub,
  2004. 'year' => $year,
  2005. ]);
  2006. return new Response(
  2007. $this->pdf->getOutputFromHtml($html),
  2008. 200,
  2009. array(
  2010. 'Content-Type' => 'application/pdf',
  2011. 'Content-Disposition' => 'inline; filename="insolvent_student_' . $year->getCode() . '.pdf"'
  2012. )
  2013. );
  2014. }
  2015. /**
  2016. * @Route("/classroom/{id}", name="class_room_stats")
  2017. */
  2018. public function showClassRoomStats(ClassRoomRepository $classRoomRepository, ClassRoom $room): Response
  2019. {
  2020. $classRoom = $classRoomRepository->find($id);
  2021. $successfulCount = $classRoomRepository->countSuccessfulStudentsForClass($classRoom);
  2022. $unsuccessfulCount = $classRoomRepository->countUnsuccessfulStudentsForClass($classRoom);
  2023. $mentionStatistics = $classRoomRepository->getMentionStatisticsForClass($classRoom);
  2024. return $this->render('class_room/stats.html.twig', [
  2025. 'classRoom' => $classRoom,
  2026. 'successfulCount' => $successfulCount,
  2027. 'unsuccessfulCount' => $unsuccessfulCount,
  2028. 'mentionStatistics' => $mentionStatistics,
  2029. ]);
  2030. }
  2031. /**
  2032. * @Route("/classroom/{id}/insolvent", name="admin_classroom_insolvent")
  2033. */
  2034. public function listInsolventStudentsByRoom(ClassRoom $room): Response
  2035. {
  2036. $year = $this->schoolYearService->sessionYearById();
  2037. $paymentPlan = $year->getPaymentPlan();
  2038. // List of student subscriptions for the class
  2039. $subscriptions = $this->subRepo->findBy(array("schoolYear" => $year, "classRoom" => $room));
  2040. $students = [];
  2041. $dueAmounts = [];
  2042. foreach($subscriptions as $sub){
  2043. if($year->paymentThresholdAmount($room) > $sub->getStudent()->getPaymentsSum($year) ){
  2044. $students[] = $sub->getStudent() ;
  2045. $dueAmounts[$sub->getStudent()->getId()] = $year->paymentThresholdAmount($room)-$sub->getStudent()->getPaymentsSum($year);
  2046. }
  2047. }
  2048. $html = $this->render('classroom/templating/insolvent_student_list.html.twig', [
  2049. 'room' => $room,
  2050. 'students' => $students,
  2051. 'year' => $year,
  2052. 'amounts' => $dueAmounts
  2053. ]);
  2054. return new Response(
  2055. $this->pdf->getOutputFromHtml($html),
  2056. 200,
  2057. array(
  2058. 'Content-Type' => 'application/pdf',
  2059. 'Content-Disposition' => 'inline; filename="insolvent_student_' . $room->getName() . '.pdf"'
  2060. )
  2061. );
  2062. }
  2063. /**
  2064. * @Route("/insolventspercentage", name="admin_classroom_insolvents_percentage")
  2065. */
  2066. public function insolventStudentsRate(): Response
  2067. {
  2068. $year = $this->schoolYearService->sessionYearById();
  2069. $paymentPlan = $year->getPaymentPlan();
  2070. $rooms = $this->repo->findAll();
  2071. $rates = [];
  2072. foreach($rooms as $room){
  2073. $subscriptions = $this->subRepo->findBy(array("schoolYear" => $year, "classRoom" => $room));
  2074. $installments = $this->instRepo->findBy(array("classRoom" => $room, "paymentPlan" => $paymentPlan));
  2075. $sum = 0;
  2076. foreach($installments as $installment){
  2077. $sum += $installment->getAmount();
  2078. }
  2079. $ratesByRoom = [];
  2080. foreach($subscriptions as $sub){
  2081. $ratesByRoom[] = 100*$sub->getStudent()->getPaymentsSum($year) / $sum;
  2082. }
  2083. // Calculer la somme des valeurs entières
  2084. $sum = array_sum($ratesByRoom);
  2085. // Calculer la moyenne
  2086. $avg = count($ratesByRoom) > 0 ? $sum / count($ratesByRoom) : 0;
  2087. $rates[$room->getName()] = $avg ;
  2088. }
  2089. $html = $this->render('school_year/templating/recovery_rates_by_room.html.twig', [
  2090. 'rates' => $rates,
  2091. 'year' => $year,
  2092. ]);
  2093. return new Response(
  2094. $this->pdf->getOutputFromHtml($html),
  2095. 200,
  2096. array(
  2097. 'Content-Type' => 'application/pdf',
  2098. 'Content-Disposition' => 'inline; filename="insolvent_student_' . $year->getCode() . '.pdf"'
  2099. )
  2100. );
  2101. }
  2102. }