> */ public function parentStudents(int $parentId): array { if ($parentId <= 0) { return []; } $rows = DB::table('enrollments as e') ->select( 'e.student_id', 'e.class_section_id', 'e.updated_at', 'e.created_at', 's.firstname', 's.lastname', 'cs.class_section_name', ) ->join('students as s', 's.id', '=', 'e.student_id') ->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'e.class_section_id') ->where('e.parent_id', $parentId) ->where('e.is_withdrawn', 0) ->orderByDesc('e.updated_at') ->orderByDesc('e.created_at') ->get(); $students = []; foreach ($rows as $row) { $arr = (array) $row; $studentId = (int) ($arr['student_id'] ?? 0); if ($studentId === 0 || isset($students[$studentId])) { continue; } $students[$studentId] = $arr; } return array_values($students); } /** * legacy `getParentSectionIds`. * * @return list */ public function parentSectionIds(int $parentId): array { if ($parentId <= 0) { return []; } $ids = DB::table('enrollments') ->where('parent_id', $parentId) ->where('is_withdrawn', 0) ->whereNotNull('class_section_id') ->distinct() ->pluck('class_section_id') ->map(fn ($id) => (int) $id) ->filter(fn ($id) => $id > 0) ->unique() ->values() ->all(); return array_values($ids); } public function parentCanAccessSection(int $parentUserId, ?int $classSectionId): bool { if (! $classSectionId) { return false; } return in_array((int) $classSectionId, $this->parentSectionIds($parentUserId), true); } /** * Progress reports visible to the parent (all teachers) for allowed sections. * * @param list $sectionIds */ public function reportsForSections(array $sectionIds): Collection { $sectionIds = array_values(array_filter(array_map('intval', $sectionIds))); if ($sectionIds === []) { return collect(); } return ClassProgressReport::query() ->select('class_progress_reports.*') ->addSelect([ 'cs.class_section_name', DB::raw('CONCAT(IFNULL(u.firstname, ""), " ", IFNULL(u.lastname, "")) AS teacher_name'), ]) ->leftJoin('classSection as cs', 'cs.class_section_id', '=', 'class_progress_reports.class_section_id') ->leftJoin('users as u', 'u.id', '=', 'class_progress_reports.teacher_id') ->whereIn('class_progress_reports.class_section_id', $sectionIds) ->orderByDesc('class_progress_reports.week_start') ->get(); } /** * legacy `groupReportsByWeek` — keys `"{week_start}:{class_section_id}"`. * * @param iterable $rows * @return array> */ public function groupReportsByWeek(iterable $rows): array { $statusOptions = (array) config('progress.status_options', []); $reportGroups = []; foreach ($rows as $row) { $statusLabel = $statusOptions[$row->status] ?? 'Unknown'; $row->setAttribute('status_label', $statusLabel); $weekStart = $row->week_start instanceof CarbonInterface ? $row->week_start->format('Y-m-d') : (string) $row->week_start; $sectionId = (int) $row->class_section_id; if ($weekStart === '' || $sectionId === 0) { continue; } $key = $weekStart.':'.$sectionId; if (! isset($reportGroups[$key])) { $reportGroups[$key] = [ 'week_start' => $weekStart, 'week_end' => $row->week_end instanceof CarbonInterface ? $row->week_end->format('Y-m-d') : (string) ($row->week_end ?? ''), 'class_section_name' => $row->class_section_name ?? '', 'class_section_id' => $sectionId, 'reports' => [], ]; } $subject = (string) ($row->subject ?? ''); if ($subject === '') { continue; } $reportGroups[$key]['reports'][$subject] = (new ClassProgressReportResource($row))->toArray(request()); } return $reportGroups; } /** * Weekly batch for a section/week (legacy parent `view`, all subjects). * * @return list */ public function weeklyReportsForSectionWeek(int $classSectionId, string $weekStartYmd): array { return ClassProgressReport::query() ->with(['classSection', 'teacher']) ->where('class_section_id', $classSectionId) ->whereDate('week_start', $weekStartYmd) ->orderBy('subject') ->get() ->all(); } /** * @return array> */ public function attachmentMapForReportIds(array $reportIds): array { return $this->classProgressQuery->attachmentMap($reportIds); } }