add grading, attendnace management
This commit is contained in:
@@ -515,43 +515,74 @@ class AttendanceQueryService
|
||||
continue;
|
||||
}
|
||||
|
||||
// Bulk-load student profiles for the whole section in one query
|
||||
$studentsArray = is_array($students) ? $students : $students->toArray();
|
||||
$studentIds = array_map(fn($sc) => (int)($sc['student_id'] ?? $sc->student_id ?? 0), $studentsArray);
|
||||
$studentProfiles = $this->student
|
||||
->query()
|
||||
->select(['id', 'firstname', 'lastname', 'school_id'])
|
||||
->whereIn('id', $studentIds)
|
||||
->where('is_active', 1)
|
||||
->get()
|
||||
->keyBy('id')
|
||||
->map(fn($row) => $row->toArray())
|
||||
->all();
|
||||
|
||||
$activeIds = array_keys($studentProfiles);
|
||||
if (empty($activeIds)) {
|
||||
unset($studentsBySection[$secCode], $datesBySection[$secCode], $attendanceData[$secCode], $attendanceRecord[$secCode]);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Bulk-load all attendance entries for the section in one query
|
||||
$allEntries = AttendanceData::query()
|
||||
->whereIn('student_id', $activeIds)
|
||||
->where(function ($q) use ($secCode, $secPk) {
|
||||
$q->where('class_section_id', $secCode);
|
||||
if ($secPk && (string)$secPk !== (string)$secCode) {
|
||||
$q->orWhere('class_section_id', $secPk);
|
||||
}
|
||||
})
|
||||
->when($termSemester !== '', fn($q) => $q->where('semester', $termSemester))
|
||||
->when($effectiveTermYear !== '', fn($q) => $q->where('school_year', $effectiveTermYear))
|
||||
->orderBy('date')
|
||||
->get()
|
||||
->map(fn($row) => $row->toArray())
|
||||
->groupBy('student_id')
|
||||
->map(fn($group) => $group->values()->all())
|
||||
->all();
|
||||
|
||||
// Bulk-load all attendance records (summaries) for the section in one query
|
||||
$allRecords = AttendanceRecord::query()
|
||||
->whereIn('student_id', $activeIds)
|
||||
->where(function ($q) use ($secCode, $secPk) {
|
||||
$q->where('class_section_id', $secCode);
|
||||
if ($secPk && (string)$secPk !== (string)$secCode) {
|
||||
$q->orWhere('class_section_id', $secPk);
|
||||
}
|
||||
})
|
||||
->when($termSemester !== '', fn($q) => $q->where('semester', $termSemester))
|
||||
->when($effectiveTermYear !== '', fn($q) => $q->where('school_year', $effectiveTermYear))
|
||||
->get()
|
||||
->keyBy('student_id')
|
||||
->map(fn($row) => $row->toArray())
|
||||
->all();
|
||||
|
||||
$hasRoster = false;
|
||||
|
||||
foreach ($students as $sc) {
|
||||
$studentId = (int)$sc['student_id'];
|
||||
|
||||
$student = $this->student
|
||||
->query()
|
||||
->select(['id', 'firstname', 'lastname', 'school_id'])
|
||||
->where('id', $studentId)
|
||||
->where('is_active', 1)
|
||||
->first();
|
||||
|
||||
foreach ($studentIds as $studentId) {
|
||||
$student = $studentProfiles[$studentId] ?? null;
|
||||
if (!$student) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$student = $student->toArray();
|
||||
$studentsBySection[$secCode][] = $student;
|
||||
$studentSchoolMap[$studentId] = (string)($student['school_id'] ?? '');
|
||||
$hasRoster = true;
|
||||
|
||||
$entries = AttendanceData::query()
|
||||
->where('student_id', $studentId)
|
||||
->where(function ($q) use ($secCode, $secPk) {
|
||||
$q->where('class_section_id', $secCode);
|
||||
if ($secPk && (string)$secPk !== (string)$secCode) {
|
||||
$q->orWhere('class_section_id', $secPk);
|
||||
}
|
||||
})
|
||||
->when($termSemester !== '', fn($q) => $q->where('semester', $termSemester))
|
||||
->when($effectiveTermYear !== '', fn($q) => $q->where('school_year', $effectiveTermYear))
|
||||
->orderBy('date')
|
||||
->get()
|
||||
->map(fn($row) => $row->toArray())
|
||||
->all();
|
||||
|
||||
$entries = $this->attendanceService->normalizeAttendanceEntries($entries);
|
||||
$entries = $this->attendanceService->normalizeAttendanceEntries(
|
||||
array_map(fn($r) => (array)$r, $allEntries[$studentId] ?? [])
|
||||
);
|
||||
$attendanceData[$secCode][$studentId] = $entries;
|
||||
|
||||
foreach ($entries as $entry) {
|
||||
@@ -561,19 +592,7 @@ class AttendanceQueryService
|
||||
}
|
||||
}
|
||||
|
||||
$summary = AttendanceRecord::query()
|
||||
->where('student_id', $studentId)
|
||||
->where(function ($q) use ($secCode, $secPk) {
|
||||
$q->where('class_section_id', $secCode);
|
||||
if ($secPk && (string)$secPk !== (string)$secCode) {
|
||||
$q->orWhere('class_section_id', $secPk);
|
||||
}
|
||||
})
|
||||
->when($termSemester !== '', fn($q) => $q->where('semester', $termSemester))
|
||||
->when($effectiveTermYear !== '', fn($q) => $q->where('school_year', $effectiveTermYear))
|
||||
->first();
|
||||
|
||||
$attendanceRecord[$secCode][$studentId] = $summary?->toArray() ?? [
|
||||
$attendanceRecord[$secCode][$studentId] = $allRecords[$studentId] ?? [
|
||||
'total_presence' => 0,
|
||||
'total_late' => 0,
|
||||
'total_absence' => 0,
|
||||
@@ -627,7 +646,7 @@ class AttendanceQueryService
|
||||
foreach ($events as $event) {
|
||||
$d = substr((string)($event['date'] ?? ''), 0, 10);
|
||||
if ($d !== '') {
|
||||
$noSchoolDays[$d] = true;
|
||||
$noSchoolDays[$d] = trim((string)($event['title'] ?? 'No School')) ?: 'No School';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Services\Attendance;
|
||||
|
||||
use App\Models\Configuration;
|
||||
use Carbon\Carbon;
|
||||
|
||||
class SemesterRangeService
|
||||
@@ -19,6 +20,16 @@ class SemesterRangeService
|
||||
|
||||
public function getSchoolYearRange(string $schoolYear): array
|
||||
{
|
||||
$fallStart = Configuration::getConfig('fall_semester_start');
|
||||
$lastDay = Configuration::getConfig('last_school_day');
|
||||
|
||||
if ($fallStart && $lastDay) {
|
||||
return [
|
||||
Carbon::parse($fallStart)->toDateString(),
|
||||
Carbon::parse($lastDay)->toDateString(),
|
||||
];
|
||||
}
|
||||
|
||||
[$startYear, $endYear] = $this->parseSchoolYear($schoolYear);
|
||||
|
||||
return [
|
||||
@@ -29,9 +40,29 @@ class SemesterRangeService
|
||||
|
||||
public function getSemesterRange(string $schoolYear, string $semester): ?array
|
||||
{
|
||||
[$startYear, $endYear] = $this->parseSchoolYear($schoolYear);
|
||||
$semester = $this->normalizeSemester($semester);
|
||||
|
||||
$fallStart = Configuration::getConfig('fall_semester_start');
|
||||
$springStart = Configuration::getConfig('spring_semester_start');
|
||||
$lastDay = Configuration::getConfig('last_school_day');
|
||||
|
||||
if ($semester === 'Fall' && $fallStart && $springStart) {
|
||||
return [
|
||||
Carbon::parse($fallStart)->toDateString(),
|
||||
Carbon::parse($springStart)->subDay()->toDateString(),
|
||||
];
|
||||
}
|
||||
|
||||
if ($semester === 'Spring' && $springStart && $lastDay) {
|
||||
return [
|
||||
Carbon::parse($springStart)->toDateString(),
|
||||
Carbon::parse($lastDay)->toDateString(),
|
||||
];
|
||||
}
|
||||
|
||||
// Fallback to hardcoded logic when config keys are missing
|
||||
[$startYear, $endYear] = $this->parseSchoolYear($schoolYear);
|
||||
|
||||
return match ($semester) {
|
||||
'Fall' => [
|
||||
Carbon::create($startYear, 9, 21)->toDateString(),
|
||||
|
||||
Reference in New Issue
Block a user