src/Controller/StudentController.php line 196

Open in your IDE?
  1. <?php
  2. namespace App\Controller;
  3. use App\Entity\Student;
  4. use App\Entity\Subscription;
  5. use App\Entity\ClassRoom;
  6. use App\Form\StudentType;
  7. use App\Repository\StudentRepository;
  8. use App\Repository\EvaluationRepository;
  9. use App\Repository\SequenceRepository;
  10. use App\Repository\MarkRepository;
  11. use Knp\Snappy\Pdf;
  12. use App\Repository\SchoolYearRepository;
  13. use App\Repository\SubscriptionRepository;
  14. use App\Repository\PaymentRepository;
  15. use App\Repository\QuaterRepository;
  16. use App\Repository\InstallmentRepository;
  17. use App\Repository\PaymentPlanRepository;
  18. use App\Repository\MainTeacherRepository;
  19. use Doctrine\ORM\EntityManagerInterface;
  20. use Symfony\Component\HttpFoundation\Request;
  21. use Symfony\Component\HttpFoundation\Response;
  22. use Symfony\Component\Routing\Annotation\Route;
  23. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method;
  24. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  25. use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
  26. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  27. use App\Service\SchoolYearService;
  28. use App\Entity\User;
  29. /**
  30. * Studentme controller.
  31. *
  32. * @Route("/prof/students")
  33. */
  34. class StudentController extends AbstractController
  35. {
  36. private EntityManagerInterface $em;
  37. private $repo;
  38. private $scRepo;
  39. private $seqRepo;
  40. private SubscriptionRepository $subRepo;
  41. private $markRepo;
  42. private $evalRepo;
  43. private $qtRepo;
  44. private $snappy;
  45. private SchoolYearService $schoolYearService;
  46. private PaymentPlanRepository $ppRepo;
  47. private InstallmentRepository $instRepo;
  48. private PaymentRepository $pRepo;
  49. private MainTeacherRepository $mainTeacherRepo;
  50. public function __construct(
  51. PaymentRepository $pRepo,
  52. InstallmentRepository $instRepo,
  53. PaymentPlanRepository $ppRepo,
  54. SchoolYearService $schoolYearService,
  55. EntityManagerInterface $em,
  56. SubscriptionRepository $subRepo,
  57. MarkRepository $markRepo,
  58. EvaluationRepository $evalRepo,
  59. StudentRepository $repo,
  60. SequenceRepository $seqRepo,
  61. SchoolYearRepository $scRepo,
  62. QuaterRepository $qtRepo,
  63. MainTeacherRepository $mainTeacherRepo,
  64. Pdf $snappy
  65. ) {
  66. $this->em = $em;
  67. $this->repo = $repo;
  68. $this->scRepo = $scRepo;
  69. $this->markRepo = $markRepo;
  70. $this->seqRepo = $seqRepo;
  71. $this->evalRepo = $evalRepo;
  72. $this->subRepo = $subRepo;
  73. $this->qtRepo = $qtRepo;
  74. $this->snappy = $snappy;
  75. $this->ppRepo = $ppRepo;
  76. $this->pRepo = $pRepo;
  77. $this->instRepo = $instRepo;
  78. $this->mainTeacherRepo = $mainTeacherRepo;
  79. $this->schoolYearService = $schoolYearService;
  80. }
  81. // =========================================================
  82. // CORRECTION 2 : méthode privée mutualisée pour l'auth
  83. // Remplace les 6 lignes répétées dans chaque action
  84. // =========================================================
  85. private function checkAuth(): ?Response
  86. {
  87. if (!$this->getUser()) {
  88. $this->addFlash('warning', 'You need login first!');
  89. return $this->redirectToRoute('app_login');
  90. }
  91. /** @var User $user */
  92. $user = $this->getUser();
  93. if (!$user->isVerified()) {
  94. $this->addFlash('warning', 'You need to have a verified account!');
  95. return $this->redirectToRoute('app_login');
  96. }
  97. return null;
  98. }
  99. /**
  100. * @Route("/create", name="admin_students_new", methods={"GET","POST"})
  101. */
  102. public function create(Request $request): Response
  103. {
  104. if ($redirect = $this->checkAuth()) return $redirect;
  105. $student = new Student();
  106. $form = $this->createForm(StudentType::class, $student);
  107. $numero = $this->repo->getNumeroDispo();
  108. $student->setMatricule($numero);
  109. $form->handleRequest($request);
  110. if ($form->isSubmitted() && $form->isValid()) {
  111. if ($student->getEntryClass() != null) {
  112. $sub = new Subscription();
  113. $sub->setStudent($student);
  114. $sub->setClassRoom($student->getEntryClass());
  115. $sub->setSchoolYear($this->schoolYearService->sessionYearById());
  116. $this->em->persist($sub);
  117. }
  118. $this->em->persist($student);
  119. $this->em->flush();
  120. $this->addFlash('success', 'Student succesfully created');
  121. return $this->redirectToRoute('admin_students', [
  122. 'type' => "new_students_not_yet_registered_checkbox",
  123. ]);
  124. }
  125. return $this->render('student/new.html.twig', ['form' => $form->createView()]);
  126. }
  127. /**
  128. * Lists all Studentme entities.
  129. *
  130. * @Route("/{type}", name="admin_students")
  131. * @Method("GET")
  132. * @Template()
  133. */
  134. public function indexAction($type)
  135. {
  136. if ($redirect = $this->checkAuth()) return $redirect;
  137. $year = $this->schoolYearService->sessionYearById();
  138. switch ($type) {
  139. case "new_students_not_yet_registered_checkbox":
  140. $students = $this->repo->findNewStudents($year);
  141. break;
  142. case "new_registered_students_checkbox":
  143. $students = $this->repo->findNewRegisteredStudents($year);
  144. break;
  145. case "registered_former_students_checkbox":
  146. $students = $this->repo->findFormerRegisteredStudents($year);
  147. break;
  148. case "complete_registered_students_checkbox":
  149. // CORRECTION 1 : $year passé en argument (Option B appliquée dans le repo)
  150. $students = $this->repo->findEnrolledStudentsThisYear2($year);
  151. break;
  152. default:
  153. $students = $this->repo->findEnrolledStudentsThisYear2();
  154. break;
  155. }
  156. return $this->render('student/list.html.twig', compact("students"));
  157. }
  158. /**
  159. * @Route("/{id}/unregister/{room_id}", name="admin_students_unregister", requirements={"id"="\d+", "room_id"="\d+"})
  160. * @ParamConverter("std", options={"mapping": {"id": "id"}})
  161. * @ParamConverter("room", options={"mapping": {"room_id": "id"}})
  162. */
  163. public function unregisterAction(Student $std, ClassRoom $room)
  164. {
  165. if ($redirect = $this->checkAuth()) return $redirect;
  166. $year = $this->schoolYearService->sessionYearById();
  167. $sub = $this->subRepo->findOneBy(["student" => $std, "classRoom" => $room, "schoolYear" => $year]);
  168. $this->em->remove($sub);
  169. $this->em->flush();
  170. return $this->redirectToRoute('admin_classrooms_show', ["id" => $room->getId()]);
  171. }
  172. /**
  173. * Finds and displays a Studentme entity.
  174. *
  175. * @Route("/{id}/show", name="admin_students_show", requirements={"id"="\d+"})
  176. * @Method("GET")
  177. * @Template()
  178. */
  179. public function showAction(Student $student)
  180. {
  181. if ($redirect = $this->checkAuth()) return $redirect;
  182. $year = $this->schoolYearService->sessionYearById();
  183. $seq = $this->seqRepo->findOneBy(["activated" => true]);
  184. $sub = $this->subRepo->findOneBy(["student" => $student, "schoolYear" => $year]);
  185. $results = [
  186. 'student' => $student,
  187. 'cours' => null,
  188. 'session1' => null,
  189. 'session2' => null,
  190. 'session3' => null,
  191. 'session4' => null,
  192. 'session5' => null,
  193. 'session6' => null,
  194. ];
  195. $payments = $this->pRepo->findBy(["subscription" => $sub], ['updatedAt' => 'ASC']);
  196. $paymentPlan = $this->ppRepo->findOneBy(["schoolYear" => $year]);
  197. if ($sub != null) {
  198. $installments = $this->instRepo->findBy(["paymentPlan" => $paymentPlan, "classRoom" => $sub->getClassRoom()]);
  199. } else {
  200. $installments = $this->instRepo->findBy(["paymentPlan" => $paymentPlan]);
  201. }
  202. $seqs = $this->seqRepo->findSequenceThisYear($year);
  203. $evalSeqs = [];
  204. if ($sub != null) {
  205. foreach ($seqs as $seq) {
  206. $evalSeqs[$seq->getId()] = $this->evalRepo->findBy([
  207. "classRoom" => $sub->getClassRoom(),
  208. "sequence" => $seq,
  209. ]);
  210. }
  211. $courses = [];
  212. $averageSeqs = [];
  213. foreach ($evalSeqs[$seq->getId()] as $eval) {
  214. $courses[] = $eval->getCourse()->getWording();
  215. }
  216. foreach ($seqs as $seq) {
  217. $average = [];
  218. foreach ($evalSeqs[$seq->getId()] as $eval) {
  219. $mark = $this->markRepo->findOneBy(["student" => $student, "evaluation" => $eval]);
  220. if ($mark) {
  221. $average[] = $mark->getValue();
  222. }
  223. }
  224. $averageSeqs[$seq->getId()] = $average;
  225. }
  226. $filename = "assets/images/student/" . $student->getMatricule() . ".jpg";
  227. $file_exists = file_exists($filename);
  228. $results['payments'] = $payments;
  229. $results['payment_plan'] = $paymentPlan;
  230. $results['installments'] = $installments;
  231. $results['sub'] = $sub;
  232. $results['file_exists'] = $file_exists;
  233. $results['cours'] = json_encode($courses);
  234. foreach ($seqs as $seq) {
  235. $results[strtolower($seq->getWording())] = json_encode($averageSeqs[$seq->getId()]);
  236. }
  237. }
  238. return $this->render('student/show.html.twig', $results);
  239. }
  240. /**
  241. * Displays a form to edit an existing Studentme entity.
  242. *
  243. * @Route("/{id}/edit", name="admin_students_edit", requirements={"id"="\d+"}, methods={"GET","PUT"})
  244. * @Template()
  245. */
  246. public function edit(Request $request, Student $student): Response
  247. {
  248. if ($redirect = $this->checkAuth()) return $redirect;
  249. $form = $this->createForm(StudentType::class, $student, ['method' => 'PUT']);
  250. $form->handleRequest($request);
  251. if ($form->isSubmitted() && $form->isValid()) {
  252. $this->em->flush();
  253. $this->addFlash('success', 'Student succesfully updated');
  254. $year = $this->schoolYearService->sessionYearById();
  255. $sub = $this->subRepo->findOneBy(["student" => $student, "schoolYear" => $year]);
  256. return $this->redirectToRoute('admin_classrooms_show', ["id" => $sub->getClassRoom()->getId()]);
  257. }
  258. return $this->render('student/edit.html.twig', [
  259. 'student' => $student,
  260. 'form' => $form->createView(),
  261. ]);
  262. }
  263. /**
  264. * Deletes a Studentme entity.
  265. *
  266. * @Route("/{id}/delete", name="admin_students_delete", requirements={"id"="\d+"}, methods={"DELETE"})
  267. */
  268. public function delete(Student $student, Request $request): Response
  269. {
  270. if ($redirect = $this->checkAuth()) return $redirect;
  271. if ($this->isCsrfTokenValid('students_deletion' . $student->getId(), $request->request->get('csrf_token'))) {
  272. $this->em->remove($student);
  273. $this->em->flush();
  274. $this->addFlash('info', 'Student succesfully deleted');
  275. }
  276. return $this->redirectToRoute('admin_students', [
  277. 'type' => "new_students_not_yet_registered_checkbox",
  278. ]);
  279. }
  280. /**
  281. * Build student's school certificate
  282. *
  283. * @Route("/{id}/certificate", name="admin_student_certificate", requirements={"id"="\d+"})
  284. */
  285. public function schoolCertificate(Pdf $pdf, Student $std): Response
  286. {
  287. if ($redirect = $this->checkAuth()) return $redirect;
  288. $year = $this->schoolYearService->sessionYearById();
  289. $sub = $this->subRepo->findOneBy(["student" => $std, "schoolYear" => $year]);
  290. $html = $this->renderView('student/school_certificate.html.twig', [
  291. 'year' => $year,
  292. 'std' => $std,
  293. 'sub' => $sub,
  294. ]);
  295. return new Response($pdf->getOutputFromHtml($html), 200, [
  296. 'Content-Type' => 'application/pdf',
  297. 'Content-Disposition' => 'inline; filename="certif_' . $std->getMatricule() . '.pdf"',
  298. ]);
  299. }
  300. /**
  301. * @Route("/{id}/receipt", name="admin_student_receipt", requirements={"id"="\d+"})
  302. */
  303. public function tuitionReceiptAction(Pdf $pdf, Student $std): Response
  304. {
  305. if ($redirect = $this->checkAuth()) return $redirect;
  306. $year = $this->schoolYearService->sessionYearById();
  307. $sub = $this->subRepo->findOneBy(["student" => $std, "schoolYear" => $year]);
  308. $payments = $this->pRepo->findBy(["subscription" => $sub], ['updatedAt' => 'ASC']);
  309. $paymentPlan = $this->ppRepo->findOneBy(["schoolYear" => $year]);
  310. $installments = $this->instRepo->findBy(["paymentPlan" => $paymentPlan, "classRoom" => $sub->getClassRoom()]);
  311. $html = $this->renderView('student/templating/tuition_receipt.html.twig', [
  312. 'year' => $year,
  313. 'std' => $std,
  314. 'sub' => $sub,
  315. 'payments' => $payments,
  316. 'payment_plan' => $paymentPlan,
  317. 'installments' => $installments,
  318. ]);
  319. return new Response($pdf->getOutputFromHtml($html), 200, [
  320. 'Content-Type' => 'application/pdf',
  321. 'Content-Disposition' => 'inline; filename="recu_' . $std->getMatricule() . '.pdf"',
  322. ]);
  323. }
  324. /**
  325. * @Route("/{id}/badge", name="admin_student_badge", requirements={"id"="\d+"})
  326. */
  327. public function schoolBadge(Pdf $pdf, Student $std): Response
  328. {
  329. if ($redirect = $this->checkAuth()) return $redirect;
  330. $year = $this->schoolYearService->sessionYearById();
  331. $sub = $this->subRepo->findOneBy(["student" => $std, "schoolYear" => $year]);
  332. $filename = "assets/images/student/" . $std->getMatricule() . ".jpg";
  333. $fileExist = file_exists($filename);
  334. $html = $this->renderView('student/badge.html.twig', [
  335. 'sub' => $sub,
  336. 'fileExist' => $fileExist,
  337. ]);
  338. return new Response($pdf->getOutputFromHtml($html), 200, [
  339. 'Content-Type' => 'application/pdf',
  340. 'Content-Disposition' => 'inline; filename="badge_' . $std->getMatricule() . '.pdf"',
  341. ]);
  342. }
  343. /**
  344. * @Route("/{id}/reportCardTrim2024", name="admin_students_reportcards_quat_2024", requirements={"id"="\d+"})
  345. * @Method("GET")
  346. * @Template()
  347. */
  348. public function reporCardTrimAction2024(Pdf $pdf, Student $std, Request $request)
  349. {
  350. if ($redirect = $this->checkAuth()) return $redirect;
  351. $headerFontSize = $request->request->get('header_font_size');
  352. $lineHeight = $request->request->get('line_height');
  353. $copyright = $request->request->get('copyright') == "on";
  354. $connection = $this->em->getConnection();
  355. $year = $this->schoolYearService->sessionYearById();
  356. $sub = $this->subRepo->findOneBy(["student" => $std, "schoolYear" => $year]);
  357. $quater = $this->qtRepo->findOneBy(["activated" => true]);
  358. $students = $this->repo->findEnrolledStudentsThisYearInClass($sub->getClassRoom(), $year);
  359. $mainTeacher = $this->mainTeacherRepo->findOneBy([
  360. "classRoom" => $sub->getClassRoom(),
  361. "schoolYear" => $year,
  362. ])->getTeacher();
  363. $filename = "assets/images/student/" . $std->getMatricule() . ".jpg";
  364. $fileExist = file_exists($filename);
  365. $query = "SELECT DISTINCT sequence.id as sequence, course.id as course_id, course.wording, course.coefficient,
  366. mark.value, mark.weight, mark.rank2, evaluation.mini as mini, evaluation.maxi as maxi,
  367. evaluation.competence, attribution.teacher_id, school_year.id, user.full_name
  368. FROM sequence
  369. JOIN evaluation ON evaluation.sequence_id = sequence.id
  370. JOIN course ON evaluation.course_id = course.id
  371. JOIN attribution ON attribution.course_id = course.id
  372. JOIN user ON user.id = attribution.teacher_id
  373. JOIN mark ON evaluation.id = mark.evaluation_id
  374. JOIN quater ON sequence.quater_id = quater.id
  375. JOIN school_year ON quater.school_year_id = school_year.id AND school_year.id = attribution.year_id
  376. WHERE quater.id = :quater_id AND mark.student_id = :student_id
  377. ORDER BY course.id, sequence.id";
  378. $params = [
  379. 'quater_id' => $quater->getId(),
  380. 'student_id' => $std->getId(),
  381. ];
  382. $result = $connection->executeQuery($query, $params);
  383. $data = $result->fetchAllAssociative();
  384. $html = $this->renderView('student/reportcard/quaterly_2024.html.twig', [
  385. 'year' => $year,
  386. 'quater' => $quater,
  387. 'mainTeacher' => $mainTeacher,
  388. 'data' => $data,
  389. 'std' => $std,
  390. 'students' => $students,
  391. 'room' => $sub->getClassRoom(),
  392. 'lineHeight' => 0.75 * $lineHeight,
  393. 'headerFontSize' => 0.75 * $headerFontSize,
  394. 'copyright' => $copyright,
  395. 'fileExist' => $fileExist,
  396. ]);
  397. return new Response($pdf->getOutputFromHtml($html), 200, [
  398. 'Content-Type' => 'application/pdf',
  399. 'Content-Disposition' => 'inline; filename="bull_' . $quater->getId() . '_' . $std->getMatricule() . '.pdf"',
  400. ]);
  401. }
  402. /**
  403. * @Route("/{id}/reportCardTrim", name="admin_students_reportcards_quat", requirements={"id"="\d+"})
  404. * @Method("GET")
  405. * @Template()
  406. */
  407. public function reporCardTrimAction(Pdf $pdf, Student $std)
  408. {
  409. if ($redirect = $this->checkAuth()) return $redirect;
  410. $connection = $this->em->getConnection();
  411. $year = $this->schoolYearService->sessionYearById();
  412. $sub = $this->subRepo->findOneBy(["student" => $std, "schoolYear" => $year]);
  413. $quater = $this->qtRepo->findOneBy(["activated" => true]);
  414. $sequences = $this->seqRepo->findBy(["quater" => $quater]);
  415. $filename = "assets/images/student/" . $std->getMatricule() . ".jpg";
  416. $fileExist = file_exists($filename);
  417. // CORRECTION 3 : execute() déprécié → executeStatement()
  418. $i = 1;
  419. foreach ($sequences as $seq) {
  420. $sql = "CREATE OR REPLACE VIEW V_STUDENT_MARK_SEQ" . $i . " AS
  421. SELECT DISTINCT eval.id as eval, crs.id as crs, room.id as room,
  422. teach.full_name as teacher, modu.id as module, m.value as value, m.weight as weight
  423. FROM mark m
  424. JOIN student std ON m.student_id = std.id
  425. JOIN evaluation eval ON m.evaluation_id = eval.id
  426. JOIN class_room room ON eval.class_room_id = room.id
  427. JOIN course crs ON eval.course_id = crs.id
  428. JOIN attribution att ON att.course_id = crs.id
  429. JOIN user teach ON att.teacher_id = teach.id
  430. JOIN module modu ON modu.id = crs.module_id
  431. JOIN sequence seq ON seq.id = eval.sequence_id
  432. WHERE std.id = ? AND eval.sequence_id = ?
  433. ORDER BY crs.id";
  434. $connection->executeStatement($sql, [$std->getId(), $seq->getId()]);
  435. $i++;
  436. }
  437. $connection->executeStatement(
  438. "CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER AS
  439. SELECT DISTINCT seq1.crs as crs,
  440. (seq1.value * seq1.weight + seq2.value * seq2.weight) / (seq1.weight + seq2.weight) as value,
  441. greatest(seq1.weight, seq2.weight) as weight,
  442. seq1.weight as weight1, seq2.weight as weight2,
  443. seq1.value as value1, seq2.value as value2,
  444. seq1.teacher as teacher, seq1.module as module, seq1.room as room
  445. FROM V_STUDENT_MARK_SEQ1 seq1
  446. JOIN V_STUDENT_MARK_SEQ2 seq2 ON seq1.crs = seq2.crs
  447. ORDER BY seq1.crs"
  448. );
  449. // CORRECTION 3 : fetchAll() déprécié → fetchAllAssociative()
  450. $dataQuater = $connection->executeQuery("SELECT * FROM V_STUDENT_MARK_QUATER")->fetchAllAssociative();
  451. $html = $this->renderView('student/reportcardTrimApc.html.twig', [
  452. 'year' => $year,
  453. 'quater' => $quater,
  454. 'data' => $dataQuater,
  455. 'sequences' => $sequences,
  456. 'std' => $std,
  457. 'room' => $sub->getClassRoom(),
  458. 'fileExist' => $fileExist,
  459. ]);
  460. return new Response($pdf->getOutputFromHtml($html), 200, [
  461. 'Content-Type' => 'application/pdf',
  462. 'Content-Disposition' => 'inline; filename="bull_' . $quater->getId() . '_' . $std->getMatricule() . '.pdf"',
  463. ]);
  464. }
  465. /**
  466. * @Route("/{id}/reportCardYear", name="admin_students_reportcards_year", requirements={"id"="\d+"})
  467. * @Method("GET")
  468. * @Template()
  469. */
  470. public function reporCardYear(Student $std, Request $request)
  471. {
  472. if ($redirect = $this->checkAuth()) return $redirect;
  473. $headerFontSize = $request->request->get('header_font_size');
  474. $lineHeight = $request->request->get('line_height');
  475. $copyright = $request->request->get('copyright') == "on";
  476. $connection = $this->em->getConnection();
  477. $year = $this->schoolYearService->sessionYearById();
  478. $sequences = $this->seqRepo->findSequenceThisYear($year);
  479. $sub = $this->subRepo->findOneBy(["student" => $std, "schoolYear" => $year]);
  480. $filename = "assets/images/student/" . $std->getMatricule() . ".jpg";
  481. $fileExist = file_exists($filename);
  482. // CORRECTION 3 : execute() déprécié → executeStatement()
  483. $i = 1;
  484. foreach ($sequences as $seq) {
  485. $sql = "CREATE OR REPLACE VIEW V_STUDENT_MARK_SEQ" . $i . " AS
  486. SELECT DISTINCT eval.id as eval, crs.id as crs, room.id as room, year.id as year,
  487. teach.id as teacher, modu.id as module, m.value as value, m.weight as weight
  488. FROM mark m
  489. JOIN student std ON m.student_id = std.id
  490. JOIN evaluation eval ON m.evaluation_id = eval.id
  491. JOIN class_room room ON eval.class_room_id = room.id
  492. JOIN course crs ON eval.course_id = crs.id
  493. JOIN attribution att ON att.course_id = crs.id
  494. JOIN user teach ON att.teacher_id = teach.id
  495. JOIN module modu ON modu.id = crs.module_id
  496. JOIN sequence seq ON seq.id = eval.sequence_id
  497. JOIN quater quat ON seq.quater_id = quat.id
  498. JOIN school_year year ON quat.school_year_id = year.id
  499. WHERE std.id = ? AND room.id = ? AND eval.sequence_id = ?
  500. ORDER BY crs.id";
  501. $connection->executeStatement($sql, [$std->getId(), $sub->getClassRoom()->getId(), $seq->getId()]);
  502. $i++;
  503. }
  504. $connection->executeStatement(
  505. "CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER1 AS
  506. SELECT DISTINCT seq1.crs as crs,
  507. (seq1.value * seq1.weight + seq2.value * seq2.weight) / (seq1.weight + seq2.weight) as value,
  508. greatest(seq1.weight, seq2.weight) as weight,
  509. seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  510. FROM V_STUDENT_MARK_SEQ1 seq1
  511. JOIN V_STUDENT_MARK_SEQ2 seq2 ON seq1.crs = seq2.crs
  512. ORDER BY seq1.crs"
  513. );
  514. $connection->executeStatement(
  515. "CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER2 AS
  516. SELECT DISTINCT seq1.crs as crs,
  517. (seq1.value * seq1.weight + seq2.value * seq2.weight) / (seq1.weight + seq2.weight) as value,
  518. greatest(seq1.weight, seq2.weight) as weight,
  519. seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  520. FROM V_STUDENT_MARK_SEQ3 seq1
  521. JOIN V_STUDENT_MARK_SEQ4 seq2 ON seq1.crs = seq2.crs
  522. ORDER BY seq1.crs"
  523. );
  524. $connection->executeStatement(
  525. "CREATE OR REPLACE VIEW V_STUDENT_MARK_QUATER3 AS
  526. SELECT DISTINCT seq1.crs as crs,
  527. (seq1.value * seq1.weight + seq2.value * seq2.weight) / (seq1.weight + seq2.weight) as value,
  528. greatest(seq1.weight, seq2.weight) as weight,
  529. seq1.teacher as teacher, seq1.module as modu, seq1.room as room
  530. FROM V_STUDENT_MARK_SEQ5 seq1
  531. JOIN V_STUDENT_MARK_SEQ6 seq2 ON seq1.crs = seq2.crs
  532. ORDER BY seq1.crs"
  533. );
  534. $connection->executeStatement(
  535. "CREATE OR REPLACE VIEW ANNUAL_DATA AS
  536. SELECT DISTINCT
  537. course.wording as course, course.coefficient as coef,
  538. module.name as module,
  539. user.full_name as teacher,
  540. quat1.value as value1, quat1.weight as weight1,
  541. quat2.value as value2, quat2.weight as weight2,
  542. quat3.value as value3, quat3.weight as weight3,
  543. (quat1.value * quat1.weight + quat2.value * quat2.weight + quat3.value * quat3.weight)
  544. / (quat1.weight + quat2.weight + quat3.weight) as value
  545. FROM V_STUDENT_MARK_QUATER1 quat1
  546. JOIN class_room ON class_room.id = quat1.room
  547. JOIN course ON course.id = quat1.crs
  548. JOIN module ON course.module_id = quat1.modu
  549. JOIN user ON user.id = quat1.teacher
  550. JOIN V_STUDENT_MARK_QUATER2 quat2 ON quat1.crs = quat2.crs
  551. JOIN V_STUDENT_MARK_QUATER3 quat3 ON quat2.crs = quat3.crs
  552. ORDER BY module"
  553. );
  554. // CORRECTION 3 : fetchAll() déprécié → fetchAllAssociative()
  555. $dataYear = $connection->executeQuery("SELECT * FROM ANNUAL_DATA")->fetchAllAssociative();
  556. $html = $this->renderView('student/reportcardYearApc.html.twig', [
  557. 'year' => $year,
  558. 'data' => $dataYear,
  559. 'std' => $std,
  560. 'room' => $sub->getClassRoom(),
  561. 'headerFontSize' => 0.75 * $headerFontSize,
  562. 'lineHeight' => 1.5 * $lineHeight,
  563. 'copyright' => $copyright,
  564. 'fileExist' => $fileExist,
  565. ]);
  566. return new Response($this->snappy->getOutputFromHtml($html), 200, [
  567. 'Content-Type' => 'application/pdf',
  568. 'Content-Disposition' => 'attachment; filename="BUL_ANN_' . $std->getMatricule() . '.pdf"',
  569. ]);
  570. }
  571. }