# Functional & Non-Functional Requirements

## Sistem Absensi Digital Berbasis Web — SMA

> **Versi:** 2.0.0
> **Tanggal:** April 2026
> **Status:** Final
> **Perubahan dari v1.1.0:** Penambahan FR-08 validation chain, FR-07 alur kartu hilang, FR-08 double scan & offline handling; penyempurnaan NFR akurasi, kompatibilitas, dan keterukuran; pembaruan Constraints C-07 dan C-10.

---

## Daftar Isi

1. [Konteks Sistem](#1-konteks-sistem)
2. [Peran Pengguna (Roles)](#2-peran-pengguna-roles)
3. [Functional Requirements (FR)](#3-functional-requirements-fr)
4. [Non-Functional Requirements (NFR)](#4-non-functional-requirements-nfr)
5. [Batasan Sistem (Constraints)](#5-batasan-sistem-constraints)

---

## 1. Konteks Sistem

Sistem ini adalah **Aplikasi Web Absensi Digital** untuk Sekolah Menengah Atas (SMA) yang mencakup:

-  Pencatatan kehadiran harian guru dan siswa secara otomatis melalui scan QR Code via halaman scanner berbasis browser
-  Mekanisme scanner berbasis **kiosk**: setiap guru dan siswa memiliki **ID card fisik** yang dicetak dengan QR Code unik per individu; pengguna mendekatkan kartu ke kamera perangkat kiosk (komputer/tablet) yang membuka halaman scanner di browser — bukan model di mana pengguna memindai QR dari ponsel masing-masing
-  Rekam absensi mengajar guru per sesi yang dipicu oleh tindakan aktif guru (mulai & selesai mengajar)
-  Rekam absensi mata pelajaran siswa yang diinput oleh guru per sesi
-  Portal mandiri per role dengan panel masing-masing
-  Sistem alert otomatis untuk kondisi kritis
-  Manajemen kalender libur dan pengajuan izin dengan mekanisme approval
-  Mekanisme kenaikan kelas siswa di akhir tahun ajaran

---

## 2. Peran Pengguna (Roles)

Setiap role memiliki panel tersendiri dengan navigasi dan akses fitur yang berbeda.

| Role          | Panel             | Deskripsi Tanggung Jawab                                                                                                                                     |
| ------------- | ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `super_admin` | Panel Super Admin | Pengelola penuh sistem: konfigurasi, master data, user management, laporan, kalender libur, kenaikan kelas                                                   |
| `operator`    | Panel Operator    | Fokus operasional absensi harian: monitoring dan koreksi check-in/out guru & siswa, input absensi mengajar guru dan absensi mapel siswa, regenerate QR token |
| `teacher`     | Panel Guru        | Memulai & mengakhiri sesi mengajar, menginput absensi mapel siswa untuk kelasnya, melihat rekap absensi diri sendiri                                         |
| `student`     | Panel Siswa       | Memantau rekap absensi harian dan per mapel, melihat jadwal, mengajukan dan memantau status izin                                                             |

---

## 3. Functional Requirements (FR)

---

### FR-01 — Autentikasi & Manajemen Sesi

| ID      | Deskripsi                                                                                                                          |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| FR-01.1 | Sistem menyediakan halaman login berbasis email dan password untuk semua role                                                      |
| FR-01.2 | Sistem menggunakan session-based authentication (custom controller)                                                                |
| FR-01.3 | Setelah login berhasil, sistem melakukan redirect ke panel yang sesuai dengan role pengguna                                        |
| FR-01.4 | Sistem mencegah akses ke panel atau route yang tidak sesuai dengan role (RoleMiddleware); akses tidak sah menghasilkan respons 403 |
| FR-01.5 | Sistem menyediakan fungsi logout yang menghapus sesi aktif                                                                         |
| FR-01.6 | Pengguna dapat memperbarui data profil dan password dari panel masing-masing                                                       |
| FR-01.7 | Akun dengan `is_active = false` ditolak saat login dengan pesan yang informatif                                                    |

---

### FR-02 — Manajemen Pengguna & Peran

_Dikelola oleh `super_admin`._

| ID      | Deskripsi                                                                                    |
| ------- | -------------------------------------------------------------------------------------------- |
| FR-02.1 | `super_admin` dapat membuat akun pengguna dengan role: `operator`, `teacher`, atau `student` |
| FR-02.2 | `super_admin` dapat mengubah data akun dan menonaktifkan/mengaktifkan akun pengguna          |
| FR-02.3 | Setiap akun dengan role `teacher` otomatis terhubung ke satu profil guru (`TEACHERS`)        |
| FR-02.4 | Setiap akun dengan role `student` otomatis terhubung ke satu profil siswa (`STUDENTS`)       |
| FR-02.5 | `super_admin` dapat mengatur ulang password pengguna                                         |

---

### FR-03 — Manajemen Master Data

_Dikelola oleh `super_admin`._

| ID      | Deskripsi                                                                                                                                |
| ------- | ---------------------------------------------------------------------------------------------------------------------------------------- |
| FR-03.1 | `super_admin` dapat membuat, mengubah, dan menonaktifkan data guru (`TEACHERS`) termasuk nomor pegawai, foto, dan gender                 |
| FR-03.2 | `super_admin` dapat membuat, mengubah, dan menonaktifkan data siswa (`STUDENTS`) termasuk nomor induk, foto, gender, dan penugasan kelas |
| FR-03.3 | `super_admin` dapat membuat, mengubah, dan menonaktifkan data kelas (`CLASSROOMS`) termasuk tingkat kelas dan wali kelas                 |
| FR-03.4 | `super_admin` dapat membuat, mengubah, dan menonaktifkan data mata pelajaran (`SUBJECTS`)                                                |
| FR-03.5 | Data guru dan siswa mendukung upload foto profil                                                                                         |

---

### FR-04 — Manajemen Tahun Ajaran & Semester

_Dikelola oleh `super_admin`._

| ID      | Deskripsi                                                                                     |
| ------- | --------------------------------------------------------------------------------------------- |
| FR-04.1 | `super_admin` dapat membuat dan mengelola tahun ajaran (`ACADEMIC_YEARS`)                     |
| FR-04.2 | Setiap tahun ajaran memiliki **tepat dua** semester: Semester 1 dan Semester 2                |
| FR-04.3 | Hanya satu semester yang boleh berstatus `is_active = true` pada satu waktu di seluruh sistem |
| FR-04.4 | Semester aktif menjadi acuan untuk seluruh proses absensi yang sedang berjalan                |
| FR-04.5 | `super_admin` dapat menutup semester aktif dan mengaktifkan semester berikutnya secara manual |

---

### FR-05 — Mekanisme Kenaikan Kelas

_Dikelola oleh `super_admin`, dipicu di akhir tahun ajaran setelah Semester 2 ditutup._

| ID      | Deskripsi                                                                                                           |
| ------- | ------------------------------------------------------------------------------------------------------------------- |
| FR-05.1 | Setelah Semester 2 ditutup, sistem mengaktifkan fitur **Proses Kenaikan Kelas**                                     |
| FR-05.2 | Sistem menampilkan daftar seluruh siswa aktif beserta kelas dan tingkat saat ini sebagai dasar proses               |
| FR-05.3 | `super_admin` menentukan keputusan untuk setiap siswa: **naik kelas**, **tinggal kelas**, atau **lulus**            |
| FR-05.4 | Siswa yang **naik kelas** dipindahkan ke kelas baru (tingkat berikutnya) yang dipilih `super_admin`                 |
| FR-05.5 | Siswa yang **tinggal kelas** tetap di tingkat yang sama namun dapat dipindahkan ke kelas yang berbeda               |
| FR-05.6 | Siswa yang **lulus** (dari kelas XII) dinonaktifkan dari sistem (`is_active = false`)                               |
| FR-05.7 | Proses kenaikan kelas hanya dapat dijalankan sekali per tahun ajaran dan bersifat irreversible setelah dikonfirmasi |
| FR-05.8 | Riwayat absensi siswa dari tahun ajaran sebelumnya tetap tersimpan dan tidak dihapus                                |

---

### FR-06 — Manajemen Jadwal Pelajaran

_Dikelola oleh `super_admin`._

| ID      | Deskripsi                                                                                                                       |
| ------- | ------------------------------------------------------------------------------------------------------------------------------- |
| FR-06.1 | `super_admin` dapat membuat jadwal pelajaran per semester, per hari, per sesi, per kelas                                        |
| FR-06.2 | Setiap entri jadwal menghubungkan: semester, hari, urutan sesi, waktu mulai & selesai, mata pelajaran, kelas, dan guru pengampu |
| FR-06.3 | Sistem harus mencegah jadwal yang konflik: guru atau kelas yang sama pada hari, sesi, dan semester yang sama                    |
| FR-06.4 | Jadwal dengan `is_active = false` tidak memunculkan sesi absensi                                                                |

---

### FR-07 — Manajemen QR Code & Kiosk Token

_Dikelola oleh `super_admin` dan sebagian oleh `operator`._

| ID      | Deskripsi                                                                                                                                                                                                           |
| ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| FR-07.1 | Sistem membuat QR token unik untuk setiap guru (`TEACHER_QR_TOKENS`)                                                                                                                                                |
| FR-07.2 | Sistem membuat QR token unik untuk setiap siswa (`STUDENT_QR_TOKENS`)                                                                                                                                               |
| FR-07.3 | QR token dapat di-regenerate oleh `super_admin` atau `operator`; token lama langsung tidak valid pada saat yang sama                                                                                                |
| FR-07.4 | QR Code dapat diunduh dan dicetak dalam format gambar untuk ditempel pada **ID card fisik** per individu                                                                                                            |
| FR-07.5 | `super_admin` atau `operator` dapat melakukan regenerate QR token atas permintaan guru atau siswa yang melaporkan kartu hilang atau rusak; sistem mencatat log regenerasi (siapa yang melakukan, kapan, dan alasan) |
| FR-07.6 | Selama masa kartu hilang atau menunggu cetak ulang, `operator` atau `super_admin` dapat mengoreksi absensi harian secara manual (FR-09.5, FR-10.5) sebagai kompensasi                                               |
| FR-07.7 | `super_admin` dapat membuat Kiosk Token (`KIOSK_TOKENS`) untuk mengotorisasi perangkat yang akan membuka halaman scanner                                                                                            |
| FR-07.8 | Kiosk Token memiliki nama perangkat, masa berlaku (`expires_at`), dan dapat dinonaktifkan sewaktu-waktu                                                                                                             |

---

### FR-08 — Halaman Kiosk / Scanner QR

_Diakses oleh perangkat (tablet/PC) yang membuka halaman scanner dengan Kiosk Token valid. Tidak memerlukan login akun pengguna. Pengguna mendekatkan ID card fisik ber-QR Code ke kamera perangkat kiosk._

| ID       | Deskripsi                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| FR-08.1  | Sistem menyediakan halaman scanner berbasis browser menggunakan `html5-qrcode` yang hanya dapat diakses dengan Kiosk Token valid dan belum kadaluarsa                                                                                                                                                                                                                                                                                                                                      |
| FR-08.2  | Halaman scanner diperuntukkan **hanya** untuk pencatatan check-in dan check-out harian guru dan siswa; tidak untuk absensi mapel                                                                                                                                                                                                                                                                                                                                                           |
| FR-08.3  | Setiap scan QR yang masuk diproses melalui validation chain berikut secara berurutan: **(1)** Kiosk Token valid dan belum kadaluarsa → **(2)** QR token dikenal dan ada di database → **(3)** Pengguna pemilik token berstatus `is_active = true` → **(4)** Tanggal hari ini bukan hari libur dengan `is_daily_attendance_active = false` → **(5)** Catat kehadiran. Jika salah satu validasi gagal, proses berhenti dan sistem menampilkan pesan error yang sesuai dengan tahap kegagalan |
| FR-08.4  | Jika scan kedua terjadi dalam rentang waktu kurang dari 1 menit sejak scan terakhir oleh individu yang sama, sistem **mengabaikan** scan tersebut dan menampilkan pesan _"Absensi sudah tercatat, silakan coba beberapa saat lagi"_ tanpa membuat record baru                                                                                                                                                                                                                              |
| FR-08.5  | Scan pertama yang valid dalam satu hari dicatat sebagai `check_in_time`; scan valid berikutnya pada hari yang sama (setelah melewati batas 1 menit) dicatat sebagai `check_out_time`                                                                                                                                                                                                                                                                                                       |
| FR-08.6  | Scan ketiga dan seterusnya pada hari yang sama (setelah check*in dan check_out sudah tercatat) diabaikan oleh sistem dan menampilkan pesan *"Check-in dan check-out hari ini sudah tercatat"\_                                                                                                                                                                                                                                                                                             |
| FR-08.7  | Setelah scan valid berhasil, sistem menampilkan **card data diri** berisi: foto, nama lengkap, role (guru/siswa), kelas (untuk siswa) atau jabatan (untuk guru), dan status kehadiran yang baru saja dicatat                                                                                                                                                                                                                                                                               |
| FR-08.8  | Sistem menampilkan feedback visual yang berbeda untuk setiap kondisi: check-in berhasil, check-out berhasil, absensi sudah tercatat (double scan), QR tidak dikenal, pengguna tidak aktif, hari libur, dan Kiosk Token tidak valid/kadaluarsa                                                                                                                                                                                                                                              |
| FR-08.9  | Halaman kiosk menampilkan **indikator status koneksi** ke server secara real-time. Jika koneksi ke server terputus, sistem menampilkan pesan peringatan yang jelas, menonaktifkan fungsi scan, dan memblokir pencatatan baru hingga koneksi pulih                                                                                                                                                                                                                                          |
| FR-08.10 | Sistem menolak scan dari Kiosk Token yang telah kadaluarsa atau dinonaktifkan                                                                                                                                                                                                                                                                                                                                                                                                              |
| FR-08.11 | Halaman scanner harus stabil dan tidak mengalami memory leak selama digunakan seharian penuh (≥ 8 jam)                                                                                                                                                                                                                                                                                                                                                                                     |

---

### FR-09 — Absensi Harian Guru

_Pencatatan otomatis via scanner. Monitoring dan koreksi oleh `operator` dan `super_admin`._

| ID      | Deskripsi                                                                                                                                       |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
| FR-09.1 | Sistem mencatat absensi harian guru (`TEACHER_DAILY_ATTENDANCES`) per tanggal berdasarkan scan QR di halaman kiosk                              |
| FR-09.2 | Status yang didukung: `present`, `late`, `absent`, `permission`, `sick`, `out_of_office`                                                        |
| FR-09.3 | Sistem menentukan status `present` atau `late` berdasarkan perbandingan `check_in_time` dengan batas waktu yang dikonfigurasi di `SETTINGS`     |
| FR-09.4 | Jika guru tidak melakukan scan hingga batas waktu yang dikonfigurasi, Task Scheduler secara otomatis membuat record `absent` (`is_auto = true`) |
| FR-09.5 | `operator` dan `super_admin` dapat mengoreksi status absensi harian guru secara manual                                                          |
| FR-09.6 | Record absensi harian tidak dibuat pada tanggal yang merupakan hari libur (`HOLIDAYS`)                                                          |

---

### FR-10 — Absensi Harian Siswa

_Pencatatan otomatis via scanner. Monitoring dan koreksi oleh `operator` dan `super_admin`._

| ID      | Deskripsi                                                                                                                     |
| ------- | ----------------------------------------------------------------------------------------------------------------------------- |
| FR-10.1 | Sistem mencatat absensi harian siswa (`STUDENT_DAILY_ATTENDANCES`) per tanggal berdasarkan scan QR di halaman kiosk           |
| FR-10.2 | Status yang didukung: `present`, `late`, `absent`, `permission`, `sick`                                                       |
| FR-10.3 | Sistem menentukan status `present` atau `late` berdasarkan `check_in_time` dan konfigurasi `SETTINGS`                         |
| FR-10.4 | Jika siswa tidak melakukan scan hingga batas waktu, Task Scheduler membuat record `absent` secara otomatis (`is_auto = true`) |
| FR-10.5 | `operator` dan `super_admin` dapat mengoreksi status absensi harian siswa secara manual                                       |
| FR-10.6 | Record absensi harian tidak dibuat pada hari libur yang berlaku untuk kelas siswa tersebut                                    |

---

### FR-11 — Absensi Mengajar Guru (Per Sesi)

_Dipicu oleh tindakan aktif guru di panel guru. Dimonitor dan dapat dikoreksi oleh `operator` dan `super_admin`._

| ID      | Deskripsi                                                                                                                     |
| ------- | ----------------------------------------------------------------------------------------------------------------------------- |
| FR-11.1 | Sistem menampilkan kepada guru daftar sesi mengajar hari ini berdasarkan jadwal aktif yang menjadi tanggung jawabnya          |
| FR-11.2 | Guru memulai sesi dengan mengklik tombol **"Mulai Sesi Mengajar"**; sistem mencatat waktu mulai dan status menjadi `teaching` |
| FR-11.3 | Guru mengakhiri sesi dengan mengklik tombol **"Selesai Mengajar"**; sistem mencatat waktu selesai                             |
| FR-11.4 | Jika guru tidak mengklik "Mulai Sesi" hingga sesi berakhir, Task Scheduler mencatat status `not_teaching` secara otomatis     |
| FR-11.5 | `operator` dan `super_admin` dapat mengoreksi status absensi mengajar guru jika diperlukan                                    |
| FR-11.6 | Guru hanya dapat memulai sesi pada jadwal yang merupakan tanggung jawabnya dan pada hari yang sesuai                          |
| FR-11.7 | Record absensi mengajar tidak dibuat pada hari libur                                                                          |

---

### FR-12 — Absensi Mata Pelajaran Siswa (Per Sesi)

_Diinput oleh `teacher` setelah memulai sesi. Dapat dikoreksi oleh `operator` dan `super_admin`._

| ID      | Deskripsi                                                                                                          |
| ------- | ------------------------------------------------------------------------------------------------------------------ |
| FR-12.1 | Setelah guru mengklik "Mulai Sesi Mengajar", sistem menampilkan form absensi berisi daftar siswa di kelas tersebut |
| FR-12.2 | Guru menginput status kehadiran setiap siswa untuk sesi yang sedang berlangsung                                    |
| FR-12.3 | Status yang didukung: `present`, `absent`, `permission`, `sick`, `late`                                            |
| FR-12.4 | Guru hanya dapat menginput absensi mapel untuk jadwal dan kelas yang menjadi tanggung jawabnya                     |
| FR-12.5 | Sistem mencatat `submitted_by` dan `submitted_at` untuk setiap pengisian                                           |
| FR-12.6 | `operator` dan `super_admin` dapat mengoreksi absensi mapel siswa jika diperlukan                                  |

---

### FR-13 — Manajemen Guru Pengganti

_Dikelola oleh `operator` dan `super_admin`._

| ID      | Deskripsi                                                                                                                      |
| ------- | ------------------------------------------------------------------------------------------------------------------------------ |
| FR-13.1 | `operator` dan `super_admin` dapat menunjuk guru pengganti (`SUBSTITUTE_TEACHERS`) untuk jadwal tertentu pada tanggal tertentu |
| FR-13.2 | Sistem mencatat: jadwal, tanggal, guru asli, guru pengganti, dan pihak yang menunjuk                                           |
| FR-13.3 | Jika ada guru pengganti, sesi mengajar (FR-11) dan form absensi mapel (FR-12) muncul di panel guru pengganti, bukan guru asli  |
| FR-13.4 | Absensi mengajar pada sesi yang digantikan dicatat atas nama guru pengganti                                                    |

---

### FR-14 — Kalender Hari Libur & Hari Khusus

_Dikelola oleh `super_admin`._

| ID      | Deskripsi                                                                                                               |
| ------- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-14.1 | `super_admin` dapat membuat entri hari libur (`HOLIDAYS`) dengan rentang tanggal, deskripsi, dan tipe                   |
| FR-14.2 | Tipe yang didukung: `holiday` (libur nasional/sekolah) dan `school_event` (kegiatan khusus sekolah)                     |
| FR-14.3 | Scope berlaku: `whole_school` (semua kelas) atau `per_class` (kelas tertentu, dikelola via `CLASSROOM_HOLIDAYS`)        |
| FR-14.4 | Field `is_daily_attendance_active` menentukan apakah absensi harian check-in/out tetap berjalan pada hari tersebut      |
| FR-14.5 | Semua proses otomatis (auto-absent, alert, pembentukan sesi absensi) wajib mengecek tabel `HOLIDAYS` sebelum dieksekusi |

---

### FR-15 — Pengajuan Izin Guru

_Pengajuan oleh `teacher`. Review oleh `operator` dan `super_admin`._

| ID      | Deskripsi                                                                                                                                                |
| ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| FR-15.1 | Guru dapat mengajukan permohonan izin/cuti (`TEACHER_LEAVE_REQUESTS`) dengan rentang tanggal, alasan, dan lampiran file (PDF/gambar)                     |
| FR-15.2 | Status izin: `pending` → `approved` / `rejected` / `canceled`                                                                                            |
| FR-15.3 | `operator` dan `super_admin` dapat menyetujui atau menolak permohonan izin guru disertai catatan reviewer                                                |
| FR-15.4 | Jika izin disetujui, sistem otomatis memperbarui status absensi harian guru pada tanggal yang dicakup menjadi `permission` atau `sick` sesuai jenis izin |
| FR-15.5 | `operator` dan `super_admin` dapat membuat entri izin langsung atas nama guru (`is_admin_input = true`) tanpa melalui alur pengajuan                     |
| FR-15.6 | Guru menerima notifikasi in-app saat status izinnya berubah                                                                                              |

---

### FR-16 — Pengajuan Izin Siswa

_Pengajuan oleh `student`. Review oleh `operator` dan `super_admin`._

| ID      | Deskripsi                                                                                                                |
| ------- | ------------------------------------------------------------------------------------------------------------------------ |
| FR-16.1 | Siswa dapat mengajukan permohonan izin (`STUDENT_LEAVE_REQUESTS`) dengan rentang tanggal, alasan, dan lampiran file      |
| FR-16.2 | Status izin: `pending` → `approved` / `rejected` / `canceled`                                                            |
| FR-16.3 | `operator` dan `super_admin` dapat menyetujui atau menolak permohonan izin siswa                                         |
| FR-16.4 | Jika izin disetujui, sistem otomatis memperbarui status absensi harian siswa dan absensi mapel pada tanggal yang dicakup |
| FR-16.5 | `operator` dan `super_admin` dapat membuat entri izin langsung atas nama siswa (`is_admin_input = true`)                 |
| FR-16.6 | Siswa menerima notifikasi in-app saat status izinnya berubah                                                             |

---

### FR-17 — Sistem Alert Otomatis

_Dikirim ke `super_admin` dan `operator`. Dijalankan via Laravel Task Scheduling._

| ID      | Deskripsi                                                                                                               |
| ------- | ----------------------------------------------------------------------------------------------------------------------- |
| FR-17.1 | Sistem mengirim alert ketika guru belum melakukan check-in melewati batas waktu yang dikonfigurasi                      |
| FR-17.2 | Sistem mengirim alert ketika jumlah siswa tidak hadir dalam satu kelas melewati threshold persentase yang dikonfigurasi |
| FR-17.3 | Sistem mengirim alert ketika guru tidak mengklik "Mulai Sesi Mengajar" untuk sesi yang sudah melewati waktu mulai       |
| FR-17.4 | Semua threshold dan waktu trigger alert dikonfigurasi melalui tabel `SETTINGS` (group: `alert`)                         |
| FR-17.5 | Alert tidak dikirim pada hari libur                                                                                     |
| FR-17.6 | Alert dikirim melalui notifikasi in-app (Laravel Notifications + database driver)                                       |

---

### FR-18 — Laporan & Ekspor Data

_Diakses oleh `super_admin` dan `operator`._

| ID      | Deskripsi                                                                       |
| ------- | ------------------------------------------------------------------------------- |
| FR-18.1 | Sistem menyediakan laporan rekap absensi harian guru per periode                |
| FR-18.2 | Sistem menyediakan laporan rekap absensi harian siswa per kelas per periode     |
| FR-18.3 | Sistem menyediakan laporan absensi mengajar guru per semester                   |
| FR-18.4 | Sistem menyediakan laporan absensi mata pelajaran siswa per semester per kelas  |
| FR-18.5 | Laporan dapat diekspor ke format **PDF** (barryvdh/laravel-dompdf)              |
| FR-18.6 | Laporan dapat diekspor ke format **Excel** (maatwebsite/laravel-excel)          |
| FR-18.7 | Laporan dapat difilter berdasarkan: rentang tanggal, kelas, guru, atau semester |

---

### FR-19 — Portal Mandiri Siswa

_Diakses oleh `student` melalui panel siswa._

| ID      | Deskripsi                                                               |
| ------- | ----------------------------------------------------------------------- |
| FR-19.1 | Siswa dapat melihat rekap absensi harian diri sendiri beserta statusnya |
| FR-19.2 | Siswa dapat melihat rekap absensi per mata pelajaran diri sendiri       |
| FR-19.3 | Siswa dapat melihat jadwal pelajaran kelas mereka untuk semester aktif  |
| FR-19.4 | Siswa dapat melihat status dan riwayat seluruh pengajuan izin mereka    |
| FR-19.5 | Portal siswa hanya menampilkan data milik siswa yang sedang login       |

---

### FR-20 — Manajemen Konfigurasi Sistem

_Dikelola oleh `super_admin`._

| ID      | Deskripsi                                                                                                                                                                                                   |
| ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| FR-20.1 | `super_admin` dapat membaca dan mengubah konfigurasi sistem melalui antarmuka berbasis tabel `SETTINGS`                                                                                                     |
| FR-20.2 | Konfigurasi yang dapat dikelola mencakup: jam batas check-in (terlambat), jam batas auto-absent, threshold persentase ketidakhadiran untuk alert, durasi cooldown double scan, dan parameter sistem lainnya |
| FR-20.3 | Tipe nilai konfigurasi yang didukung: `string`, `integer`, `boolean`, `json`                                                                                                                                |
| FR-20.4 | Perubahan konfigurasi berlaku langsung tanpa perlu restart sistem                                                                                                                                           |

---

## 4. Non-Functional Requirements (NFR)

---

### NFR-01 — Performa

| ID       | Deskripsi                                                                         | Target                                                         |
| -------- | --------------------------------------------------------------------------------- | -------------------------------------------------------------- |
| NFR-01.1 | Waktu respons halaman utama panel (dashboard, list data)                          | ≤ 2 detik pada koneksi jaringan lokal sekolah (latensi < 10ms) |
| NFR-01.2 | Waktu respons proses scan QR hingga card data diri tampil di browser              | ≤ 1.5 detik pada jaringan lokal (latensi < 10ms)               |
| NFR-01.3 | Waktu ekspor laporan PDF/Excel untuk data 1 semester                              | ≤ 10 detik                                                     |
| NFR-01.4 | Waktu query laporan multi-tahun (data ≥ 3 tahun ajaran, ≥ 100.000 record absensi) | ≤ 5 detik                                                      |
| NFR-01.5 | Halaman kiosk/scanner stabil tanpa memory leak                                    | ≥ 8 jam operasi berkesinambungan tanpa reload manual           |

---

### NFR-02 — Keamanan

| ID       | Deskripsi                                                                                                                                                                                                                                      |
| -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| NFR-02.1 | Semua password disimpan menggunakan hashing bcrypt (default Laravel)                                                                                                                                                                           |
| NFR-02.2 | Seluruh komunikasi browser–server menggunakan HTTPS; halaman kiosk wajib diakses via HTTPS agar izin kamera browser bersifat persistent                                                                                                        |
| NFR-02.3 | Setiap route terproteksi oleh `RoleMiddleware`; akses lintas panel menghasilkan respons 403                                                                                                                                                    |
| NFR-02.4 | Kiosk Token menggunakan string acak yang cryptographically secure dan memiliki masa berlaku eksplisit                                                                                                                                          |
| NFR-02.5 | QR Token guru dan siswa bersifat unik dan tidak dapat ditebak (token acak, bukan berbasis ID); pada satu waktu hanya boleh ada satu token aktif per individu                                                                                   |
| NFR-02.6 | QR Code bersifat statis per individu; risiko penyalahgunaan kartu (foto/screenshot QR oleh pihak lain) dimitigasi secara operasional: operator memantau anomali log scan dan regenerasi token dilakukan segera setelah kartu dilaporkan hilang |
| NFR-02.7 | File lampiran izin disimpan di `disk: local` dan tidak dapat diakses langsung via URL publik                                                                                                                                                   |
| NFR-02.8 | Sistem menggunakan CSRF middleware Laravel pada seluruh form                                                                                                                                                                                   |
| NFR-02.9 | Seluruh input pengguna divalidasi di sisi server menggunakan Laravel Form Request Validation                                                                                                                                                   |

---

### NFR-03 — Keandalan (Reliability)

| ID       | Deskripsi                                                                       | Target                                                             |
| -------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| NFR-03.1 | Uptime sistem pada jam operasional sekolah (06.00–18.00)                        | ≥ 99.5% (ekuivalen ≤ 54 menit downtime/bulan pada jam operasional) |
| NFR-03.2 | Laravel Task Scheduler berjalan reliabel untuk proses auto-absent dan alert     | Toleransi keterlambatan eksekusi ≤ 5 menit                         |
| NFR-03.3 | Kegagalan scan tunggal (QR buram, tidak terbaca) tidak menyebabkan crash sistem | Graceful error dengan pesan informatif di halaman scanner          |
| NFR-03.4 | Jika terjadi downtime tidak terencana, sistem harus kembali beroperasi          | Recovery Time Objective (RTO) ≤ 15 menit                           |

---

### NFR-04 — Akurasi

| ID       | Deskripsi                                                         | Target                                                                                                                                            |
| -------- | ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- |
| NFR-04.1 | Sistem tidak boleh mencatat kehadiran dengan identitas yang salah | Setiap QR token aktif dipetakan ke tepat satu individu; tidak boleh ada token duplikat aktif pada waktu yang sama                                 |
| NFR-04.2 | Proses regenerate token harus bersifat atomic                     | Token lama dinonaktifkan dan token baru diaktifkan dalam satu transaksi database; tidak ada jeda di mana dua token aktif untuk individu yang sama |

---

### NFR-05 — Skalabilitas

| ID       | Deskripsi                                                                                                                      |
| -------- | ------------------------------------------------------------------------------------------------------------------------------ |
| NFR-05.1 | Sistem mampu menangani minimal 1.000 siswa aktif dan 100 guru                                                                  |
| NFR-05.2 | Skema database mendukung akumulasi data absensi multi-tahun-ajaran; lihat NFR-01.4 untuk target performa query                 |
| NFR-05.3 | Halaman kiosk dapat dijalankan secara bersamaan di beberapa perangkat dengan Kiosk Token yang berbeda tanpa degradasi performa |

---

### NFR-06 — Kegunaan (Usability)

| ID       | Deskripsi                                                                              |
| -------- | -------------------------------------------------------------------------------------- |
| NFR-06.1 | UI menggunakan Tailwind CSS + Flowbite, konsisten di seluruh panel                     |
| NFR-06.2 | Halaman kiosk/scanner dapat dioperasikan oleh staf non-teknis tanpa pelatihan khusus   |
| NFR-06.3 | Card feedback scanner menampilkan informasi yang mudah dibaca dalam waktu singkat      |
| NFR-06.4 | Seluruh halaman responsif dan dapat digunakan pada tablet (minimal resolusi 768px)     |
| NFR-06.5 | Pesan error dan validasi menggunakan Bahasa Indonesia yang jelas dan tidak teknis      |
| NFR-06.6 | Indikator status koneksi pada halaman kiosk terlihat jelas tanpa menghalangi area scan |

---

### NFR-07 — Pemeliharaan (Maintainability)

| ID       | Deskripsi                                                                                                      |
| -------- | -------------------------------------------------------------------------------------------------------------- |
| NFR-07.1 | Kode mengikuti konvensi Laravel: MVC, Eloquent ORM, Form Request Validation, Resource Controller               |
| NFR-07.2 | Seluruh konfigurasi operasional (threshold, jam batas, cooldown) dikelola via `SETTINGS` tanpa modifikasi kode |
| NFR-07.3 | Skema database dikelola melalui Laravel Migrations                                                             |
| NFR-07.4 | Setiap proses batch (auto-absent, alert) terdokumentasi dalam Laravel Task Scheduling                          |

---

### NFR-08 — Kompatibilitas

| ID       | Deskripsi                                                                                                                                                     |
| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| NFR-08.1 | Sistem dapat diakses via browser modern: Chrome ≥ 90, Firefox ≥ 88, Edge ≥ 90                                                                                 |
| NFR-08.2 | Fitur kamera pada halaman scanner memerlukan browser dengan dukungan `getUserMedia` API (WebRTC); sistem menampilkan pesan yang jelas jika API tidak tersedia |
| NFR-08.3 | Halaman kiosk kompatibel dengan kamera USB eksternal dan kamera built-in pada perangkat tablet/PC yang diakses via browser Chrome atau Edge                   |
| NFR-08.4 | Dibangun di atas Laravel 13.x dengan PHP ≥ 8.2                                                                                                                |
| NFR-08.5 | Database engine: MySQL 8.0+                                                                                                                                   |

---

## 5. Batasan Sistem (Constraints)

| ID   | Deskripsi                                                                                                                                                                                                                                                                                   |
| ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| C-01 | Setiap tahun ajaran memiliki tepat **dua** semester; tidak lebih dan tidak kurang                                                                                                                                                                                                           |
| C-02 | Absensi berbasis scanner (kiosk) **hanya** digunakan untuk check-in dan check-out harian guru dan siswa; tidak untuk absensi mapel                                                                                                                                                          |
| C-03 | Absensi mapel siswa **hanya** dapat diinput oleh guru melalui panel guru, dipicu setelah guru memulai sesi mengajar                                                                                                                                                                         |
| C-04 | Absensi mengajar guru dihitung berdasarkan tindakan aktif guru ("Mulai Sesi Mengajar" dan "Selesai Mengajar"), bukan via scanner                                                                                                                                                            |
| C-05 | Notifikasi dibatasi pada **in-app notification** (database driver); notifikasi email dan SMS tidak termasuk scope v1                                                                                                                                                                        |
| C-06 | File lampiran izin disimpan secara lokal (`disk: local`); cloud storage tidak termasuk scope v1                                                                                                                                                                                             |
| C-07 | QR Code bersifat **statis per individu**. Risiko penyalahgunaan melalui foto/screenshot QR diterima sebagai trade-off desain v1 dan dimitigasi secara operasional (monitoring log anomali + regenerasi token segera saat kartu hilang). Mekanisme token dinamis dapat dipertimbangkan di v2 |
| C-08 | Laporan tidak terintegrasi dengan sistem eksternal (Dapodik, SIMDA, dll.) pada v1                                                                                                                                                                                                           |
| C-09 | Proses kenaikan kelas hanya dapat dijalankan setelah Semester 2 ditutup dan bersifat **irreversible** setelah dikonfirmasi                                                                                                                                                                  |
| C-10 | Mode offline pada halaman kiosk **tidak termasuk scope v1**. Jika koneksi ke server terputus, scan diblokir dan pesan error ditampilkan hingga koneksi pulih                                                                                                                                |

---

_Dokumen ini adalah living document. Setiap perubahan requirement harus melalui review bersama stakeholder dan diperbarui dengan versioning yang jelas._
