authService = new AuthService(); } /** * Generate token untuk schedule_id. Hanya guru mapel jadwal tersebut / admin / wali kelas. */ public function generate(): ResponseInterface { $user = $this->authService->currentUser(); if (!$user) { return $this->errorResponse('Unauthorized', null, null, 401); } $payload = $this->request->getJSON(true) ?? []; $scheduleId = (int) ($payload['schedule_id'] ?? 0); if ($scheduleId < 1) { return $this->errorResponse('schedule_id wajib diisi', null, null, 400); } $scheduleModel = new ScheduleModel(); $schedule = $scheduleModel->getScheduleWithSlot($scheduleId); if (!$schedule) { return $this->errorResponse('Jadwal tidak ditemukan', null, null, 404); } if (!$this->canAccessSchedule($schedule, $user)) { return $this->errorResponse('Anda tidak punya akses untuk jadwal ini', null, null, 403); } $qrModel = new QrAttendanceTokenModel(); $token = $qrModel->generateForSchedule($scheduleId, (int) $user['id']); if (!$token) { return $this->errorResponse('Gagal generate token', null, null, 500); } $subjectName = '-'; $className = '-'; if (!empty($schedule['subject_id'])) { $subject = (new SubjectModel())->find($schedule['subject_id']); $subjectName = $subject ? (string) $subject->name : '-'; } if (!empty($schedule['class_id'])) { $class = (new ClassModel())->find($schedule['class_id']); $className = $class ? (trim($class->grade . ' ' . $class->major . ' ' . $class->name) ?: ('Kelas #' . $class->id)) : '-'; } $expiresAt = date('Y-m-d H:i:s', strtotime('+' . QrAttendanceTokenModel::VALID_MINUTES . ' minutes')); $data = [ 'token' => $token, 'expires_at' => $expiresAt, 'schedule_id' => $scheduleId, 'subject_name' => $subjectName, 'class_name' => $className, 'valid_minutes' => QrAttendanceTokenModel::VALID_MINUTES, ]; return $this->successResponse($data, 'QR token berhasil dibuat. Tampilkan QR untuk siswa scan.'); } protected function canAccessSchedule(array $schedule, array $user): bool { $roleCodes = array_column($user['roles'] ?? [], 'role_code'); if (in_array(Role::CODE_ADMIN, $roleCodes, true) || in_array(Role::CODE_GURU_BK, $roleCodes, true)) { return true; } $classId = (int) ($schedule['class_id'] ?? 0); if (in_array(Role::CODE_WALI_KELAS, $roleCodes, true)) { $row = \Config\Database::connect() ->table('classes') ->select('id') ->where('id', $classId) ->where('wali_user_id', $user['id']) ->get() ->getRow(); return $row !== null; } if (in_array(Role::CODE_GURU_MAPEL, $roleCodes, true)) { $teacherUserId = (int) ($schedule['teacher_user_id'] ?? 0); return $teacherUserId === (int) $user['id']; } return false; } }