add controllers, servoices
This commit is contained in:
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Grading;
|
||||
|
||||
use App\Models\Configuration;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class HomeworkTrackingService
|
||||
{
|
||||
private array $teacherAssignmentCache = [];
|
||||
|
||||
public function __construct(private HomeworkTrackingCalendarService $calendarService)
|
||||
{
|
||||
}
|
||||
|
||||
public function report(?string $semester = null, ?string $schoolYear = null, int $page = 1): array
|
||||
{
|
||||
$semester = $semester ?: (string) (Configuration::getConfig('semester') ?? '');
|
||||
$schoolYear = $schoolYear ?: (string) (Configuration::getConfig('school_year') ?? '');
|
||||
|
||||
[$start, $end] = $this->calendarService->buildDateRange($schoolYear, $semester);
|
||||
$sundays = $this->calendarService->buildSundays($start, $end);
|
||||
$eventDays = $this->calendarService->eventDays($schoolYear);
|
||||
$dateToIndex = $this->calendarService->dateToIndex($sundays, $eventDays);
|
||||
|
||||
$limitToSemester = $this->hasTeacherAssignments($schoolYear);
|
||||
|
||||
$homeworkByIndex = $this->loadHomeworkByIndex($schoolYear, $semester, $limitToSemester);
|
||||
$homeworkByDate = $this->loadHomeworkByDate($schoolYear, $semester, $limitToSemester, $sundays, $eventDays);
|
||||
$teachers = $this->loadTeachers($schoolYear);
|
||||
|
||||
$perPage = 8;
|
||||
$totalRows = count($teachers);
|
||||
$totalPages = max(1, (int) ceil($totalRows / $perPage));
|
||||
$page = max(1, min($page, $totalPages));
|
||||
$offset = ($page - 1) * $perPage;
|
||||
$teachersPage = array_slice($teachers, $offset, $perPage);
|
||||
|
||||
return [
|
||||
'semester' => $semester,
|
||||
'school_year' => $schoolYear,
|
||||
'sundays' => $sundays,
|
||||
'event_days' => $eventDays,
|
||||
'date_to_index' => $dateToIndex,
|
||||
'teachers' => $teachersPage,
|
||||
'has_homework' => $homeworkByIndex['has_homework'],
|
||||
'hw_entered_at' => $homeworkByIndex['entered_at'],
|
||||
'has_homework_by_date' => $homeworkByDate['has_homework'],
|
||||
'hw_entered_at_by_date' => $homeworkByDate['entered_at'],
|
||||
'page' => $page,
|
||||
'total_pages' => $totalPages,
|
||||
'per_page' => $perPage,
|
||||
'total_rows' => $totalRows,
|
||||
];
|
||||
}
|
||||
|
||||
private function hasTeacherAssignments(string $schoolYear): bool
|
||||
{
|
||||
$year = trim((string) $schoolYear);
|
||||
if ($year === '') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (array_key_exists($year, $this->teacherAssignmentCache)) {
|
||||
return $this->teacherAssignmentCache[$year];
|
||||
}
|
||||
|
||||
$cnt = DB::table('teacher_class')->where('school_year', $year)->count();
|
||||
$this->teacherAssignmentCache[$year] = $cnt > 0;
|
||||
|
||||
return $this->teacherAssignmentCache[$year];
|
||||
}
|
||||
|
||||
private function loadHomeworkByIndex(string $schoolYear, string $semester, bool $limitToSemester): array
|
||||
{
|
||||
$query = DB::table('homework')
|
||||
->select('class_section_id', 'homework_index', DB::raw('MIN(created_at) as first_created'), DB::raw('COUNT(*) as cnt'))
|
||||
->where('school_year', $schoolYear);
|
||||
|
||||
if ($limitToSemester && $semester !== '') {
|
||||
$query->where('semester', $semester);
|
||||
}
|
||||
|
||||
$rows = $query->groupBy('class_section_id', 'homework_index')->get();
|
||||
|
||||
$hasHomework = [];
|
||||
$enteredAt = [];
|
||||
foreach ($rows as $row) {
|
||||
$csid = (int) $row->class_section_id;
|
||||
$hi = (int) $row->homework_index;
|
||||
$cnt = (int) $row->cnt;
|
||||
if ($csid > 0 && $hi > 0 && $cnt > 0) {
|
||||
$hasHomework[$csid][$hi] = true;
|
||||
$dateStr = substr((string) ($row->first_created ?? ''), 0, 10);
|
||||
$enteredAt[$csid][$hi] = $dateStr ?: null;
|
||||
}
|
||||
}
|
||||
|
||||
return ['has_homework' => $hasHomework, 'entered_at' => $enteredAt];
|
||||
}
|
||||
|
||||
private function loadHomeworkByDate(string $schoolYear, string $semester, bool $limitToSemester, array $sundays, array $eventDays): array
|
||||
{
|
||||
$query = DB::table('homework')
|
||||
->select(DB::raw('class_section_id, DATE(created_at) as hw_date, MIN(created_at) as first_created, COUNT(*) as cnt'))
|
||||
->where('school_year', $schoolYear);
|
||||
|
||||
if ($limitToSemester && $semester !== '') {
|
||||
$query->where('semester', $semester);
|
||||
}
|
||||
|
||||
$rows = $query
|
||||
->groupBy('class_section_id', DB::raw('DATE(created_at)'))
|
||||
->orderBy('hw_date', 'ASC')
|
||||
->get();
|
||||
|
||||
$hasHomework = [];
|
||||
$enteredAt = [];
|
||||
|
||||
foreach ($rows as $row) {
|
||||
$csid = (int) $row->class_section_id;
|
||||
$date = substr((string) ($row->hw_date ?? ''), 0, 10);
|
||||
$cnt = (int) $row->cnt;
|
||||
$firstCreated = substr((string) ($row->first_created ?? ''), 0, 10);
|
||||
if ($csid <= 0 || !$date || $cnt <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$baseIndex = -1;
|
||||
for ($i = count($sundays) - 1; $i >= 0; $i--) {
|
||||
if ($sundays[$i] <= $date) {
|
||||
$baseIndex = $i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ($baseIndex < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$j = $baseIndex;
|
||||
while ($j >= 0 && !empty($eventDays[$sundays[$j]])) {
|
||||
$j--;
|
||||
}
|
||||
if ($j < 0) {
|
||||
continue;
|
||||
}
|
||||
$sunday = $sundays[$j];
|
||||
|
||||
$hasHomework[$csid][$sunday] = true;
|
||||
$candidate = $firstCreated ?: $date;
|
||||
if (empty($enteredAt[$csid][$sunday]) || ($candidate && $candidate < $enteredAt[$csid][$sunday])) {
|
||||
$enteredAt[$csid][$sunday] = $candidate;
|
||||
}
|
||||
}
|
||||
|
||||
return ['has_homework' => $hasHomework, 'entered_at' => $enteredAt];
|
||||
}
|
||||
|
||||
private function loadTeachers(string $schoolYear): array
|
||||
{
|
||||
$rows = DB::table('teacher_class as tc')
|
||||
->select('tc.class_section_id', 'tc.position', 'cs.class_section_name', 'cs.class_id', 'u.firstname', 'u.lastname')
|
||||
->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'tc.class_section_id')
|
||||
->leftJoin('users as u', 'u.id', '=', 'tc.teacher_id')
|
||||
->where('tc.school_year', $schoolYear)
|
||||
->whereNotNull('tc.class_section_id')
|
||||
->whereIn('tc.position', ['main', 'ta'])
|
||||
->orderBy('cs.class_id', 'ASC')
|
||||
->orderBy('cs.class_section_name', 'ASC')
|
||||
->orderByRaw("FIELD(tc.position, 'main','ta')")
|
||||
->orderBy('u.firstname', 'ASC')
|
||||
->get();
|
||||
|
||||
$bySection = [];
|
||||
foreach ($rows as $row) {
|
||||
$sid = (int) $row->class_section_id;
|
||||
if ($sid <= 0) {
|
||||
continue;
|
||||
}
|
||||
if (!isset($bySection[$sid])) {
|
||||
$bySection[$sid] = [
|
||||
'class_section_id' => $sid,
|
||||
'class_id' => (int) ($row->class_id ?? 0),
|
||||
'class_section_name' => (string) ($row->class_section_name ?? ''),
|
||||
'teachers' => [],
|
||||
'tas' => [],
|
||||
];
|
||||
}
|
||||
$name = trim((string) ($row->firstname ?? '') . ' ' . (string) ($row->lastname ?? ''));
|
||||
$pos = strtolower((string) ($row->position ?? ''));
|
||||
if ($name !== '') {
|
||||
if ($pos === 'main') {
|
||||
$bySection[$sid]['teachers'][] = $name;
|
||||
} elseif ($pos === 'ta') {
|
||||
$bySection[$sid]['tas'][] = $name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$teachers = array_values($bySection);
|
||||
usort($teachers, function ($a, $b) {
|
||||
$ai = (int) ($a['class_id'] ?? 0);
|
||||
$bi = (int) ($b['class_id'] ?? 0);
|
||||
$order = function (int $cid): int {
|
||||
if ($cid === 13) return 0;
|
||||
if ($cid >= 1 && $cid <= 11) return $cid;
|
||||
if ($cid === 12) return 99;
|
||||
return 200 + $cid;
|
||||
};
|
||||
$cmp = $order($ai) <=> $order($bi);
|
||||
if ($cmp !== 0) {
|
||||
return $cmp;
|
||||
}
|
||||
return strnatcasecmp($a['class_section_name'] ?? '', $b['class_section_name'] ?? '');
|
||||
});
|
||||
|
||||
return $teachers;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user