Files
presensi/PROJECT_CONDITION_AUDIT.md
2026-03-05 14:37:36 +07:00

13 KiB

Audit Kondisi Project SMAN 1 — Detail

Tanggal: 2026-02-23


1. Struktur Module

Module yang sudah ada

Module Lokasi Isi utama
Academic app/Modules/Academic/ Classes, Students, Subjects, Teachers, Schedules, Lesson Slots, DapodikSync (controller + service + mapping model)
Attendance app/Modules/Attendance/ AttendanceSession, Checkin, Report
Auth app/Modules/Auth/ Login, User, Role, UserRole
Dashboard app/Modules/Dashboard/ Dashboard, Schedule, Attendance, Realtime
Devices app/Modules/Devices/ Device, Mobile, DeviceAuth
Notification app/Modules/Notification/ Telegram, Parent, StudentParent
Geo app/Modules/Geo/ Zone, GeoFence

Cek per modul yang Anda tanyakan

Modul Status Keterangan
Classes Ada Di dalam Academic: ClassModel, ClassEntity, ClassController (CRUD), route GET/POST/PUT/DELETE /api/academic/classes, halaman /dashboard/academic/classes
Students Ada Di dalam Academic: StudentModel, StudentEntity, StudentController (CRUD + paginasi), route GET/POST/PUT/DELETE /api/academic/students, halaman /dashboard/academic/students
Attendance Ada Module Attendance terpisah: AttendanceSessionModel, AttendanceCheckinService, AttendanceReportService, dll. Tabel: attendance_sessions (bukan attendance_logs)
Schedule Ada Di dalam Academic: ScheduleModel, ScheduleManagementController, ScheduleResolverService, lesson_slots. Tabel: schedules, lesson_slots
DapodikSync Ada Di dalam Academic: DapodikClient, DapodikSyncService, DapodikSyncController, DapodikRombelMappingModel. Route: POST sync/students, GET/PUT rombels. Halaman /dashboard/academic/dapodik

Kesimpulan: Semua modul yang Anda sebut (Classes, Students, Attendance, Schedule, DapodikSync) sudah ada. Tidak ada modul terpisah bernama "Classes" atau "Students"; semuanya di bawah Academic.


2. Database

Tabel yang ada (beserta struktur)

Catatan: Tidak ada tabel bernama attendance_logs. Yang dipakai: attendance_sessions.

2.1 Tabel classes

Field Type Relasi
id INT PK AUTO_INCREMENT -
name VARCHAR(100) - (rombel, mis. A, B, C)
grade VARCHAR(50) - (tingkat, mis. 10, X)
major VARCHAR(50) NOT NULL DEFAULT 'IPA' - (jurusan)
wali_user_id INT NULL FK → users.id (SET NULL)
created_at DATETIME NULL -
updated_at DATETIME NULL -

Relasi keluar: students.class_id, schedules.class_id, dapodik_rombel_mappings.class_id → classes.id


2.2 Tabel students

Field Type Relasi
id INT PK AUTO_INCREMENT -
nisn VARCHAR(50) NOT NULL UNIQUE -
name VARCHAR(255) -
gender VARCHAR(1) NULL L/P
class_id INT NULL FK → classes.id (SET NULL) — nullable untuk unmapped
is_active TINYINT(1) DEFAULT 1 -
parent_link_code VARCHAR (dari migration lain)
created_at DATETIME NULL -
updated_at DATETIME NULL -

Relasi: class_id → classes.id (boleh NULL untuk siswa belum di-map dari Dapodik).


2.3 Tabel attendance_sessions (bukan attendance_logs)

Field Type Relasi
id INT PK -
student_id INT FK → students.id
schedule_id INT NULL FK → schedules.id
device_id INT FK → devices.id
attendance_date DATE (dari migration unik)
checkin_at DATETIME -
latitude, longitude, confidence DECIMAL -
status ENUM(PRESENT, LATE, OUTSIDE_ZONE, NO_SCHEDULE, INVALID_DEVICE) -
created_at, updated_at DATETIME NULL -

Relasi: student_id → students, schedule_id → schedules, device_id → devices.


2.4 Tabel schedules

Field Type Relasi
id INT PK -
class_id INT FK → classes.id
lesson_slot_id INT NULL FK → lesson_slots.id
subject_id INT FK → subjects.id
teacher_user_id INT NULL FK → users.id
teacher_name VARCHAR(255) -
day_of_week TINYINT (1=Senin, 7=Minggu) -
start_time, end_time TIME -
room VARCHAR(100) NULL -
is_active TINYINT DEFAULT 1 -
created_at, updated_at DATETIME NULL -

Unique: (class_id, lesson_slot_id, day_of_week).

Relasi: class_id → classes, subject_id → subjects, teacher_user_id → users, lesson_slot_id → lesson_slots.


2.5 Tabel tambahan terkait

  • dapodik_rombel_mappings: id, dapodik_rombel (UNIQUE), class_id (FK → classes, NULL), last_seen_at, created_at, updated_at.
  • lesson_slots: id, slot_number, start_time, end_time, is_active.
  • subjects: id, name, code (nullable).

3. Flow Master Data

3.1 Kelas: input manual atau belum?

  • Input kelas: manual lewat halaman Classes (/dashboard/academic/classes), hanya untuk role ADMIN.
  • Form: Tingkat (text), Jurusan (text), Rombel (text), Wali Kelas (dropdown user).
  • Data disimpan ke tabel classes (name = rombel, grade, major, wali_user_id).
  • Jika belum pernah input: tabel classes kosong → tidak ada pilihan kelas di mana pun (Schedule Builder, Students, dll.).

3.2 Schedule Builder mengambil data kelas dari mana?

  • Dari API: GET /api/academic/classes (admin_only).
  • Halaman Schedule Builder index (/dashboard/academic/schedule-builder) memanggil API ini lalu mengisi dropdown "Kelas" (option value = class id, text = nama/rombel).
  • Data sumber: tabel classes via ClassController::index().

3.3 Kenapa dropdown kelas bisa kosong?

  • Penyebab: Tabel classes tidak punya data (belum ada satu baris pun).
  • Alur: Tidak ada kelas → API /api/academic/classes mengembalikan array kosong → dropdown hanya berisi "— Pilih kelas —" → Open Builder tidak bisa dipakai.
  • Solusi: Login sebagai ADMIN → buka Academic → Classes → tambah minimal satu kelas (mis. Tingkat 10, Jurusan IPA, Rombel 1). Setelah itu dropdown di Schedule Builder akan terisi.

4. Dapodik Integration

Aspek Status Keterangan
Controller Dapodik Sync Ada App\Modules\Academic\Controllers\DapodikSyncController
Endpoint API Ada POST /api/academic/dapodik/sync/students, GET /api/academic/dapodik/rombels, PUT /api/academic/dapodik/rombels/{id} (semua admin_only)
Rencana vs realisasi Sudah diimplementasi DapodikClient (getSekolah, getPesertaDidik), DapodikSyncService (sync siswa + rombel mapping), halaman Dapodik di dashboard

Env yang dipakai: DAPODIK_BASE_URL, DAPODIK_TOKEN, DAPODIK_NPSN (di .env).


5. Student Page

Apakah halaman Student sudah tampil?

  • Route: Ada — GET /dashboard/academic/studentsDashboardAcademicController::students, filter dashboard_admin_page.
  • Controller: Ada — method students() me-render view dashboard/students.
  • View: Ada — app/Views/dashboard/students.php (tabel, filter, paginasi, modal tambah/edit/hapus).
  • Query/relasi: API GET /api/academic/students jalan; join ke classes untuk class_label; class_id boleh NULL (tidak gagal).

Kenapa bisa “belum tampil”?

Kemungkinan:

  1. Bukan ADMIN — halaman dan menu Students hanya untuk role ADMIN. Jika login bukan ADMIN, menu Academic (termasuk Students) tidak muncul.
  2. URL salah — harus akses tepat: /dashboard/academic/students (mis. http://localhost/sman1/backend/public/dashboard/academic/students).
  3. Session/redirect — jika belum login atau filter redirect, akan ke halaman login/dashboard.
  4. Data kosong — halaman tetap tampil; yang kosong hanya tabel siswa (belum ada data siswa). Bukan penyebab “halaman tidak tampil”.

Kesimpulan: Secara kode, route, controller, view, dan relasi sudah ada dan konsisten. Kalau “belum tampil”, paling mungkin karena bukan user ADMIN atau salah URL/base URL.


6. Problem Diagnosis

“Schedule Builder meminta kelas, tapi tidak ada tempat input kelas”

  • Faktanya: Sudah ada tempat input kelas, yaitu halaman Classes (/dashboard/academic/classes), hanya untuk ADMIN.
  • Alur yang benar:
    1. ADMIN buka Academic → Classes (atau lewat Academic → Settings → kartu Classes).
    2. Klik Tambah Kelas → isi Tingkat, Jurusan, Rombel, (opsional) Wali Kelas → Simpan.
    3. Setelah ada minimal 1 kelas, buka Schedule Builder → dropdown Kelas terisi → pilih kelas → Open Builder.

Jadi masalahnya bukan “tidak ada tempat input”, melainkan:

  • User belum pernah mengisi kelas di halaman Classes, atau
  • Menu Classes tidak terlihat (mis. karena tidak login sebagai ADMIN).

Rekomendasi: Di halaman Schedule Builder index bisa ditambah kalimat singkat: “Jika dropdown kosong, tambah dulu kelas di Academic → Classes.”


7. Ringkasan Kondisi Project

Aspek Status Keterangan
Module Academic (Classes, Students, Subjects, Teachers, Schedules, Lesson Slots) Sudah jadi CRUD API + halaman dashboard per entitas
Module Attendance Sudah jadi attendance_sessions, check-in, report
Module Schedule (jadwal per kelas) Sudah jadi Schedule Builder, bulk save, lesson_slots
Module DapodikSync Sudah jadi Sync siswa, mapping rombel → class, halaman Dapodik
Tabel classes, students, schedules, attendance_sessions Sudah jadi Struktur + relasi jelas (termasuk lesson_slots, subjects, dapodik_rombel_mappings)
Input kelas manual Sudah jadi Halaman Classes, form lengkap
Schedule Builder pakai data kelas Sudah jadi Dari GET /api/academic/classes
Halaman Students Sudah jadi Route, controller, view, API, paginasi, filter
Dropdown kelas kosong ⚠️ Setengah jadi Fitur jalan; kosong karena belum ada data kelas di DB
Dapodik sebagai sumber master kelas ⚠️ Setengah jadi Saat ini Dapodik hanya sync siswa + mapping rombel → class. Kelas internal tetap buat manual di Classes; belum ada “sync rombel → buat kelas otomatis”

8. Arsitektur saran: Dapodik sebagai sumber utama master data

Target alur: DAPODIK → Sync → Classes → Students → Schedule → Attendance.

Kondisi saat ini

  • Classes: input manual; tidak ada sync dari Dapodik.
  • Students: bisa dari Dapodik (sync siswa + mapping rombel → class_id). class_id bisa NULL (unmapped).
  • Schedule & Attendance: sudah mengandalkan classes + students.

Opsi arsitektur

Opsi A — Kelas tetap manual (minimal change)

  • Tetap: Classes diisi manual (grade + major + rombel).
  • Dapodik: sync siswa + mapping dapodik_rombel → class_id.
  • Sesuai jika: rombel Dapodik banyak dan Anda ingin satu rombel Dapodik = satu kelas internal yang sudah Anda buat manual.

Opsi B — Sync rombel Dapodik → buat/update kelas (disarankan untuk “Dapodik sumber utama”)

  1. Tambah sync kelas/rombel dari Dapodik

    • Endpoint Dapodik: daftar rombongan belajar (rombel) per sekolah.
    • Logic: untuk setiap rombel Dapodik, buat atau update satu baris di classes (mis. parse nama rombel jadi grade + major + name/rombel), plus tetap isi dapodik_rombel_mappings (dapodik_rombel → class_id) agar siswa sync bisa map ke kelas yang sama.
    • Aturan: satu dapodik_rombel = satu class_id; kelas bisa dibuat otomatis dari nama rombel Dapodik (mis. "10 IPA 1" → grade=10, major=IPA, name=1).
  2. Urutan sync disarankan

    • Sync rombel/kelas dulu (baca Dapodik → insert/update classes + dapodik_rombel_mappings).
    • Lalu sync siswa (seperti sekarang); mapping rombel → class_id sudah terisi, sehingga siswa dapat class_id otomatis.
  3. Tetap boleh edit manual

    • Halaman Classes tetap dipakai untuk koreksi/naming (grade, major, rombel, wali).
    • Setelah sync, admin bisa ubah nama/struktur kelas jika perlu.

Opsi C — Hybrid (seperti B + flag sumber)

  • Tambah kolom mis. source (manual / dapodik) di classes supaya bisa bedakan kelas yang dari Dapodik vs yang buat manual.

Rekomendasi singkat

  • Langkah 1: Pastikan ada data kelas (manual) dulu agar Schedule Builder dan dropdown siswa tidak kosong.
  • Langkah 2: Jika ingin Dapodik sebagai sumber utama kelas, tambah sync rombel Dapodik → classes (Opsi B); jadwalkan sync rombel dulu, baru sync siswa.
  • Langkah 3: Tetap pakai Dapodik Sync yang sudah ada untuk siswa dan mapping rombel → class; setelah kelas bisa dari Dapodik, mapping itu akan mengisi class_id siswa tanpa perlu input kelas manual dulu.

Dengan ini, arsitektur bergerak ke: DAPODIK → Sync (rombel + siswa) → Classes & Students terisi → Schedule (manual di builder) → Attendance.