get('search')); $academicYearId = $request->get('academic_year_id'); $classId = $request->get('class_id'); $status = $request->get('status'); $students = Student::query() ->with(['academicYear', 'classRoom', 'department']) ->when($search !== '', function ($query) use ($search) { $query->where(function ($subQuery) use ($search) { $subQuery->where('full_name', 'like', "%{$search}%") ->orWhere('student_number', 'like', "%{$search}%") ->orWhere('nisn', 'like', "%{$search}%"); }); }) ->when($academicYearId, fn ($query) => $query->where('academic_year_id', $academicYearId)) ->when($classId, fn ($query) => $query->where('class_id', $classId)) ->when($status, fn ($query) => $query->where('self_service_status', $status)) ->latest() ->paginate(15) ->withQueryString(); $summaryBaseQuery = Student::query(); $statusLabels = [ 'not_started' => 'Belum Mulai', 'draft' => 'Draft', 'submitted' => 'Sudah Dikirim', ]; return view('student-self-service.index', [ 'students' => $students, 'search' => $search, 'filters' => [ 'academic_year_id' => $academicYearId, 'class_id' => $classId, 'status' => $status, ], 'academicYears' => AcademicYear::orderBy('name')->pluck('name', 'id'), 'classes' => SchoolClass::orderBy('name')->pluck('name', 'id'), 'statuses' => $statusLabels, 'summary' => [ 'total' => (clone $summaryBaseQuery)->count(), 'not_started' => (clone $summaryBaseQuery)->where('self_service_status', 'not_started')->count(), 'draft' => (clone $summaryBaseQuery)->where('self_service_status', 'draft')->count(), 'submitted' => (clone $summaryBaseQuery)->where('self_service_status', 'submitted')->count(), 'with_code' => (clone $summaryBaseQuery)->whereNotNull('self_service_access_code')->count(), 'without_code' => (clone $summaryBaseQuery)->whereNull('self_service_access_code')->count(), ], ]); } public function generateMissingCodes(): RedirectResponse { $students = Student::query()->whereNull('self_service_access_code')->get(); if ($students->isEmpty()) { Alert::info('Tidak ada perubahan', 'Semua siswa sudah memiliki kode akses.'); return redirect()->route('student-self-service.index')->with('success', 'Semua siswa sudah memiliki kode akses.'); } foreach ($students as $student) { $student->forceFill([ 'self_service_access_code' => $this->generateUniqueCode(), 'self_service_code_generated_at' => now(), ])->save(); } Alert::success('Berhasil', $students->count() . ' kode akses berhasil digenerate.'); return redirect()->route('student-self-service.index')->with('success', $students->count() . ' kode akses berhasil digenerate.'); } public function regenerateAllCodes(): RedirectResponse { $students = Student::query()->get(); foreach ($students as $student) { $student->forceFill([ 'self_service_access_code' => $this->generateUniqueCode(), 'self_service_code_generated_at' => now(), ])->save(); } Alert::success('Berhasil', 'Semua kode akses siswa berhasil direset dan digenerate ulang.'); return redirect()->route('student-self-service.index')->with('success', 'Semua kode akses siswa berhasil direset dan digenerate ulang.'); } public function regenerateStudentCode(Student $student): RedirectResponse { $student->forceFill([ 'self_service_access_code' => $this->generateUniqueCode(), 'self_service_code_generated_at' => now(), ])->save(); Alert::success('Berhasil', 'Kode akses untuk ' . $student->full_name . ' berhasil digenerate ulang.'); return redirect()->route('student-self-service.index')->with('success', 'Kode akses untuk ' . $student->full_name . ' berhasil digenerate ulang.'); } public function exportClassCodes(Request $request): View|RedirectResponse { $validated = $request->validate([ 'class_id' => ['required', 'exists:classes,id'], ], [ 'class_id.required' => 'Pilih kelas terlebih dahulu sebelum export kode.', ]); $class = SchoolClass::with(['academicYear', 'department'])->findOrFail($validated['class_id']); $students = Student::query() ->with(['classRoom']) ->where('class_id', $class->id) ->orderBy('full_name') ->get(); if ($students->isEmpty()) { return redirect()->route('student-self-service.index', ['class_id' => $class->id]) ->withErrors(['class_id' => 'Kelas terpilih belum memiliki data siswa.']); } $studentsWithoutCode = $students->filter(fn (Student $student) => blank($student->self_service_access_code)); foreach ($studentsWithoutCode as $student) { $student->forceFill([ 'self_service_access_code' => $this->generateUniqueCode(), 'self_service_code_generated_at' => now(), ])->save(); } $students = Student::query() ->where('class_id', $class->id) ->orderBy('full_name') ->get(); return view('student-self-service.export-class-codes', [ 'class' => $class, 'students' => $students, 'generatedCount' => $studentsWithoutCode->count(), ]); } protected function generateUniqueCode(): string { $characters = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789'; do { $code = collect(range(1, 4)) ->map(fn () => $characters[random_int(0, strlen($characters) - 1)]) ->implode(''); } while (Student::where('self_service_access_code', $code)->exists()); return $code; } }