update code

This commit is contained in:
root
2026-02-26 23:27:50 -05:00
parent 663c0cdbda
commit a6880ea14f
10 changed files with 807 additions and 138 deletions
@@ -71,12 +71,15 @@ class ParentAttendanceReportController extends BaseController
->orderBy('s.lastname', 'ASC')
->get()->getResultArray();
$cutoffThreshold = $this->normalizeCutoffTime((string) $this->configModel->getConfig('parent_report_cutoff'));
return view('parent/report_attendance', [
'students' => $students,
'today' => local_date(utc_now(), 'Y-m-d'),
'sundays' => $sundays, // array of ['value'=>Y-m-d, 'label'=>...] items
'defaultDate' => $defaultDate, // preselected date (upcoming Sunday)
'myReports' => $previewRows,
'cutoffThreshold' => $cutoffThreshold,
]);
}
@@ -141,6 +144,17 @@ class ParentAttendanceReportController extends BaseController
// Enforce Sunday-only and future-or-today selection
$todayCheck = new \DateTime('today');
$cutoffThreshold = $this->normalizeCutoffTime((string) $this->configModel->getConfig('parent_report_cutoff'));
$tzName = (string) (config('School')->attendance['timezone'] ?? user_timezone());
$tz = null;
$nowTz = null;
try {
$tz = new \DateTimeZone($tzName ?: 'UTC');
$nowTz = new \DateTime('now', $tz);
} catch (\Throwable $e) {
$tz = null;
$nowTz = null;
}
$validDates = [];
$cap = $this->firstSundayOfJune((string) $this->configModel->getConfig('school_year'));
@@ -150,9 +164,11 @@ class ParentAttendanceReportController extends BaseController
$lateTodayStr = $todayCheck->format('Y-m-d');
if ($type === 'late') {
try {
$tzName = (string) (config('School')->attendance['timezone'] ?? user_timezone());
$tz = new \DateTimeZone($tzName ?: 'UTC');
$lateNow = new \DateTime('now', $tz);
if (!$tz) {
$tzName = (string) (config('School')->attendance['timezone'] ?? user_timezone());
$tz = new \DateTimeZone($tzName ?: 'UTC');
}
$lateNow = $nowTz ?: new \DateTime('now', $tz);
$cm = $this->configModel;
$cutoffStr = (string) ($cm->getConfig('late_report_cutoff')
?: $cm->getConfig('late_cutoff_time')
@@ -183,6 +199,17 @@ class ParentAttendanceReportController extends BaseController
if ($dt < $todayCheck) {
return redirect()->back()->withInput()->with('error', 'Past dates are not allowed. Please select today or a future Sunday.');
}
if ($nowTz && $tz) {
try {
$cutoff = new \DateTime($entry . ' ' . $cutoffThreshold . ':00', $tz);
if ($nowTz >= $cutoff) {
$abbr = $cutoff->format('T');
return redirect()->back()->withInput()->with('error', 'Reporting closes at ' . $cutoffThreshold . ' ' . $abbr . ' on the report date.');
}
} catch (\Throwable $e) {
// ignore and continue
}
}
if ($dt > $cap) {
return redirect()->back()->withInput()->with('error', 'The last available date is the first Sunday of June.');
}
@@ -800,6 +827,36 @@ class ParentAttendanceReportController extends BaseController
$update['reported'] = 1;
}
$this->attendanceDataModel->update((int) $existing['id'], $update);
return;
}
if ($existingStatus === '' || $existingStatus === 'present') {
$update = [
'status' => $status,
'reason' => $existing['reason'] ?: $reasonText,
'updated_at' => utc_now(),
];
if ($hasIsReported) {
$update['is_reported'] = 'yes';
}
if ($hasLegacyReported) {
$update['reported'] = 1;
}
$this->attendanceDataModel->update((int) $existing['id'], $update);
$classSectionId = (int) ($existing['class_section_id'] ?? $classSectionId ?? 0);
$schoolId = (string) ($existing['school_id'] ?? '');
if ($classSectionId > 0 && $schoolId !== '') {
$this->adjustAttendanceRecordForStatusChange(
studentId: $studentId,
classSectionId: $classSectionId,
schoolId: $schoolId,
semester: $semester,
schoolYear: $schoolYear,
oldStatus: $existingStatus,
newStatus: $status
);
}
}
}
@@ -856,6 +913,61 @@ class ParentAttendanceReportController extends BaseController
$this->attendanceRecordModel->insert($insert);
}
private function adjustAttendanceRecordForStatusChange(
int $studentId,
int $classSectionId,
string $schoolId,
string $semester,
string $schoolYear,
string $oldStatus,
string $newStatus
): void {
$oldStatus = strtolower($oldStatus);
$newStatus = strtolower($newStatus);
if ($oldStatus === $newStatus) {
return;
}
$record = $this->attendanceRecordModel->where([
'student_id' => $studentId,
'semester' => $semester,
'school_year' => $schoolYear,
])->first();
if (!$record) {
$this->bumpAttendanceRecordFromParent($studentId, $classSectionId, $schoolId, $newStatus, $semester, $schoolYear);
return;
}
$updates = [
'total_presence' => (int) ($record['total_presence'] ?? 0),
'total_absence' => (int) ($record['total_absence'] ?? 0),
'total_late' => (int) ($record['total_late'] ?? 0),
'total_attendance' => (int) ($record['total_attendance'] ?? 0),
'updated_at' => utc_now(),
'modified_by' => (int) (session()->get('user_id') ?? 0),
];
if ($oldStatus === 'present') {
$updates['total_presence'] = max(0, $updates['total_presence'] - 1);
} elseif ($oldStatus === 'absent') {
$updates['total_absence'] = max(0, $updates['total_absence'] - 1);
} elseif ($oldStatus === 'late') {
$updates['total_late'] = max(0, $updates['total_late'] - 1);
}
if ($newStatus === 'present') {
$updates['total_presence']++;
} elseif ($newStatus === 'absent') {
$updates['total_absence']++;
} elseif ($newStatus === 'late') {
$updates['total_late']++;
}
$this->attendanceRecordModel->update((int) $record['id'], $updates);
}
// GET: staff view to list reports (today & upcoming by default)
public function list()
{
@@ -1503,6 +1615,20 @@ class ParentAttendanceReportController extends BaseController
return $userId; // fallback
}
private function normalizeCutoffTime(string $raw, string $default = '09:00'): string
{
$raw = trim($raw);
if ($raw === '') {
return $default;
}
if (preg_match('/^(\d{1,2}):(\d{2})$/', $raw, $m)) {
$hh = str_pad((string) ((int) $m[1]), 2, '0', STR_PAD_LEFT);
$mm = $m[2];
return $hh . ':' . $mm;
}
return $default;
}
/**
* Send confirmation/notification emails for parent attendance submissions.
*/