Files
presensi/app/Modules/Dashboard/Controllers/QrAttendanceController.php
2026-03-05 14:37:36 +07:00

109 lines
3.9 KiB
PHP

<?php
namespace App\Modules\Dashboard\Controllers;
use App\Core\BaseApiController;
use App\Modules\Academic\Models\ClassModel;
use App\Modules\Academic\Models\ScheduleModel;
use App\Modules\Academic\Models\SubjectModel;
use App\Modules\Auth\Entities\Role;
use App\Modules\Auth\Services\AuthService;
use App\Modules\Attendance\Models\QrAttendanceTokenModel;
use CodeIgniter\HTTP\ResponseInterface;
/**
* Generate QR token untuk absen mapel (guru tampilkan QR, siswa scan).
* POST /api/dashboard/qr-attendance/generate
* Body: { schedule_id: number }
*/
class QrAttendanceController extends BaseApiController
{
protected AuthService $authService;
public function __construct()
{
$this->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;
}
}