src/Controller/ClassRoomController.php line 771

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