This commit is contained in:
@@ -206,7 +206,11 @@ abstract class BaseController extends Controller
|
||||
'admin',
|
||||
'administrator',
|
||||
'administrative staff',
|
||||
'parent',
|
||||
'principal',
|
||||
'teacher',
|
||||
'teacher assistant',
|
||||
'teacher_assistant',
|
||||
'vice principal',
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -54,6 +54,7 @@ class ClassProgressController extends BaseController
|
||||
|
||||
public function create()
|
||||
{
|
||||
$context = $this->resolveSchoolYearContext();
|
||||
$teacherId = (int) session()->get('user_id');
|
||||
$assignments = $this->loadTeacherSections($teacherId);
|
||||
$first = $assignments[0] ?? null;
|
||||
@@ -76,12 +77,15 @@ class ClassProgressController extends BaseController
|
||||
'classId' => $classId,
|
||||
'sundayOptions' => $sundayOptions,
|
||||
'defaultWeekStart' => $defaultWeekStart,
|
||||
'isSchoolYearReadonly' => $context->isReadonly(),
|
||||
];
|
||||
return view('teacher/class_progress_submit', $data);
|
||||
}
|
||||
|
||||
public function store()
|
||||
{
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
[, $schoolYear] = $this->resolveCurrentTerm();
|
||||
$subjectSections = self::SUBJECT_SECTIONS;
|
||||
$rules = [
|
||||
'class_section_id' => 'required|integer',
|
||||
@@ -132,8 +136,9 @@ class ClassProgressController extends BaseController
|
||||
->select('id')
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('week_start', $weekStart)
|
||||
->where('teacher_id', $teacherId)
|
||||
->findAll();
|
||||
->where('teacher_id', $teacherId);
|
||||
$this->applyProgressSchoolYearScope($existingReports, $schoolYear);
|
||||
$existingReports = $existingReports->findAll();
|
||||
|
||||
if (! $confirmOverwrite && ! empty($existingReports)) {
|
||||
return redirect()->back()
|
||||
@@ -175,7 +180,7 @@ class ClassProgressController extends BaseController
|
||||
'homework' => $homework ?: null,
|
||||
'status' => $status,
|
||||
'flags_json' => $this->normalizeFlags($this->request->getPost('flags')),
|
||||
];
|
||||
] + $this->progressReportSchoolYearData($schoolYear);
|
||||
|
||||
$reportId = $this->reportModel->insert($data, true);
|
||||
$attachmentField = "attachment_$slug";
|
||||
@@ -198,6 +203,7 @@ class ClassProgressController extends BaseController
|
||||
public function history()
|
||||
{
|
||||
$teacherId = (int) session()->get('user_id');
|
||||
[$semester, $schoolYear] = $this->resolveCurrentTerm();
|
||||
$assignments = $this->loadTeacherSections($teacherId);
|
||||
$selectedSectionId = (int) $this->request->getGet('class_section_id');
|
||||
$validSectionIds = array_column($assignments, 'class_section_id');
|
||||
@@ -207,7 +213,6 @@ class ClassProgressController extends BaseController
|
||||
if ($selectedSectionId && ! in_array($selectedSectionId, $validSectionIds, true)) {
|
||||
$selectedSectionId = $validSectionIds[0] ?? null;
|
||||
}
|
||||
[$semester, $schoolYear] = $this->resolveCurrentTerm();
|
||||
$allowedTeacherIds = $this->resolveAssignedTeacherIds($selectedSectionId, $semester, $schoolYear);
|
||||
if (empty($allowedTeacherIds)) {
|
||||
$allowedTeacherIds = [$teacherId];
|
||||
@@ -217,6 +222,7 @@ class ClassProgressController extends BaseController
|
||||
->join('classSection cs', 'cs.class_section_id = class_progress_reports.class_section_id', 'left')
|
||||
->join('users u', 'u.id = class_progress_reports.teacher_id', 'left')
|
||||
->whereIn('teacher_id', $allowedTeacherIds);
|
||||
$this->applyProgressSchoolYearScope($builder, $schoolYear, true);
|
||||
if ($selectedSectionId) {
|
||||
$builder->where('class_progress_reports.class_section_id', $selectedSectionId);
|
||||
}
|
||||
@@ -251,24 +257,27 @@ class ClassProgressController extends BaseController
|
||||
'subjectSections' => self::SUBJECT_SECTIONS,
|
||||
'classSectionOptions' => $sectionOptions,
|
||||
'selectedSectionId' => $selectedSectionId,
|
||||
'schoolYear' => $schoolYear,
|
||||
'isSchoolYearReadonly' => $this->resolveSchoolYearContext()->isReadonly(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function view($id)
|
||||
{
|
||||
$teacherId = (int) session()->get('user_id');
|
||||
$row = $this->reportModel
|
||||
[$semester, $schoolYear] = $this->resolveCurrentTerm();
|
||||
$rowQuery = $this->reportModel
|
||||
->select('class_progress_reports.*, cs.class_section_name, CONCAT(IFNULL(u.firstname, ""), " ", IFNULL(u.lastname, "")) AS teacher_name')
|
||||
->join('classSection cs', 'cs.class_section_id = class_progress_reports.class_section_id', 'left')
|
||||
->join('users u', 'u.id = class_progress_reports.teacher_id', 'left')
|
||||
->where('class_progress_reports.id', (int) $id)
|
||||
->first();
|
||||
->where('class_progress_reports.id', (int) $id);
|
||||
$this->applyProgressSchoolYearScope($rowQuery, $schoolYear, true);
|
||||
$row = $rowQuery->first();
|
||||
|
||||
if (! $row) {
|
||||
throw new PageNotFoundException('Progress report not found.');
|
||||
}
|
||||
|
||||
[$semester, $schoolYear] = $this->resolveCurrentTerm();
|
||||
$allowedTeacherIds = $this->resolveAssignedTeacherIds((int) $row['class_section_id'], $semester, $schoolYear);
|
||||
if (empty($allowedTeacherIds)) {
|
||||
if ($teacherId !== (int) $row['teacher_id']) {
|
||||
@@ -286,7 +295,9 @@ class ClassProgressController extends BaseController
|
||||
->join('users u', 'u.id = class_progress_reports.teacher_id', 'left')
|
||||
->whereIn('teacher_id', $allowedTeacherIds)
|
||||
->where('class_progress_reports.class_section_id', $row['class_section_id'])
|
||||
->where('week_start', $row['week_start'])
|
||||
->where('week_start', $row['week_start']);
|
||||
$this->applyProgressSchoolYearScope($weeklyReportsQuery, $schoolYear);
|
||||
$weeklyReports = $weeklyReportsQuery
|
||||
->orderBy('subject', 'ASC')
|
||||
->findAll();
|
||||
|
||||
@@ -313,17 +324,18 @@ class ClassProgressController extends BaseController
|
||||
public function edit($id)
|
||||
{
|
||||
$teacherId = (int) session()->get('user_id');
|
||||
$row = $this->reportModel
|
||||
[$semester, $schoolYear] = $this->resolveCurrentTerm();
|
||||
$rowQuery = $this->reportModel
|
||||
->select('class_progress_reports.*, cs.class_section_name')
|
||||
->join('classSection cs', 'cs.class_section_id = class_progress_reports.class_section_id', 'left')
|
||||
->where('class_progress_reports.id', (int) $id)
|
||||
->first();
|
||||
->where('class_progress_reports.id', (int) $id);
|
||||
$this->applyProgressSchoolYearScope($rowQuery, $schoolYear);
|
||||
$row = $rowQuery->first();
|
||||
|
||||
if (! $row) {
|
||||
throw new PageNotFoundException('Progress report not found.');
|
||||
}
|
||||
|
||||
[$semester, $schoolYear] = $this->resolveCurrentTerm();
|
||||
$allowedTeacherIds = $this->resolveAssignedTeacherIds((int) $row['class_section_id'], $semester, $schoolYear);
|
||||
if (empty($allowedTeacherIds)) {
|
||||
if ($teacherId !== (int) $row['teacher_id']) {
|
||||
@@ -338,7 +350,9 @@ class ClassProgressController extends BaseController
|
||||
->select('class_progress_reports.*')
|
||||
->whereIn('teacher_id', $allowedTeacherIds)
|
||||
->where('class_section_id', $row['class_section_id'])
|
||||
->where('week_start', $row['week_start'])
|
||||
->where('week_start', $row['week_start']);
|
||||
$this->applyProgressSchoolYearScope($weeklyReportsQuery, $schoolYear);
|
||||
$weeklyReports = $weeklyReportsQuery
|
||||
->orderBy('subject', 'ASC')
|
||||
->findAll();
|
||||
|
||||
@@ -405,18 +419,23 @@ class ClassProgressController extends BaseController
|
||||
'isEdit' => true,
|
||||
'formAction' => base_url('teacher/progress/update/' . (int) $row['id']),
|
||||
'submitLabel' => 'Update Progress',
|
||||
'isSchoolYearReadonly' => $this->resolveSchoolYearContext()->isReadonly(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function update($id)
|
||||
{
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
$teacherId = (int) session()->get('user_id');
|
||||
$row = $this->reportModel->find((int) $id);
|
||||
[$semester, $schoolYear] = $this->resolveCurrentTerm();
|
||||
$rowQuery = $this->reportModel
|
||||
->where('class_progress_reports.id', (int) $id);
|
||||
$this->applyProgressSchoolYearScope($rowQuery, $schoolYear);
|
||||
$row = $rowQuery->first();
|
||||
if (! $row) {
|
||||
throw new PageNotFoundException('Progress report not found.');
|
||||
}
|
||||
|
||||
[$semester, $schoolYear] = $this->resolveCurrentTerm();
|
||||
$allowedTeacherIds = $this->resolveAssignedTeacherIds((int) $row['class_section_id'], $semester, $schoolYear);
|
||||
if (empty($allowedTeacherIds)) {
|
||||
if ($teacherId !== (int) $row['teacher_id']) {
|
||||
@@ -473,8 +492,9 @@ class ClassProgressController extends BaseController
|
||||
->select('id')
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('week_start', $weekStart)
|
||||
->where('teacher_id', $teacherId)
|
||||
->findAll();
|
||||
->where('teacher_id', $teacherId);
|
||||
$this->applyProgressSchoolYearScope($conflicts, $schoolYear);
|
||||
$conflicts = $conflicts->findAll();
|
||||
if (! $confirmOverwrite && ! empty($conflicts)) {
|
||||
return redirect()->back()
|
||||
->withInput()
|
||||
@@ -497,7 +517,9 @@ class ClassProgressController extends BaseController
|
||||
->select('class_progress_reports.*')
|
||||
->whereIn('teacher_id', $allowedTeacherIds)
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('week_start', $row['week_start'])
|
||||
->where('week_start', $row['week_start']);
|
||||
$this->applyProgressSchoolYearScope($weeklyReportsQuery, $schoolYear);
|
||||
$weeklyReports = $weeklyReportsQuery
|
||||
->orderBy('subject', 'ASC')
|
||||
->findAll();
|
||||
|
||||
@@ -533,7 +555,7 @@ class ClassProgressController extends BaseController
|
||||
'unit_title' => $unitTitle,
|
||||
'covered' => $covered,
|
||||
'homework' => $homework ?: null,
|
||||
];
|
||||
] + $this->progressReportSchoolYearData($schoolYear);
|
||||
if ($flagsInput !== null) {
|
||||
$data['flags_json'] = $this->normalizeFlags($flagsInput);
|
||||
}
|
||||
@@ -698,8 +720,7 @@ class ClassProgressController extends BaseController
|
||||
|
||||
protected function loadTeacherSections(int $teacherId): array
|
||||
{
|
||||
$schoolYear = (string) ($this->configModel->getConfig('school_year') ?? '');
|
||||
$semester = (string) ($this->configModel->getConfig('semester') ?? '');
|
||||
[$semester, $schoolYear] = $this->resolveCurrentTerm();
|
||||
return $this->teacherClassModel->getClassAssignmentsByUserId($teacherId, $schoolYear, $semester);
|
||||
}
|
||||
|
||||
@@ -878,7 +899,7 @@ class ClassProgressController extends BaseController
|
||||
|
||||
protected function resolveProgressDateRange(): ?array
|
||||
{
|
||||
$schoolYear = (string) ($this->configModel->getConfig('school_year') ?? '');
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->configModel->getConfig('school_year') ?? ''));
|
||||
if ($schoolYear === '') {
|
||||
return null;
|
||||
}
|
||||
@@ -946,11 +967,65 @@ class ClassProgressController extends BaseController
|
||||
|
||||
protected function resolveCurrentTerm(): array
|
||||
{
|
||||
$schoolYear = (string) ($this->configModel->getConfig('school_year') ?? '');
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->configModel->getConfig('school_year') ?? ''));
|
||||
$semester = (string) ($this->configModel->getConfig('semester') ?? '');
|
||||
return [$semester, $schoolYear];
|
||||
}
|
||||
|
||||
protected function applyProgressSchoolYearScope($builder, string $schoolYear, bool $canScopeBySection = false): void
|
||||
{
|
||||
if ($schoolYear === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$db = db_connect();
|
||||
$hasReportYear = $db->fieldExists('school_year', 'class_progress_reports');
|
||||
$hasSectionYear = $db->fieldExists('school_year', 'classSection');
|
||||
$semesterResolver = new SemesterRangeService($this->configModel);
|
||||
[$rangeStart, $rangeEnd] = $semesterResolver->getSchoolYearRange($schoolYear);
|
||||
|
||||
if ($hasReportYear) {
|
||||
if ($rangeStart !== '' && $rangeEnd !== '') {
|
||||
$builder
|
||||
->groupStart()
|
||||
->where('class_progress_reports.school_year', $schoolYear)
|
||||
->orGroupStart()
|
||||
->groupStart()
|
||||
->where('class_progress_reports.school_year IS NULL', null, false)
|
||||
->orWhere('class_progress_reports.school_year', '')
|
||||
->groupEnd()
|
||||
->where('class_progress_reports.week_start >=', $rangeStart)
|
||||
->where('class_progress_reports.week_start <=', $rangeEnd)
|
||||
->groupEnd()
|
||||
->groupEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
$builder->where('class_progress_reports.school_year', $schoolYear);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($canScopeBySection && $hasSectionYear) {
|
||||
$builder->where('cs.school_year', $schoolYear);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($rangeStart !== '' && $rangeEnd !== '') {
|
||||
$builder
|
||||
->where('class_progress_reports.week_start >=', $rangeStart)
|
||||
->where('class_progress_reports.week_start <=', $rangeEnd);
|
||||
}
|
||||
}
|
||||
|
||||
protected function progressReportSchoolYearData(string $schoolYear): array
|
||||
{
|
||||
if ($schoolYear === '' || ! db_connect()->fieldExists('school_year', 'class_progress_reports')) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ['school_year' => $schoolYear];
|
||||
}
|
||||
|
||||
protected function resolveAssignedTeacherIds(?int $classSectionId, string $semester, string $schoolYear): array
|
||||
{
|
||||
if (! $classSectionId || $schoolYear === '') {
|
||||
|
||||
@@ -29,6 +29,7 @@ class ParentProgressController extends BaseController
|
||||
|
||||
public function index()
|
||||
{
|
||||
$schoolYear = $this->currentSchoolYearName();
|
||||
$students = $this->getParentStudents();
|
||||
$sectionIds = array_values(array_unique(array_filter(array_map(
|
||||
static fn (array $student): int => (int) ($student['class_section_id'] ?? 0),
|
||||
@@ -42,7 +43,8 @@ class ParentProgressController extends BaseController
|
||||
->select('class_progress_reports.*, cs.class_section_name, CONCAT(IFNULL(u.firstname, ""), " ", IFNULL(u.lastname, "")) AS teacher_name')
|
||||
->join('classSection cs', 'cs.class_section_id = class_progress_reports.class_section_id', 'left')
|
||||
->join('users u', 'u.id = class_progress_reports.teacher_id', 'left')
|
||||
->whereIn('class_progress_reports.class_section_id', $sectionIds);
|
||||
->whereIn('class_progress_reports.class_section_id', $sectionIds)
|
||||
->where('class_progress_reports.school_year', $schoolYear);
|
||||
|
||||
$rows = $builder
|
||||
->orderBy('week_start', 'DESC')
|
||||
@@ -75,10 +77,12 @@ class ParentProgressController extends BaseController
|
||||
|
||||
public function view($id)
|
||||
{
|
||||
$schoolYear = $this->currentSchoolYearName();
|
||||
$row = $this->reportModel
|
||||
->select('class_progress_reports.*, cs.class_section_name, CONCAT(IFNULL(u.firstname, ""), " ", IFNULL(u.lastname, "")) AS teacher_name')
|
||||
->join('classSection cs', 'cs.class_section_id = class_progress_reports.class_section_id', 'left')
|
||||
->join('users u', 'u.id = class_progress_reports.teacher_id', 'left')
|
||||
->where('class_progress_reports.school_year', $schoolYear)
|
||||
->find((int) $id);
|
||||
|
||||
if (! $row || ! $this->isSectionAccessible($row['class_section_id'] ?? null)) {
|
||||
@@ -92,6 +96,7 @@ class ParentProgressController extends BaseController
|
||||
->select('class_progress_reports.*')
|
||||
->where('class_section_id', $row['class_section_id'])
|
||||
->where('week_start', $row['week_start'])
|
||||
->where('school_year', $schoolYear)
|
||||
->orderBy('subject', 'ASC')
|
||||
->findAll();
|
||||
|
||||
@@ -165,6 +170,7 @@ class ParentProgressController extends BaseController
|
||||
$rows = $this->enrollmentModel
|
||||
->select('class_section_id')
|
||||
->where('parent_id', $parentId)
|
||||
->where('school_year', $this->currentSchoolYearName())
|
||||
->where('is_withdrawn', 0)
|
||||
->groupBy('class_section_id')
|
||||
->findAll();
|
||||
@@ -213,6 +219,7 @@ class ParentProgressController extends BaseController
|
||||
->join('students s', 's.id = e.student_id')
|
||||
->join('classSection cs', 'cs.class_section_id = e.class_section_id', 'left')
|
||||
->where('e.parent_id', $parentId)
|
||||
->where('e.school_year', $this->currentSchoolYearName())
|
||||
->where('e.is_withdrawn', 0)
|
||||
->orderBy('e.updated_at', 'DESC')
|
||||
->orderBy('e.created_at', 'DESC')
|
||||
|
||||
@@ -31,7 +31,7 @@ class ParentReportCardController extends BaseController
|
||||
return redirect()->back()->with('error', 'Unable to retrieve student data. Please contact support.');
|
||||
}
|
||||
|
||||
$schoolYear = trim((string) ($this->request->getGet('school_year') ?? $this->currentSchoolYearName()));
|
||||
$schoolYear = trim((string) $this->currentSchoolYearName());
|
||||
$semester = trim((string) ($this->request->getGet('semester') ?? $this->configModel->getConfig('semester') ?? ''));
|
||||
|
||||
$builder = $this->db->table('students s')
|
||||
@@ -82,7 +82,7 @@ class ParentReportCardController extends BaseController
|
||||
throw new PageNotFoundException('Student not found.');
|
||||
}
|
||||
|
||||
$schoolYear = trim((string) ($this->request->getGet('school_year') ?? $this->currentSchoolYearName()));
|
||||
$schoolYear = trim((string) $this->currentSchoolYearName());
|
||||
$semester = trim((string) ($this->request->getGet('semester') ?? $this->configModel->getConfig('semester') ?? ''));
|
||||
|
||||
$this->touchAcknowledgement($parentId, (int) $studentId, $schoolYear, $semester, [
|
||||
|
||||
@@ -12,6 +12,7 @@ use App\Models\TeacherClassModel;
|
||||
use App\Models\AdminNotificationSubjectModel;
|
||||
use App\Models\NotificationModel;
|
||||
use App\Models\UserNotificationModel;
|
||||
use App\Services\SemesterRangeService;
|
||||
use CodeIgniter\Exceptions\PageNotFoundException;
|
||||
|
||||
class PrintRequests extends BaseController
|
||||
@@ -46,18 +47,26 @@ class PrintRequests extends BaseController
|
||||
public function teacher_index()
|
||||
{
|
||||
$teacher_id = session()->get('user_id');
|
||||
$context = $this->resolveSchoolYearContext();
|
||||
$schoolYear = $context->yearName();
|
||||
|
||||
$data['print_requests'] = $this->printRequestModel
|
||||
$printRequestsQuery = $this->printRequestModel
|
||||
->select('print_requests.*, admins.firstname as admin_firstname, admins.lastname as admin_lastname')
|
||||
->join('users as admins', 'admins.id = print_requests.admin_id', 'left')
|
||||
->where('print_requests.teacher_id', $teacher_id)
|
||||
->join('classSection cs', 'cs.class_section_id = print_requests.class_id', 'left')
|
||||
->where('print_requests.teacher_id', $teacher_id);
|
||||
$this->applyPrintRequestSchoolYearScope($printRequestsQuery, $schoolYear);
|
||||
$data['print_requests'] = $printRequestsQuery
|
||||
->orderBy('print_requests.required_by', 'DESC')
|
||||
->orderBy('print_requests.id', 'DESC')
|
||||
->findAll();
|
||||
|
||||
$teacher_classes = $this->teacherClassModel->getClassByTeacherId($teacher_id);
|
||||
$teacher_classes = $this->teacherClassModel->getClassAssignmentsByUserId((int) $teacher_id, $schoolYear);
|
||||
$data['class_id'] = !empty($teacher_classes) ? $teacher_classes[0]['class_section_id'] : null;
|
||||
$dateOptions = $this->buildRequiredByOptions();
|
||||
$data['sundays'] = $dateOptions['sundays'];
|
||||
$data['times'] = $dateOptions['times'];
|
||||
$data['isSchoolYearReadonly'] = $context->isReadonly();
|
||||
|
||||
return view('print_requests/teacher_index', $data);
|
||||
}
|
||||
@@ -94,6 +103,9 @@ class PrintRequests extends BaseController
|
||||
|
||||
public function create()
|
||||
{
|
||||
$context = $this->resolveSchoolYearContext();
|
||||
$this->assertSchoolYearWritable($context);
|
||||
$schoolYear = $context->yearName();
|
||||
$validationRules = [
|
||||
'file' => 'uploaded[file]|max_size[file,5120]|ext_in[file,pdf,jpg,png,jpeg,doc,docx,txt]',
|
||||
'page_selection' => 'permit_empty|regex_match[/^\\s*\\d+(?:\\s*-\\s*\\d+)?(?:\\s*,\\s*\\d+(?:\\s*-\\s*\\d+)?)*\\s*$/]',
|
||||
@@ -125,7 +137,7 @@ class PrintRequests extends BaseController
|
||||
'required_by' => $this->request->getPost('required_by'),
|
||||
'pickup_method' => $this->request->getPost('pickup_method'),
|
||||
'status' => 'not_assigned',
|
||||
];
|
||||
] + $this->printRequestSchoolYearData($schoolYear);
|
||||
|
||||
$printRequestId = (int) $this->printRequestModel->insert($data, true);
|
||||
if ($printRequestId > 0) {
|
||||
@@ -175,6 +187,7 @@ class PrintRequests extends BaseController
|
||||
|
||||
// Case 2: Teacher edit
|
||||
if ($this->request->getPost('num_copies')) {
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
$user_id = session()->get('user_id');
|
||||
if ($request['teacher_id'] != $user_id) {
|
||||
return redirect()->to('teacher/print-requests')->with('error', 'You are not authorized to edit this request.');
|
||||
@@ -230,6 +243,7 @@ class PrintRequests extends BaseController
|
||||
|
||||
public function delete($id)
|
||||
{
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
$teacher_id = session()->get('user_id');
|
||||
$request = $this->printRequestModel->find($id);
|
||||
|
||||
@@ -260,6 +274,9 @@ class PrintRequests extends BaseController
|
||||
public function copy($id)
|
||||
{
|
||||
$teacher_id = session()->get('user_id');
|
||||
$context = $this->resolveSchoolYearContext();
|
||||
$this->assertSchoolYearWritable($context);
|
||||
$schoolYear = $context->yearName();
|
||||
$request = $this->printRequestModel->find($id);
|
||||
|
||||
if (!$request) {
|
||||
@@ -296,7 +313,7 @@ class PrintRequests extends BaseController
|
||||
'required_by' => $request['required_by'],
|
||||
'pickup_method' => $request['pickup_method'],
|
||||
'status' => 'not_assigned',
|
||||
];
|
||||
] + $this->printRequestSchoolYearData($schoolYear);
|
||||
|
||||
$copiedId = (int) $this->printRequestModel->insert($data, true);
|
||||
if ($copiedId > 0) {
|
||||
@@ -308,6 +325,9 @@ class PrintRequests extends BaseController
|
||||
|
||||
public function createCopy()
|
||||
{
|
||||
$context = $this->resolveSchoolYearContext();
|
||||
$this->assertSchoolYearWritable($context);
|
||||
$schoolYear = $context->yearName();
|
||||
$validationRules = [
|
||||
'num_copies' => 'required|integer|greater_than[0]',
|
||||
'required_by' => 'required|valid_date',
|
||||
@@ -329,7 +349,7 @@ class PrintRequests extends BaseController
|
||||
'required_by' => $this->request->getPost('required_by'),
|
||||
'pickup_method' => $this->request->getPost('pickup_method'),
|
||||
'status' => 'not_assigned',
|
||||
];
|
||||
] + $this->printRequestSchoolYearData($schoolYear);
|
||||
|
||||
$printRequestId = (int) $this->printRequestModel->insert($data, true);
|
||||
if ($printRequestId > 0) {
|
||||
@@ -374,6 +394,95 @@ class PrintRequests extends BaseController
|
||||
];
|
||||
}
|
||||
|
||||
private function applyPrintRequestSchoolYearScope($query, string $schoolYear): void
|
||||
{
|
||||
if ($schoolYear === '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$hasPrintRequestYear = $this->printRequestsHaveSchoolYearColumn();
|
||||
$hasClassSectionYear = db_connect()->fieldExists('school_year', 'classSection');
|
||||
$range = (new SemesterRangeService($this->configModel))->getSchoolYearRange($schoolYear);
|
||||
[$rangeStart, $rangeEnd] = $range;
|
||||
|
||||
if ($hasPrintRequestYear && $hasClassSectionYear) {
|
||||
$query->groupStart()
|
||||
->where('print_requests.school_year', $schoolYear)
|
||||
->orGroupStart()
|
||||
->groupStart()
|
||||
->where('print_requests.school_year IS NULL', null, false)
|
||||
->orWhere('print_requests.school_year', '')
|
||||
->groupEnd()
|
||||
->where('cs.school_year', $schoolYear)
|
||||
->groupEnd();
|
||||
|
||||
if ($rangeStart !== '' && $rangeEnd !== '') {
|
||||
$query
|
||||
->orGroupStart()
|
||||
->groupStart()
|
||||
->where('print_requests.school_year IS NULL', null, false)
|
||||
->orWhere('print_requests.school_year', '')
|
||||
->groupEnd()
|
||||
->groupStart()
|
||||
->where('cs.school_year IS NULL', null, false)
|
||||
->orWhere('cs.school_year', '')
|
||||
->groupEnd()
|
||||
->where('print_requests.required_by >=', $rangeStart . ' 00:00:00')
|
||||
->where('print_requests.required_by <=', $rangeEnd . ' 23:59:59')
|
||||
->groupEnd();
|
||||
}
|
||||
|
||||
$query->groupEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $hasPrintRequestYear && $hasClassSectionYear) {
|
||||
$query->where('cs.school_year', $schoolYear);
|
||||
return;
|
||||
}
|
||||
|
||||
if ($rangeStart !== '' && $rangeEnd !== '') {
|
||||
if ($hasPrintRequestYear) {
|
||||
$query
|
||||
->groupStart()
|
||||
->where('print_requests.school_year', $schoolYear)
|
||||
->orGroupStart()
|
||||
->groupStart()
|
||||
->where('print_requests.school_year IS NULL', null, false)
|
||||
->orWhere('print_requests.school_year', '')
|
||||
->groupEnd()
|
||||
->where('print_requests.required_by >=', $rangeStart . ' 00:00:00')
|
||||
->where('print_requests.required_by <=', $rangeEnd . ' 23:59:59')
|
||||
->groupEnd()
|
||||
->groupEnd();
|
||||
return;
|
||||
}
|
||||
|
||||
$query
|
||||
->where('print_requests.required_by >=', $rangeStart . ' 00:00:00')
|
||||
->where('print_requests.required_by <=', $rangeEnd . ' 23:59:59');
|
||||
return;
|
||||
}
|
||||
|
||||
if ($hasPrintRequestYear) {
|
||||
$query->where('print_requests.school_year', $schoolYear);
|
||||
}
|
||||
}
|
||||
|
||||
private function printRequestSchoolYearData(string $schoolYear): array
|
||||
{
|
||||
if ($schoolYear === '' || ! $this->printRequestsHaveSchoolYearColumn()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return ['school_year' => $schoolYear];
|
||||
}
|
||||
|
||||
private function printRequestsHaveSchoolYearColumn(): bool
|
||||
{
|
||||
return db_connect()->fieldExists('school_year', 'print_requests');
|
||||
}
|
||||
|
||||
public function serveFile(string $filename, string $mode = 'inline')
|
||||
{
|
||||
$safeName = basename(trim($filename));
|
||||
|
||||
@@ -91,6 +91,9 @@ class ExamDraftController extends BaseController
|
||||
|
||||
public function teacherIndex()
|
||||
{
|
||||
$this->syncAcademicContext();
|
||||
$context = $this->resolveSchoolYearContext();
|
||||
|
||||
$teacherId = (int) (session()->get('user_id') ?? 0);
|
||||
if ($teacherId <= 0) {
|
||||
return redirect()->to('/login');
|
||||
@@ -175,11 +178,15 @@ class ExamDraftController extends BaseController
|
||||
'maxUploadBytes' => self::MAX_UPLOAD_BYTES,
|
||||
'validation' => $validation,
|
||||
'printableDraftIds' => $printableIds,
|
||||
'isSchoolYearReadonly' => $context->isReadonly(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function teacherStore()
|
||||
{
|
||||
$this->syncAcademicContext();
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
|
||||
$teacherId = (int) (session()->get('user_id') ?? 0);
|
||||
if ($teacherId <= 0) {
|
||||
return redirect()->to('/login');
|
||||
@@ -193,10 +200,13 @@ class ExamDraftController extends BaseController
|
||||
return redirect()->back()->withInput()->with('error', 'Select a class section before submitting.');
|
||||
}
|
||||
|
||||
$assignment = $this->teacherClassModel
|
||||
$assignmentQuery = $this->teacherClassModel
|
||||
->where('teacher_id', $teacherId)
|
||||
->where('class_section_id', $classSectionId)
|
||||
->first();
|
||||
->where('class_section_id', $classSectionId);
|
||||
if ($this->schoolYear !== '') {
|
||||
$assignmentQuery->where('school_year', $this->schoolYear);
|
||||
}
|
||||
$assignment = $assignmentQuery->first();
|
||||
|
||||
if (empty($assignment)) {
|
||||
return redirect()->back()->withInput()->with('error', 'You are not assigned to the selected class section.');
|
||||
@@ -785,6 +795,8 @@ class ExamDraftController extends BaseController
|
||||
|
||||
public function teacherStatusFeed()
|
||||
{
|
||||
$this->syncAcademicContext();
|
||||
|
||||
$teacherId = (int) (session()->get('user_id') ?? 0);
|
||||
if ($teacherId <= 0) {
|
||||
return $this->response->setStatusCode(401);
|
||||
@@ -848,6 +860,8 @@ class ExamDraftController extends BaseController
|
||||
->join('classSection cs', 'cs.class_section_id = exam_drafts.class_section_id', 'left')
|
||||
->join('users u', 'u.id = exam_drafts.' . $this->authorIdColumn, 'left');
|
||||
|
||||
$this->applyExamDraftYearScope($query);
|
||||
|
||||
if (empty($classSectionIds)) {
|
||||
return $query->where('exam_drafts.' . $this->authorIdColumn, $teacherId);
|
||||
}
|
||||
@@ -859,19 +873,25 @@ class ExamDraftController extends BaseController
|
||||
->where('exam_drafts.' . $this->authorIdColumn . ' !=', $teacherId)
|
||||
->where('exam_drafts.status !=', 'draft');
|
||||
|
||||
if ($this->schoolYear !== '') {
|
||||
$query->where('exam_drafts.school_year', $this->schoolYear);
|
||||
}
|
||||
if ($this->semester !== '') {
|
||||
$query->where('exam_drafts.semester', $this->semester);
|
||||
}
|
||||
|
||||
$query->groupEnd()
|
||||
->groupEnd();
|
||||
|
||||
return $query;
|
||||
}
|
||||
|
||||
private function syncAcademicContext(): void
|
||||
{
|
||||
$this->schoolYear = $this->currentSchoolYearName((string) ($this->configModel->getConfig('school_year') ?? ''));
|
||||
$this->semester = (string) ($this->configModel->getConfig('semester') ?? '');
|
||||
}
|
||||
|
||||
private function applyExamDraftYearScope($query): void
|
||||
{
|
||||
if ($this->schoolYear !== '') {
|
||||
$query->where('exam_drafts.school_year', $this->schoolYear);
|
||||
}
|
||||
}
|
||||
|
||||
private function attachTeacherDraftContext(array $row, int $viewerId): array
|
||||
{
|
||||
$isOwn = $this->draftTeacherId($row) === $viewerId;
|
||||
|
||||
@@ -1065,13 +1065,7 @@ class GradingController extends Controller
|
||||
|
||||
public function belowSixty()
|
||||
{
|
||||
$configuredYear = (string) $this->schoolYear;
|
||||
|
||||
$schoolYear = trim((string)($this->request->getGet('school_year') ?? ''));
|
||||
|
||||
if ($schoolYear === '') {
|
||||
$schoolYear = $configuredYear;
|
||||
}
|
||||
$schoolYear = $this->currentSchoolYearName((string) $this->schoolYear);
|
||||
|
||||
// This page is Fall only.
|
||||
$semester = 'fall';
|
||||
@@ -1124,6 +1118,16 @@ public function belowSixty()
|
||||
'canViewGrading' => $canViewGrading,
|
||||
]);
|
||||
}
|
||||
|
||||
private function currentSchoolYearName(?string $fallback = null): string
|
||||
{
|
||||
try {
|
||||
return service('schoolYearContext')->resolve($this->request)->yearName();
|
||||
} catch (\Throwable) {
|
||||
return trim((string) ($fallback ?? ''));
|
||||
}
|
||||
}
|
||||
|
||||
public function editBelowSixtyEmail()
|
||||
{
|
||||
$studentId = (int)$this->request->getGet('student_id');
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace App\Controllers\View;
|
||||
use App\Models\HomeworkModel;
|
||||
use App\Models\StudentModel;
|
||||
use App\Models\StudentClassModel;
|
||||
use CodeIgniter\Controller;
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\TeacherClassModel;
|
||||
use App\Models\ConfigurationModel;
|
||||
use App\Models\UserModel;
|
||||
@@ -16,7 +16,7 @@ use App\Controllers\View\GradingController;
|
||||
use App\Models\GradingLockModel;
|
||||
use App\Models\MissingScoreOverrideModel;
|
||||
|
||||
class HomeworkController extends Controller
|
||||
class HomeworkController extends BaseController
|
||||
{
|
||||
protected $db;
|
||||
protected $semesterScoreService;
|
||||
@@ -59,11 +59,12 @@ class HomeworkController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
public function updateHomeworkScores(array $scores = null, int $updatedBy = null, int $classSectionId = null)
|
||||
public function updateHomeworkScores(?array $scores = null, ?int $updatedBy = null, ?int $classSectionId = null)
|
||||
{
|
||||
$scores = $this->request->getPost('scores');
|
||||
$semester = $this->request->getPost('semester') ?? $this->semester;
|
||||
$schoolYear = $this->request->getPost('school_year') ?? $this->schoolYear;
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
|
||||
if ($updatedBy === null) {
|
||||
$updatedBy = session()->get('user_id');
|
||||
@@ -195,6 +196,8 @@ class HomeworkController extends Controller
|
||||
$selectedSemester = $this->getSelectedSemester();
|
||||
$normalized = $this->normalizeSemesterSelection($selectedSemester);
|
||||
$semesterLabel = $normalized !== '' ? ucfirst($normalized) : $selectedSemester;
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
|
||||
// Step 1: Get the highest existing homework_index
|
||||
$existingIndexes = $this->homeworkModel
|
||||
@@ -202,7 +205,7 @@ class HomeworkController extends Controller
|
||||
->where('class_section_id', $classSectionId)
|
||||
//->where('teacher_id', $updatedBy)
|
||||
->whereIn('semester', $this->getSemesterVariants($semesterLabel))
|
||||
->where('school_year', $this->schoolYear)
|
||||
->where('school_year', $schoolYear)
|
||||
->groupBy('homework_index')
|
||||
->orderBy('homework_index', 'DESC')
|
||||
->findAll();
|
||||
@@ -219,6 +222,7 @@ class HomeworkController extends Controller
|
||||
// Step 2: Get all students in the class
|
||||
$students = $this->studentClassModel
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('school_year', $schoolYear)
|
||||
->findAll();
|
||||
|
||||
// Step 3: Insert a new homework row for each student if not already exists
|
||||
@@ -233,7 +237,7 @@ class HomeworkController extends Controller
|
||||
->where('class_section_id', $classSectionId)
|
||||
//->where('teacher_id', $updatedBy)
|
||||
->whereIn('semester', $this->getSemesterVariants($semesterLabel))
|
||||
->where('school_year', $this->schoolYear)
|
||||
->where('school_year', $schoolYear)
|
||||
->first();
|
||||
|
||||
if ($existing) continue;
|
||||
@@ -246,7 +250,7 @@ class HomeworkController extends Controller
|
||||
'homework_index' => $nextIndex,
|
||||
'score' => null,
|
||||
'semester' => $semesterLabel,
|
||||
'school_year' => $this->schoolYear,
|
||||
'school_year' => $schoolYear,
|
||||
'created_at' => utc_now(),
|
||||
'updated_at' => utc_now()
|
||||
];
|
||||
@@ -269,15 +273,23 @@ class HomeworkController extends Controller
|
||||
public function showHomework()
|
||||
{
|
||||
$updatedBy = session()->get('user_id');
|
||||
$classSectionId = $this->getClassSectionIdForTeacher($updatedBy);
|
||||
$semester = $this->getSelectedSemester();
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
$classSectionId = (int) (
|
||||
$this->request->getGet('class_section_id')
|
||||
?? $this->request->getPost('class_section_id')
|
||||
?? 0
|
||||
);
|
||||
if ($classSectionId <= 0) {
|
||||
$classSectionId = (int) ($this->getClassSectionIdForTeacher($updatedBy, $schoolYear, $semester) ?? 0);
|
||||
}
|
||||
if (!$classSectionId) {
|
||||
return redirect()->back()->with('status', 'No class section found for the current teacher.');
|
||||
}
|
||||
|
||||
session()->set('class_section_id', $classSectionId);
|
||||
|
||||
$semester = $this->getSelectedSemester();
|
||||
$homeworkHeaders = $this->getHomeworkHeaders($classSectionId, $semester, $this->schoolYear);
|
||||
$homeworkHeaders = $this->getHomeworkHeaders($classSectionId, $semester, $schoolYear);
|
||||
if (empty($homeworkHeaders)) {
|
||||
$homeworkHeaders = [1];
|
||||
}
|
||||
@@ -285,15 +297,15 @@ class HomeworkController extends Controller
|
||||
$classSectionId,
|
||||
$homeworkHeaders,
|
||||
$semester,
|
||||
$this->schoolYear
|
||||
$schoolYear
|
||||
);
|
||||
$missingOkMap = $this->missingScoreOverrideModel->getOverridesMap($classSectionId, $semester, $this->schoolYear, 'homework');
|
||||
$missingOkMap = $this->missingScoreOverrideModel->getOverridesMap($classSectionId, $semester, $schoolYear, 'homework');
|
||||
|
||||
return view('teacher/add_homework', [
|
||||
'students' => $students,
|
||||
'homeworkHeaders' => $homeworkHeaders,
|
||||
'semester' => $semester,
|
||||
'schoolYear' => $this->schoolYear,
|
||||
'schoolYear' => $schoolYear,
|
||||
'class_section_id' => $classSectionId,
|
||||
'missingOkMap' => $missingOkMap,
|
||||
]);
|
||||
@@ -503,9 +515,16 @@ class HomeworkController extends Controller
|
||||
return $students;
|
||||
}
|
||||
|
||||
private function getClassSectionIdForTeacher($updatedBy)
|
||||
private function getClassSectionIdForTeacher($updatedBy, ?string $schoolYear = null, ?string $semester = null)
|
||||
{
|
||||
$class = $this->teacherClassModel->where('teacher_id', $updatedBy)->first();
|
||||
$builder = $this->teacherClassModel->where('teacher_id', $updatedBy);
|
||||
if ($schoolYear !== null && $schoolYear !== '') {
|
||||
$builder->where('school_year', $schoolYear);
|
||||
}
|
||||
if ($semester !== null && $semester !== '') {
|
||||
$builder->where('semester', $semester);
|
||||
}
|
||||
$class = $builder->first();
|
||||
return $class['class_section_id'] ?? null;
|
||||
}
|
||||
|
||||
|
||||
@@ -1644,23 +1644,8 @@ private function getGradeLevel($grade): array
|
||||
return redirect()->back()->with('error', 'Unable to retrieve student data. Please contact support.');
|
||||
}
|
||||
|
||||
$currentSchoolYear = $this->schoolYear;
|
||||
|
||||
// Get available school years from invoices
|
||||
$schoolYears = $this->invoiceModel
|
||||
->select('school_year')
|
||||
->distinct()
|
||||
->where('parent_id', $parentId)
|
||||
->orderBy('school_year', 'DESC')
|
||||
->findAll();
|
||||
|
||||
// Determine which year to show
|
||||
$selectedYear = $this->request->getGet('school_year');
|
||||
|
||||
if (empty($selectedYear)) {
|
||||
$hasCurrentYear = in_array($currentSchoolYear, array_column($schoolYears, 'school_year'));
|
||||
$selectedYear = $hasCurrentYear ? $currentSchoolYear : (!empty($schoolYears) ? $schoolYears[0]['school_year'] : null);
|
||||
}
|
||||
$currentSchoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
$selectedYear = $currentSchoolYear;
|
||||
|
||||
// Fetch invoices for the selected year
|
||||
$invoices = [];
|
||||
@@ -1718,7 +1703,6 @@ private function getGradeLevel($grade): array
|
||||
|
||||
return view('/parent/invoice_payment', [
|
||||
'invoices' => $invoices,
|
||||
'schoolYears' => $schoolYears,
|
||||
'selectedYear' => $selectedYear,
|
||||
'currentSchoolYear' => $currentSchoolYear,
|
||||
'dueDate' => $this->dueDate,
|
||||
|
||||
@@ -58,7 +58,7 @@ class ParentAttendanceReportController extends BaseController
|
||||
[$sundays, $defaultDate] = $this->computeSundays();
|
||||
|
||||
// Load upcoming reports for preview/edit (today and forward within this school year)
|
||||
$schoolYear = (string) $this->configModel->getConfig('school_year');
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->configModel->getConfig('school_year') ?? ''));
|
||||
$todayYmd = local_date(utc_now(), 'Y-m-d');
|
||||
$previewRows = $this->reportModel->builder()
|
||||
->select('parent_attendance_reports.*, s.firstname, s.lastname')
|
||||
@@ -141,6 +141,7 @@ class ParentAttendanceReportController extends BaseController
|
||||
$dismissTime = $post['dismiss_time'] ?? null;
|
||||
$reasonRaw = $post['reason'] ?? null;
|
||||
$reason = is_string($reasonRaw) ? trim($reasonRaw) : null;
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->configModel->getConfig('school_year') ?? ''));
|
||||
|
||||
// Enforce Sunday-only and future-or-today selection
|
||||
$todayCheck = new \DateTime('today');
|
||||
@@ -157,7 +158,7 @@ class ParentAttendanceReportController extends BaseController
|
||||
}
|
||||
$validDates = [];
|
||||
|
||||
$cap = $this->firstSundayOfJune((string) $this->configModel->getConfig('school_year'));
|
||||
$cap = $this->firstSundayOfJune($schoolYear);
|
||||
|
||||
$lateCutoff = null;
|
||||
$lateNow = null;
|
||||
@@ -236,7 +237,6 @@ class ParentAttendanceReportController extends BaseController
|
||||
// Upper bound already enforced by $validDates building
|
||||
|
||||
$semester = (string) $this->configModel->getConfig('semester');
|
||||
$schoolYear = (string) $this->configModel->getConfig('school_year');
|
||||
$semesterResolver = new SemesterRangeService($this->configModel);
|
||||
|
||||
$inserted = 0;
|
||||
@@ -493,7 +493,7 @@ class ParentAttendanceReportController extends BaseController
|
||||
}
|
||||
|
||||
// Upper bound: first Sunday of June (school year end)
|
||||
$schoolYear = (string) $this->configModel->getConfig('school_year');
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->configModel->getConfig('school_year') ?? ''));
|
||||
$cap = $this->firstSundayOfJune($schoolYear);
|
||||
|
||||
$dates = [];
|
||||
@@ -1458,12 +1458,15 @@ class ParentAttendanceReportController extends BaseController
|
||||
return $this->response->setJSON(['ok' => true, 'students' => []]);
|
||||
}
|
||||
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->configModel->getConfig('school_year') ?? ''));
|
||||
|
||||
// Fetch existing submissions for these students on this date
|
||||
$rows = $this->reportModel->builder()
|
||||
->select('parent_attendance_reports.student_id, parent_attendance_reports.type, parent_attendance_reports.report_date, s.firstname, s.lastname')
|
||||
->join('students s', 's.id = parent_attendance_reports.student_id', 'left')
|
||||
->whereIn('parent_attendance_reports.report_date', $dateValues)
|
||||
->whereIn('parent_attendance_reports.student_id', $studentIds)
|
||||
->where('parent_attendance_reports.school_year', $schoolYear)
|
||||
->get()->getResultArray();
|
||||
|
||||
$map = [];
|
||||
|
||||
@@ -164,10 +164,7 @@ class ParentController extends BaseController
|
||||
return redirect()->back()->with('error', 'Parent session not found.');
|
||||
}
|
||||
|
||||
$currentSchoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
|
||||
// Get selected school year (no semester filter on parent view)
|
||||
$selectedYear = $this->request->getVar('school_year') ?? $currentSchoolYear;
|
||||
$selectedYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
|
||||
// Build query to retrieve attendance
|
||||
$builder = $this->db->table('attendance_data');
|
||||
@@ -180,19 +177,10 @@ class ParentController extends BaseController
|
||||
$query = $builder->get();
|
||||
$attendanceResults = $query->getResultArray();
|
||||
|
||||
// Get list of available school years
|
||||
$schoolYears = $this->db->table('attendance_data')
|
||||
->select('school_year')
|
||||
->distinct()
|
||||
->orderBy('school_year', 'DESC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
// If no records found, set a flag to show message in the view
|
||||
if (empty($attendanceResults)) {
|
||||
return view('/parent/attendance', [
|
||||
'attendance' => null,
|
||||
'schoolYears' => $schoolYears,
|
||||
'selectedYear' => $selectedYear,
|
||||
'selectedSemester' => null,
|
||||
//'error' => 'No attendance records found for the selected school year and semester.'
|
||||
@@ -202,7 +190,6 @@ class ParentController extends BaseController
|
||||
// Return view with attendance results
|
||||
return view('/parent/attendance', [
|
||||
'attendance' => $attendanceResults,
|
||||
'schoolYears' => $schoolYears,
|
||||
'selectedYear' => $selectedYear,
|
||||
'selectedSemester' => null,
|
||||
'error' => null
|
||||
@@ -212,7 +199,6 @@ class ParentController extends BaseController
|
||||
|
||||
return view('/parent/attendance', [
|
||||
'attendance' => null,
|
||||
'schoolYears' => [],
|
||||
'selectedYear' => $selectedYear ?? null,
|
||||
'selectedSemester' => null,
|
||||
'error' => 'Failed to retrieve attendance data. Please try again later.'
|
||||
@@ -269,9 +255,9 @@ class ParentController extends BaseController
|
||||
return redirect()->back()->with('error', 'Configuration error: School year missing.');
|
||||
}
|
||||
|
||||
// Get selected school year from request or fallback
|
||||
$selectedYear = $this->request->getGet('school_year') ?? $this->schoolYear;
|
||||
$isEditable = ($selectedYear === $this->schoolYear);
|
||||
$context = $this->resolveSchoolYearContext();
|
||||
$selectedYear = $context->yearName();
|
||||
$isEditable = ! $context->isReadonly();
|
||||
|
||||
// Get parent ID from session
|
||||
$parentId = session()->get('user_id');
|
||||
@@ -370,22 +356,9 @@ class ParentController extends BaseController
|
||||
);
|
||||
}
|
||||
|
||||
// Fetch available school years
|
||||
$schoolYears = $this->db->table('enrollments')
|
||||
->select('school_year')
|
||||
->distinct()
|
||||
->orderBy('school_year', 'DESC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
if (empty($schoolYears)) {
|
||||
$schoolYears[] = ['school_year' => $this->schoolYear];
|
||||
}
|
||||
|
||||
// Render view
|
||||
return view('/parent/enroll_classes', [
|
||||
'students' => $students,
|
||||
'schoolYears' => $schoolYears,
|
||||
'selectedYear' => $selectedYear,
|
||||
'isEditable' => $isEditable,
|
||||
'withdrawalDeadline' => $this->withdrawalDeadline,
|
||||
|
||||
@@ -5,7 +5,7 @@ namespace App\Controllers\View;
|
||||
use App\Models\ProjectModel;
|
||||
use App\Models\StudentModel;
|
||||
use App\Models\StudentClassModel;
|
||||
use CodeIgniter\Controller;
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\TeacherClassModel;
|
||||
use App\Models\ConfigurationModel;
|
||||
use RuntimeException;
|
||||
@@ -15,7 +15,7 @@ use App\Models\GradingLockModel;
|
||||
use App\Models\MissingScoreOverrideModel;
|
||||
|
||||
|
||||
class ProjectController extends Controller
|
||||
class ProjectController extends BaseController
|
||||
{
|
||||
protected $db;
|
||||
protected ConfigurationModel $configModel;
|
||||
@@ -42,16 +42,26 @@ class ProjectController extends Controller
|
||||
$studentModel = new StudentModel();
|
||||
$projectModel = new ProjectModel();
|
||||
|
||||
$teacherClass = $teacherClassModel->where('teacher_id', $updatedBy)->first();
|
||||
if (!$teacherClass) {
|
||||
return redirect()->back()->with('status', 'No class section found for the current teacher.');
|
||||
}
|
||||
|
||||
$classSectionId = $teacherClass['class_section_id'];
|
||||
session()->set('class_section_id', $classSectionId);
|
||||
|
||||
$semester = $this->getTeacherSelectedSemester();
|
||||
$schoolYear = $this->getTeacherSchoolYear();
|
||||
$classSectionId = (int) (
|
||||
$this->request->getGet('class_section_id')
|
||||
?? $this->request->getPost('class_section_id')
|
||||
?? 0
|
||||
);
|
||||
if ($classSectionId <= 0) {
|
||||
$teacherClass = $teacherClassModel
|
||||
->where('teacher_id', $updatedBy)
|
||||
->where('school_year', $schoolYear)
|
||||
->where('semester', $semester)
|
||||
->first();
|
||||
if (!$teacherClass) {
|
||||
return redirect()->back()->with('status', 'No class section found for the current teacher.');
|
||||
}
|
||||
$classSectionId = (int) $teacherClass['class_section_id'];
|
||||
}
|
||||
|
||||
session()->set('class_section_id', $classSectionId);
|
||||
|
||||
$projectRows = $projectModel
|
||||
->select('id, project_index')
|
||||
@@ -71,6 +81,7 @@ class ProjectController extends Controller
|
||||
$studentsClasses = $studentClassModel
|
||||
->active()
|
||||
->where('student_class.class_section_id', $classSectionId)
|
||||
->where('student_class.school_year', $schoolYear)
|
||||
->findAll();
|
||||
$students = [];
|
||||
|
||||
@@ -115,7 +126,7 @@ class ProjectController extends Controller
|
||||
]);
|
||||
}
|
||||
|
||||
public function updateProjectScores(array $scores = null, int $updatedBy = null, int $classSectionId = null)
|
||||
public function updateProjectScores(?array $scores = null, ?int $updatedBy = null, ?int $classSectionId = null)
|
||||
{
|
||||
$scores = $this->request->getPost('scores');
|
||||
$projectModel = new ProjectModel();
|
||||
@@ -127,6 +138,7 @@ class ProjectController extends Controller
|
||||
$classSectionId = session()->get('class_section_id');
|
||||
$semester = $this->getTeacherSelectedSemester();
|
||||
$schoolYear = $this->getTeacherSchoolYear();
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
$classSectionId = (int) ($classSectionId ?? 0);
|
||||
if ($classSectionId > 0 && $this->isScoresLocked($classSectionId, $semester, $schoolYear)) {
|
||||
return redirect()->back()->with('error', 'Scores are locked for this class. Unlock to edit.');
|
||||
@@ -190,7 +202,8 @@ class ProjectController extends Controller
|
||||
'student_id' => $studentId,
|
||||
'project_index' => $index,
|
||||
'class_section_id' => $classSectionId,
|
||||
'semester' => $semester
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
])->first();
|
||||
|
||||
$data = [
|
||||
@@ -231,6 +244,7 @@ class ProjectController extends Controller
|
||||
$classSectionId = session()->get('class_section_id');
|
||||
$semester = $this->getTeacherSelectedSemester();
|
||||
$schoolYear = $this->getTeacherSchoolYear();
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
|
||||
$projectModel = new ProjectModel();
|
||||
$studentClassModel = new StudentClassModel();
|
||||
@@ -257,6 +271,7 @@ class ProjectController extends Controller
|
||||
$students = $studentClassModel
|
||||
->active()
|
||||
->where('student_class.class_section_id', $classSectionId)
|
||||
->where('student_class.school_year', $schoolYear)
|
||||
->findAll();
|
||||
|
||||
foreach ($students as $student) {
|
||||
@@ -533,6 +548,6 @@ class ProjectController extends Controller
|
||||
|
||||
private function getTeacherSchoolYear(): string
|
||||
{
|
||||
return (string) $this->schoolYear;
|
||||
return $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Controllers\View;
|
||||
|
||||
use CodeIgniter\Controller;
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\TeacherClassModel;
|
||||
use App\Models\StudentClassModel;
|
||||
use App\Models\StudentModel;
|
||||
@@ -17,7 +17,7 @@ use Config\Services;
|
||||
use App\Models\GradingLockModel;
|
||||
use App\Models\MissingScoreOverrideModel;
|
||||
|
||||
class QuizController extends Controller
|
||||
class QuizController extends BaseController
|
||||
{
|
||||
protected $db;
|
||||
protected $semesterScoreService;
|
||||
@@ -50,7 +50,7 @@ class QuizController extends Controller
|
||||
$this->missingScoreOverrideModel = new MissingScoreOverrideModel();
|
||||
}
|
||||
|
||||
public function updateQuizScores(array $scores = null, int $updatedBy = null, int $classSectionId = null)
|
||||
public function updateQuizScores(?array $scores = null, ?int $updatedBy = null, ?int $classSectionId = null)
|
||||
{
|
||||
$scores = $this->request->getPost('scores');
|
||||
log_message('error', '✅ Raw Scores: ' . print_r($scores, true));
|
||||
@@ -60,7 +60,8 @@ class QuizController extends Controller
|
||||
}
|
||||
$classSectionId = $this->request->getPost('class_section_id') ?? session()->get('class_section_id');
|
||||
$semester = $this->request->getPost('semester') ?? $this->getTeacherSelectedSemester();
|
||||
$schoolYear = $this->request->getPost('school_year') ?? $this->schoolYear;
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
$classSectionId = (int) ($classSectionId ?? 0);
|
||||
if ($classSectionId > 0 && $this->isScoresLocked($classSectionId, $semester, $schoolYear)) {
|
||||
return redirect()->back()->with('error', 'Scores are locked for this class. Unlock to edit.');
|
||||
@@ -206,7 +207,7 @@ class QuizController extends Controller
|
||||
|
||||
// 3) Headers: distinct quiz_index for this class/term
|
||||
$semester = $this->getTeacherSelectedSemester();
|
||||
$schoolYear = $this->schoolYear;
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
$quizHeaderRows = $this->quizModel->select('quiz_index')
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('school_year', $schoolYear)
|
||||
@@ -272,9 +273,9 @@ class QuizController extends Controller
|
||||
'students' => $students,
|
||||
'quizHeaders' => $quizHeaders, // e.g., [1,2,3]
|
||||
'semester' => $semester,
|
||||
'schoolYear' => $this->schoolYear,
|
||||
'schoolYear' => $schoolYear,
|
||||
'classSectionId' => $classSectionId,
|
||||
'missingOkMap' => $this->missingScoreOverrideModel->getOverridesMap($classSectionId, $semester, $this->schoolYear, 'quiz'),
|
||||
'missingOkMap' => $this->missingScoreOverrideModel->getOverridesMap($classSectionId, $semester, $schoolYear, 'quiz'),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -294,7 +295,8 @@ class QuizController extends Controller
|
||||
try {
|
||||
|
||||
$semester = $this->getTeacherSelectedSemester();
|
||||
$schoolYear = $this->schoolYear;
|
||||
$schoolYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
$this->assertSchoolYearWritable($this->resolveSchoolYearContext());
|
||||
$existingQuizNumbers = $this->quizModel
|
||||
->select('quiz_index')
|
||||
->where('class_section_id', $classSectionId)
|
||||
@@ -323,6 +325,7 @@ class QuizController extends Controller
|
||||
|
||||
$students = $this->studentClassModel
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('school_year', $schoolYear)
|
||||
->findAll();
|
||||
|
||||
if (empty($students)) {
|
||||
@@ -341,8 +344,8 @@ class QuizController extends Controller
|
||||
'quiz_index' => $nextQuizNumber,
|
||||
'class_section_id' => $classSectionId,
|
||||
'updated_by' => $updatedBy,
|
||||
'semester' => $this->semester,
|
||||
'school_year' => $this->schoolYear,
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
])
|
||||
->first();
|
||||
|
||||
|
||||
@@ -46,9 +46,11 @@ class ScoreCommentController extends BaseController
|
||||
|
||||
public function saveComments()
|
||||
{
|
||||
$schoolYearContext = $this->resolveSchoolYearContext();
|
||||
$this->assertSchoolYearWritable($schoolYearContext);
|
||||
$comments = $this->request->getPost('comments');
|
||||
$classSectionId = (int)($this->request->getPost('class_section_id') ?? session()->get('class_section_id') ?? 0);
|
||||
$schoolYear = (string) ($this->request->getPost('school_year') ?? $this->schoolYear);
|
||||
$schoolYear = $schoolYearContext->yearName();
|
||||
$rawSelectedSemester = $this->request->getPost('selected_semester');
|
||||
$normalizedSelected = $this->normalizeSemesterSelection($rawSelectedSemester);
|
||||
if ($normalizedSelected !== '') {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Controllers\View;
|
||||
|
||||
use CodeIgniter\Controller;
|
||||
use App\Controllers\BaseController;
|
||||
use App\Models\TeacherClassModel;
|
||||
use App\Models\StudentClassModel;
|
||||
use App\Models\StudentModel;
|
||||
@@ -28,7 +28,7 @@ use App\Models\MissingScoreOverrideModel;
|
||||
|
||||
|
||||
|
||||
class ScoreController extends Controller
|
||||
class ScoreController extends BaseController
|
||||
{
|
||||
protected $semesterScoreService;
|
||||
protected $db;
|
||||
@@ -88,6 +88,8 @@ class ScoreController extends Controller
|
||||
public function index()
|
||||
{
|
||||
log_message('debug', 'ScoreController::index invoked');
|
||||
$schoolYearContext = $this->resolveSchoolYearContext();
|
||||
$this->schoolYear = $schoolYearContext->yearName();
|
||||
$semesterChoiceParam = $this->request->getGet('semester_choice');
|
||||
$session = session();
|
||||
if ($this->request->getGet('choose_semester') !== null) {
|
||||
@@ -139,25 +141,13 @@ class ScoreController extends Controller
|
||||
);
|
||||
|
||||
if (empty($assignments)) {
|
||||
// Fallback: any class regardless of term
|
||||
$fallback = $this->teacherClassModel
|
||||
->where('teacher_id', $teacherId)
|
||||
->first();
|
||||
if ($fallback) {
|
||||
$assignments = [[
|
||||
'class_section_id' => $fallback['class_section_id'],
|
||||
'class_section_name' => null,
|
||||
'school_year' => $fallback['school_year'] ?? $effectiveSchoolYear,
|
||||
'semester' => $fallback['semester'] ?? $effectiveSemester,
|
||||
]];
|
||||
$effectiveSemester = $fallback['semester'] ?? $effectiveSemester;
|
||||
$effectiveSchoolYear = $fallback['school_year'] ?? $effectiveSchoolYear;
|
||||
} else {
|
||||
log_message('info', 'No class section assigned to teacher ID: ' . $teacherId);
|
||||
return redirect()
|
||||
->to('no-classes')
|
||||
->with('message', 'You do not have an assigned class yet. Please contact the administration.');
|
||||
}
|
||||
log_message(
|
||||
'info',
|
||||
"No {$effectiveSchoolYear} {$effectiveSemester} class section assigned to teacher ID: {$teacherId}"
|
||||
);
|
||||
return redirect()
|
||||
->to('no-classes')
|
||||
->with('message', 'You do not have an assigned class for the selected school year and semester. Please contact the administration.');
|
||||
}
|
||||
|
||||
$allowedIds = array_map(static fn($a) => (int)($a['class_section_id'] ?? 0), $assignments);
|
||||
@@ -222,6 +212,7 @@ class ScoreController extends Controller
|
||||
$csRow = $this->db->table('classSection')
|
||||
->select('class_section_name')
|
||||
->where('class_section_id', $classSectionId)
|
||||
->where('school_year', $effectiveSchoolYear)
|
||||
->get()->getRowArray();
|
||||
$classSectionName = $csRow['class_section_name'] ?? '';
|
||||
log_message('debug', "ScoreController::index teacher {$teacherId} classSection {$classSectionId} semester {$effectiveSemester}");
|
||||
@@ -281,6 +272,7 @@ class ScoreController extends Controller
|
||||
'focusTarget' => $focusTarget,
|
||||
'schoolYear' => $effectiveSchoolYear,
|
||||
'scoresLocked' => $scoresLocked,
|
||||
'isSchoolYearReadonly' => $schoolYearContext->isReadonly(),
|
||||
];
|
||||
|
||||
return view('/teacher/scores', $data);
|
||||
@@ -288,11 +280,13 @@ class ScoreController extends Controller
|
||||
|
||||
public function submitScoresLock()
|
||||
{
|
||||
$schoolYearContext = $this->resolveSchoolYearContext();
|
||||
$this->assertSchoolYearWritable($schoolYearContext);
|
||||
$classSectionId = (int) ($this->request->getPost('class_section_id') ?? session()->get('class_section_id') ?? 0);
|
||||
$semesterRaw = (string) ($this->request->getPost('semester') ?? $this->request->getPost('selected_semester') ?? '');
|
||||
$semesterNormalized = $this->normalizeSemester($semesterRaw);
|
||||
$semester = $semesterNormalized !== '' ? ucfirst($semesterNormalized) : $this->semester;
|
||||
$schoolYear = (string) ($this->request->getPost('school_year') ?? $this->schoolYear);
|
||||
$schoolYear = $schoolYearContext->yearName();
|
||||
|
||||
if ($classSectionId <= 0 || $semester === '' || $schoolYear === '') {
|
||||
return redirect()->back()->with('error', 'Missing class section or term.');
|
||||
@@ -496,6 +490,7 @@ class ScoreController extends Controller
|
||||
$studentClasses = $this->studentClassModel
|
||||
->active()
|
||||
->where('student_class.class_section_id', $classSectionId)
|
||||
->where('student_class.school_year', $schoolYear)
|
||||
->findAll();
|
||||
|
||||
foreach ($studentClasses as $studentClass) {
|
||||
@@ -1086,6 +1081,9 @@ class ScoreController extends Controller
|
||||
|
||||
public function updateScores(string $table, ?string $redirectUrl = null)
|
||||
{
|
||||
$schoolYearContext = $this->resolveSchoolYearContext();
|
||||
$this->assertSchoolYearWritable($schoolYearContext);
|
||||
$this->schoolYear = $schoolYearContext->yearName();
|
||||
$builder = $this->db->table($table);
|
||||
|
||||
$scores = $this->request->getPost('final_score'); // name must match input form
|
||||
@@ -1322,18 +1320,7 @@ public function viewStudentScore()
|
||||
return redirect()->back()->with('error', 'Unable to retrieve student data. Please contact support.');
|
||||
}
|
||||
|
||||
// Handle selected school year (parents can view scores for any available year)
|
||||
$selectedYear = $this->request->getVar('school_year') ?? $this->schoolYear;
|
||||
|
||||
// Fetch distinct school years only from semester_scores
|
||||
$query = $this->db->table('semester_scores')
|
||||
->select('school_year')
|
||||
->distinct()
|
||||
->get();
|
||||
|
||||
$schoolYears = array_column($query->getResultArray(), 'school_year');
|
||||
$schoolYears = array_unique($schoolYears);
|
||||
rsort($schoolYears);
|
||||
$selectedYear = $this->currentSchoolYearName((string) ($this->schoolYear ?? ''));
|
||||
|
||||
// Initialize scores array
|
||||
$scores = [];
|
||||
@@ -1402,7 +1389,6 @@ $students = $this->db->table('students')
|
||||
|
||||
return view('/parent/scores', [
|
||||
'organizedScores' => $scores,
|
||||
'schoolYears' => $schoolYears,
|
||||
'selectedYear' => $selectedYear,
|
||||
'semesterOrder' => ['Fall', 'Spring'],
|
||||
'showExamScores' => $releaseAny,
|
||||
|
||||
Reference in New Issue
Block a user