Files
2026-05-16 13:44:12 -04:00

160 lines
5.6 KiB
PHP
Executable File

<?php
namespace App\Controllers\View;
use App\Controllers\BaseController;
use CodeIgniter\Controller;
use App\Models\TeacherClassModel;
use App\Models\StudentModel;
use App\Models\ConfigurationModel;
use App\Models\GradingLockModel;
use App\Models\MissingScoreOverrideModel;
class FinalController extends BaseController
{
protected $db;
protected $schoolYear;
protected $semester;
protected $configModel;
protected $studentModel;
protected $teacherClassModel;
protected $gradingLockModel;
protected $missingScoreOverrideModel;
public function __construct()
{
$this->db = \Config\Database::connect();
$this->configModel = new ConfigurationModel();
$this->studentModel = new StudentModel();
$this->teacherClassModel = new TeacherClassModel();
$this->schoolYear = $this->configModel->getConfig('school_year');
$this->semester = $this->configModel->getConfig('semester');
$this->gradingLockModel = new GradingLockModel();
$this->missingScoreOverrideModel = new MissingScoreOverrideModel();
}
public function add()
{
// Accept class_section_id from POST/GET with session fallback
$incoming = $this->request->getPost('class_section_id')
?? $this->request->getGet('class_section_id')
?? session()->get('class_section_id');
$classSectionId = (int) ($incoming ?: 0);
if ($classSectionId <= 0) {
return redirect()->back()->with('status', 'Missing class section.');
}
// Persist for downstream calls
session()->set('class_section_id', $classSectionId);
$semester = $this->getTeacherSelectedSemester();
$schoolYear = $this->schoolYear;
try {
$result = $this->getSavedScores($classSectionId, $semester, $schoolYear);
$missingOkMap = $this->missingScoreOverrideModel->getOverridesMap($classSectionId, $semester, $schoolYear, 'final_exam');
return view('teacher/add_final_exam', [
'students' => $result['students'],
'semester' => $result['semester'],
'schoolYear' => $result['schoolYear'],
'classSectionId' => $classSectionId,
'missingOkMap' => $missingOkMap,
]);
} catch (\Throwable $e) {
return redirect()->back()->with('status', $e->getMessage());
}
}
public function showFinalMngt()
{
$incoming = $this->request->getPost('class_section_id')
?? $this->request->getGet('class_section_id')
?? session()->get('class_section_id');
$classSectionId = (int) ($incoming ?: 0);
if ($classSectionId <= 0) {
return redirect()->back()->with('status', 'Missing class section.');
}
$semester = $this->getTeacherSelectedSemester();
$schoolYear = $this->schoolYear;
try {
$result = $this->getSavedScores($classSectionId, $semester, $schoolYear);
$scoresLocked = $this->gradingLockModel->isLocked($classSectionId, $semester, $schoolYear);
return view('grading/final', [
'students' => $result['students'],
'semester' => $result['semester'],
'schoolYear' => $result['schoolYear'],
'classSectionId' => $classSectionId,
'scoresLocked' => $scoresLocked,
]);
} catch (\Throwable $e) {
return redirect()->back()->with('status', $e->getMessage());
}
}
private function getSavedScores(int $classSectionId, string $semester, string $schoolYear): array
{
if ($classSectionId <= 0) {
throw new \InvalidArgumentException('Invalid class section id.');
}
session()->set('class_section_id', $classSectionId);
// Subquery: pick ONE final exam row per student (latest by id)
$latestFinalSub = $this->db->table('final_exam')
->select('student_id, MAX(id) AS max_id')
->where('class_section_id', $classSectionId)
->where('semester', $semester)
->where('school_year', $schoolYear)
->groupBy('student_id')
->getCompiledSelect();
// Main query: roster + LEFT JOIN the single final exam row
$qb = $this->studentModel
->select('
s.id AS student_id,
s.school_id,
s.firstname,
s.lastname,
fe.score
')
->from('students s')
->join(
'student_class sc',
'sc.student_id = s.id
AND sc.class_section_id = ' . (int) $classSectionId . '
AND sc.school_year = ' . $this->db->escape($schoolYear),
'inner',
false
)
->join('(' . $latestFinalSub . ') fl', 'fl.student_id = s.id', 'left', false)
->join('final_exam fe', 'fe.id = fl.max_id', 'left')
->orderBy('s.lastname', 'ASC')
->orderBy('s.firstname', 'ASC');
$qb->distinct();
$rows = $qb->get()->getResultArray();
// Ensure one row per student
$unique = [];
foreach ($rows as $r) {
$unique[(int)$r['student_id']] = $r;
}
$students = array_values($unique);
return [
'students' => $students,
'semester' => $semester,
'schoolYear' => $schoolYear,
];
}
private function getTeacherSelectedSemester(): string
{
helper('semester_selection_helper');
return selected_teacher_semester();
}
}