Revisi Implementasi Decision Tree untuk Penomoran Surat Otomatis
1. Latar Belakang
Sistem penomoran surat otomatis saat ini masih menggunakan increment sederhana (nomor_terakhir + 1). Untuk meningkatkan akurasi dan memberikan kontribusi akademik yang lebih berbobot, Node 3 (penentuan nomor urut) akan menggunakan Full Decision Tree (scikit-learn) dengan multi-feature, bukan counter biasa.
2. Ruang Lingkup Perubahan
| Area |
File |
Perubahan |
| eLaDesSkripsiML |
ml_model.py |
Rombak: tambah DecisionTreeClassifier + fitur multi untuk DecisionTreeRegressor |
|
elades_mysql.py |
Tambah auto-klasifikasi, kode surat, counter dengan FOR UPDATE, orchestrator |
|
app.py |
Update endpoint /api/proses-nomor/<id>, tambah /api/retrain |
| eLaDesSkripsi |
3 Migration baru |
Tambah kolom ke jenis_surat, pengajuan, dan tabel nomor_surat_counters |
3. Decision Tree Flow
Root: jenis_surat_id tersedia?
├── Tidak → Error return
└── Ya → Fetch jenis_surat dari MySQL
│
├── Node 1: KLASIFIKASI SURAT
│ ├── Cek jenis_surat.kategori
│ │ ├── Ada → gunakan itu
│ │ └── Tidak → Python keyword matching:
│ │ ├── "pernyataan" → "Surat Pernyataan"
│ │ ├── "pengantar" → "Surat Pengantar"
│ │ ├── "keterangan" → "Surat Keterangan"
│ │ └── default → "Surat Keterangan"
│ └── Output: klasifikasi_surat
│
├── Node 2: KODE SURAT
│ ├── jenis_surat.kode_surat ada?
│ │ ├── Ya → gunakan kode_surat
│ │ └── Tidak → default:
│ │ ├── Surat Keterangan → "SK"
│ │ ├── Surat Pengantar → "SP"
│ │ └── Surat Pernyataan → "SPT"
│ └── Output: kode_surat
│
├── Node 3: FULL DECISION TREE — NOMOR URUT
│ ├── Tentukan periode:
│ │ ├── reset_periode = "bulanan" → filter (jenis, klasifikasi, BULAN, TAHUN)
│ │ └── reset_periode = "tahunan" → filter (jenis, klasifikasi, TAHUN)
│ ├── Ambil existing numbers (FOR UPDATE lock)
│ ├── Cek gap: ada nomor yang loncat?
│ │ ├── Ya → pakai nomor gap pertama (isi celah)
│ │ └── Tidak → Full Decision Tree prediction
│ ├── Siapkan fitur training multi-dimensi
│ ├── Train DecisionTreeRegressor
│ ├── Predict nomor berikutnya
│ ├── Validasi: cek duplikat via FOR UPDATE
│ └── Output: nomor_urut
│
├── Node 4: FORMAT NOMOR SURAT
│ ├── format_nomor dari jenis_surat
│ ├── Replace: {NO_URUT} {KODE} {BULAN_ROM} {TAHUN}
│ └── Output: nomor_terformat
│
└── SAVE: UPDATE pengajuan
├── nomor_surat = nomor_urut
├── klasifikasi_surat = hasil Node 1
├── kode_surat = hasil Node 2
└── tanggal_surat = NOW()
4. Fitur Multi-Dimensi untuk DecisionTreeRegressor
| Fitur |
Keterangan |
bulan |
Bulan pengajuan (1-12) |
tahun |
Tahun pengajuan |
index_ke |
Urutan ke berapa dalam sequence |
jumlah_dalam_periode |
Total surat dalam periode yang sama |
selisih_hari |
Selisih hari dari pengajuan sebelumnya |
5. Endpoint API
| Endpoint |
Method |
Fungsi |
/api/proses-nomor/<id> |
POST |
Decision Tree lengkap: klasifikasi + kode + nomor urut + format |
/api/retrain |
POST |
Retrain model setelah ada jenis_surat baru |
/api/health |
GET |
Cek kesehatan server |
6. Output Response
{
"success": true,
"nomor_surat": "001/SKD/VI/2026",
"nomor_urut": 1,
"klasifikasi_surat": "Surat Keterangan",
"kode_surat": "SKD",
"message": "Nomor surat berhasil diproses"
}