# Model Data dan Domain

Data peserta wisuda mencatat kehadiran sesuai istilah kampus serta referensi dan tanggal sertifikat acara secara terpisah dari ijazah akademik. Pembaruan dicatat di audit dan tidak mengubah status kelulusan.

## Entitas inti (konseptual)
- Organisasi: fakultas/unit, program studi, pengguna, peran, izin.
- Periode: tahun akademik, semester, kalender, periode registrasi.
- Kurikulum: versi kurikulum, mata kuliah, prasyarat, mata kuliah kurikulum.
- Orang: calon mahasiswa, mahasiswa, dosen, profil dan dokumen terbatas.
- Kegiatan belajar: kelas/penawaran mata kuliah, jadwal, ruang, KRS, presensi, komponen dan hasil nilai.
- Layanan: tagihan, transaksi pembayaran, bantuan/aktivitas kemahasiswaan, tugas akhir, bimbingan, yudisium, wisuda.
- Integrasi: mapping kode eksternal, outbox/sinkronisasi, percobaan, hasil, rekonsiliasi.
- Tata kelola: audit event, konfigurasi, arsip/retensi.

## Relasi penting
Mahasiswa terhubung ke satu program studi dan angkatan; KRS menghubungkan mahasiswa dengan penawaran kelas pada semester. Penawaran kelas terhubung ke mata kuliah, dosen, jadwal. Nilai terkait pendaftaran kelas dan periode. Tugas akhir, yudisium, dan wisuda memiliki status serta riwayat. Kardinalitas final harus mengikuti aturan kampus.

## Aturan penyimpanan
- Gunakan primary key internal stabil; kode akademik eksternal unik sesuai lingkup dan dapat berubah hanya melalui proses terkendali.
- Gunakan foreign key, unique constraint, indeks yang sesuai query, timestamps, dan transaksi.
- Simpan uang sebagai integer satuan rupiah atau decimal yang disepakati; jangan gunakan floating point.
- Simpan waktu konsisten dan tampilkan sesuai `Asia/Makassar`; kebijakan penyimpanan UTC perlu dipastikan.
- Data nilai/keuangan yang telah disahkan tidak dihapus biasa; gunakan koreksi berizin dan audit.
- Arsip dokumen sensitif secara privat dengan metadata akses dan retensi.

## Migrasi dan data PDDikti
Model eksternal dipisahkan dari model lokal melalui tabel mapping dan adapter. Jangan menetapkan nama field/metode Feeder tanpa dokumentasi resmi yang cocok dengan versi kampus. Lihat [Neo Feeder](09-neo-feeder.md).

### Ketentuan integrasi
Jangan gunakan ID Feeder sebagai primary key domain SIAKAD. Gunakan mapping eksternal terpisah, simpan status sinkronisasi per record/per periode, dan jalankan impor melalui staging serta review operator. Skema payload berada di adapter versioned, bukan menjadi struktur tabel domain. Sumber kebenaran dan konflik ditentukan per entitas/field sebelum sinkronisasi dua arah.

### Domain yang dipisahkan
Rancangan awal memisahkan orang/mahasiswa dari riwayat pendidikan per prodi, serta mata kuliah dari kurikulum dan anggota kurikulum, kelas dari penugasan dosen/peserta, nilai kelas dari ringkasan aktivitas kuliah per semester, dan status kelulusan dari profil mahasiswa. Rincian method dan mapping sementara ada di [mapping awal Feeder](17-mapping-feeder-awal.md).

## Terbuka
Format NIM, identitas nasional, retensi, soft delete, serta aturan historisasi harus disepakati. Satu instalasi dimiliki satu kampus; konfigurasi institusi boleh disimpan sebagai profil tunggal dan dapat diubah saat setup. Jangan memasukkan data nyata ke fixture atau dokumentasi.

Rincian entitas konseptual, constraints, dan pemisahan MVP ada di [blueprint database dan urutan MVP](18-blueprint-database-mvp.md). Nama tabel di blueprint adalah usulan konseptual, bukan migration final.

## Implementasi fondasi saat ini
Migration awal membuat `institution_profiles` (satu profil yang dipakai per instalasi) dan `academic_periods`. Profil menyimpan identitas/alamat kontak umum. Periode menyimpan tahun akademik, nama semester yang dapat disesuaikan kampus, tanggal mulai/akhir, catatan, dan penanda aktif; kombinasi tahun akademik + nama semester unik. Waktu buka dan tutup KRS opsional disimpan berpasangan sebagai waktu lokal aplikasi (`Asia/Makassar`) dan, jika diatur, membatasi pembuatan/perubahan/pengajuan KRS di server. Kode institusi tetap opsional sampai sumber resmi kampus dipastikan. Ini belum memodelkan semua identitas/field referensi Neo Feeder.

Migration akses menambahkan status aktif pengguna dan tabel `roles`, `permissions`, `role_user`, serta `permission_role`. Pengguna lama dinonaktifkan saat kolom status dibuat; pembuatan superadmin dilakukan melalui command tanpa akun/kata sandi demo. Lihat [RBAC](08-rbac.md).

Master akademik saat ini memakai `organizational_units` dan `study_programs`. Keduanya memiliki `local_code` internal unik; jenjang dan jenis unit disimpan sebagai label kampus. `study_programs.organizational_unit_id` opsional agar struktur kampus yang tidak memakai fakultas tetap dapat dimodelkan. Data ini belum menyimpan ID/payload Neo Feeder; gunakan tabel external mapping terpisah setelah kontrak resmi diverifikasi.

Katalog memakai `courses` yang tidak terikat langsung pada satu program studi; keterkaitannya akan ditetapkan oleh versi kurikulum. SKS disimpan dengan satu angka desimal dan jenis mata kuliah sebagai label lokal. `academic_calendar_events` terhubung ke `academic_periods`, menyimpan jenis agenda dan rentang tanggal, serta memakai status batal agar agenda dapat dipertahankan. Rentang kalender tidak dipaksa berada di antara tanggal mulai/akhir semester karena pendaftaran dan persiapan dapat terjadi sebelum semester.

Versi kurikulum memakai `curricula` yang mengikat satu program studi ke satu periode mulai berlaku. Hanya draf yang dapat diedit; saat terbit, susunan dikunci. `curriculum_courses` menyimpan semester rekomendasi, kelompok lokal, sifat wajib/pilihan, dan snapshot SKS agar perubahan katalog berikutnya tidak mengubah kurikulum terbit. ID/method Feeder tetap di external mapping terpisah.

Penawaran kelas pada `course_offerings` mengikat satu periode akademik dengan satu mata kuliah dari kurikulum terbit. Identitas kelas, kapasitas, catatan, dan status rencana/dibuka/ditutup/dibatalkan disimpan lokal. Jadwal, dosen, dan pendaftaran mahasiswa disimpan pada entitas terkait; sinkronisasi Feeder belum menjadi bagian tabel domain ini.

Ruang disimpan dalam `rooms`; pertemuan berulang mingguan berada di `class_meetings` dengan hari, jam lokal, ruang, dosen opsional, dan label sesi. Bentrok waktu pada ruang maupun dosen dalam periode sama serta bentrok jadwal pada kelas yang sama ditolak. Kebijakan lintas-periode dan penjadwalan khusus harus dievaluasi saat kebutuhan kampus dipetakan.

Identitas dosen lokal tersimpan pada `lecturers` dengan kode internal, nama, kontak opsional, dan label kepegawaian lokal. ID dosen Neo Feeder tidak disimpan di kolom ini; pemetaan eksternal tetap menjadi tanggung jawab lapisan integrasi.

Identitas mahasiswa dan riwayat program studi dipisahkan: `students` menyimpan NIM/kode lokal dan kontak, sedangkan `student_academic_records` menyimpan program, periode masuk/keluar, dan status. KRS berada di `study_plans` per mahasiswa/periode dengan kelas pada `study_plan_courses`. Kapasitas hanya dihitung sebagai terisi setelah KRS diajukan atau disetujui. Batas maksimum SKS dan aturan prasyarat belum diputuskan kampus.

Presensi awal memakai `class_sessions` untuk setiap tanggal pertemuan dalam satu penawaran kelas, dan `attendance_records` untuk status per mahasiswa pada pertemuan tersebut. Satu kelas tidak boleh memiliki dua pertemuan pada tanggal yang sama; satu mahasiswa hanya memiliki satu catatan per pertemuan. Peserta diambil dari KRS berstatus disetujui. Status awal mencakup hadir, tidak hadir, terlambat, dan izin; kebijakan bukti izin, koreksi yang sudah disahkan, serta ambang minimum kehadiran masih perlu ditetapkan.

Pengaturan tunggal `academic_rules` menyimpan batas SKS semester, kebijakan perhitungan percobaan ulang untuk IPK, dan presisi angka IPK. Semua nilai boleh kosong; perilaku yang belum diputuskan tidak ditebak. Batas SKS yang diisi diterapkan saat kelas ditambahkan dan KRS diajukan. Kebijakan IPK yang lengkap membuka perhitungan IPK berdasarkan nilai bobot mutu tersimpan.

Penilaian memakai `grade_sheets` sebagai status pengajuan kelas, `assessment_components` untuk komponen dan bobot, serta `assessment_scores` untuk skor per mahasiswa/per komponen. `grading_scales` menyimpan label, rentang skor, bobot mutu, dan status lulus yang dapat dikonfigurasi kampus; rentang tumpang tindih ditolak. Persetujuan menyimpan nilai numerik serta hasil konversi sebagai snapshot pada `course_final_grades`. Perubahan skala tidak mengganti konversi historis yang sudah tersimpan. Lembar yang sudah diajukan atau disetujui tidak dapat diedit; lembar yang dikembalikan dapat diperbaiki dan diajukan ulang.

Ringkasan hasil studi membaca KRS yang disetujui dan nilai akhir yang sudah disetujui per pendaftaran. Rata-rata numerik dan bobot mutu ditimbang menurut SKS hanya atas mata kuliah yang memiliki konversi; halaman menampilkan total SKS KRS, SKS bernilai, serta SKS berbobot mutu secara terpisah. Laporan program/status menghitung riwayat akademik, bukan mahasiswa unik; mahasiswa dengan beberapa riwayat dapat muncul lebih dari sekali. Ini belum menerapkan rumus resmi IPS/IPK atau format transkrip kampus.

PMB memakai `admission_cycles` untuk periode, jadwal, serta status buka/tutup dan `admission_applications` untuk data pendaftar, program pilihan, cap waktu persetujuan pemrosesan, status proses, petugas peninjau, dan tautan konversi mahasiswa. Siklus terkait periode akademik sebagai periode masuk; konversi mempertahankan kode pendaftaran dan mencatat mahasiswa hasil registrasi. Dokumen disimpan privat pada tabel `admission_documents`; pembayaran dan aturan seleksi khusus menunggu kebijakan kampus.

Register tugas akhir awal disimpan di `student_final_projects`: mahasiswa, topik, pembimbing opsional, tahap/status bebas sesuai kebijakan kampus, tanggal mulai/selesai, dan catatan. Log bimbingan berada di `final_project_consultations` dengan tanggal, dosen opsional, ringkasan, tindak lanjut, dan pencatat. Isi topik/catatan tidak disalin ke nilai audit. Record ini bukan sumber keputusan akademik lulus; persetujuan proposal, ujian, syarat yudisium, dan wisuda belum dimodelkan.

Kasus yudisium disimpan di `yudisium_cases` per riwayat pendidikan mahasiswa, dengan pengaju, peninjau, status, periode/tanggal/referensi keputusan, dan catatan. `yudisium_case_events` menyimpan riwayat pengajuan, pengembalian, persetujuan, dan pengajuan ulang; isi catatan tidak disalin ke log audit. Persetujuan memperbarui status riwayat pendidikan menjadi lulus dan periode keluar dalam transaksi yang sama. Hanya status aktif dapat diajukan; syarat kelulusan lain masih diperiksa manual.

Acara wisuda disimpan di `graduation_events`; `graduation_registrations` menghubungkan acara dengan kasus yudisium disetujui dan mencatat operator/waktu pendaftaran. Indeks unik mencegah pendaftaran ganda pada acara yang sama. Pendaftaran peserta tidak mengubah status akademik; status kehadiran dan referensi/tanggal sertifikat acara dapat dicatat, namun bukan nomor atau dokumen ijazah. Pembatalan, biaya, dan kapasitas belum tersedia.

Pencatatan keuangan awal memakai `student_bills` untuk referensi tagihan manual per mahasiswa dan `student_bill_payments` untuk pembayaran parsial. Nilai IDR disimpan sebagai bilangan bulat. Pembayaran melebihi sisa tagihan ditolak di dalam transaksi dengan penguncian tagihan. Pembatalan mengubah status catatan pembayaran dan menyimpan alasan/pelaku/waktu, tidak menghapus baris lama. Belum ada tarif otomatis, tagihan berkala, pengembalian dana, atau rekonsiliasi bank/payment gateway.

`audit_logs` mencatat aktor, waktu, aksi, jenis/ID entitas, nama field, serta nilai sebelum/sesudah untuk daftar atribut akademik yang diizinkan. Nilai nama, email, telepon, kode identitas pribadi, token, dan kredensial tidak dicatat. Audit bersifat append-only dari aplikasi; retensi dan proteksi tingkat database/backup harus dikonfigurasi sebelum produksi.

Dokumen PMB disimpan pada `admission_documents` dengan relasi ke pendaftar, nama/path privat acak, jenis MIME hasil deteksi, ukuran, dan waktu unggah. Berkas berada di disk `local` (`storage/app/private`), tidak memiliki URL publik, dan hanya dapat diunduh melalui route berizin yang memeriksa relasi dokumen-aplikasi. Aturan retensi dan penghapusan harus ditetapkan kampus.

Catatan kegiatan/prestasi awal disimpan di `student_activities` dengan mahasiswa, jenis, judul, penyelenggara, rentang tanggal, hasil, catatan, dan pencatat. Catatan bebas tidak disalin ke nilai audit. Modul ini tidak menyimpan perkara konseling/disiplin atau dokumen sensitif.

Fondasi integrasi memakai `external_record_mappings` untuk memasangkan ID lokal dengan ID eksternal tanpa mengganti primary key SIAKAD. `integration_batches` dan `integration_batch_items` menyimpan arah, versi kontrak/mapping, status, fingerprint, hitungan hasil, dan error yang telah diredaksi; payload mentah dan token tidak disimpan. Tabel ini belum dipakai untuk request ke Feeder.
