diff --git a/CHANGELOG.md b/CHANGELOG.md index bc0effd..5b4aaba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -47,6 +47,7 @@ _None yet._ - **Per-student detail page (ENH-021, #66):** new `GET /mahasiswa/detail/(:any)` → `Mahasiswa::detail()` renders a single student's full biodata record (all columns from `GetBiodataMahasiswa`) read-only, with a "Detail" button added to each row in the Mahasiswa list. Reuses the `fetchBiodata($id)` single-record fetch shared with `edit()`. - **Pagination & UI/UX refinements on menu pages (ENH-022, #68):** the three NeoFeeder menu pages (Mahasiswa, Aktivitas Kuliah, Mahasiswa Lulus/DO) gained a page-size selector (10/20/50/100), a "Halaman X dari Y" indicator with total count (via `GetCount*` endpoints), First/Prev/Next/Last links, and accessible ` diff --git a/app/Views/verifikasi_ipk/index.php b/app/Views/verifikasi_ipk/index.php new file mode 100644 index 0000000..cc2e0ba --- /dev/null +++ b/app/Views/verifikasi_ipk/index.php @@ -0,0 +1,47 @@ +
+
+
+
+

Verifikasi IPK

+
+
+
+
+ +
+
+ +
+ + + +
+ Terdapat sesi verifikasi IPK yang belum selesai. + Lanjutkan +
+ + +
+
+ + +
+
Unggah Excel
+
+
+ +
+ + +
+ Gunakan template Graduation (nim, nama, tgl_keluar, ipk, nilai_skripsi). + Hanya kolom nim dan ipk yang dibaca. IPK Excel dianggap benar + dan akan menimpa IPK semester terakhir yang aktif di Neo Feeder. +
+
+ +
+
+
+
+
diff --git a/app/Views/verifikasi_ipk/results.php b/app/Views/verifikasi_ipk/results.php new file mode 100644 index 0000000..6dc60a3 --- /dev/null +++ b/app/Views/verifikasi_ipk/results.php @@ -0,0 +1,44 @@ +
+
+
+
+

Verifikasi IPK — Hasil

+
+
+
+
+ +
+
+
+ Verifikasi selesai. Berikut ringkasan pengiriman ke Neo Feeder. +
+ + +
Tidak ada data diproses.
+ +
+
+ + + + + + + + + + + +
NIMStatusKeterangan
Berhasil' : 'Gagal' ?>
+
+
+ + + +
+
diff --git a/app/Views/verifikasi_ipk/verification.php b/app/Views/verifikasi_ipk/verification.php new file mode 100644 index 0000000..29a8757 --- /dev/null +++ b/app/Views/verifikasi_ipk/verification.php @@ -0,0 +1,100 @@ +
+
+
+
+

Verifikasi IPK

+
+
+
+
+ +
+
+ +
+
Hasil batch sebelumnya
+
+ + + + + + + + + + + +
NIMStatusKeterangan
Berhasil' : 'Gagal' ?>
+
+
+ + +
+ +
+
+ Batch dari mahasiswa +
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
#NIMNamaIPK Neo FeederIPK ExcelSemesterStatusPerbaiki
Tidak ada data pada batch ini.
+ + Cocok + + Beda + + Semester non-aktif + + Tidak ditemukan + + + + + + + +
+
+ +
+
+
+
diff --git a/docs/IMPROVEMENTS.md b/docs/IMPROVEMENTS.md index b16be1e..23f938b 100644 --- a/docs/IMPROVEMENTS.md +++ b/docs/IMPROVEMENTS.md @@ -207,3 +207,14 @@ The label is encoded directly in the ID prefix. When a valid item becomes a GitH - **Actual Implemented:** Added a `nilai_skripsi` column (letter grade) to the Excel template — `EXCEL_HEADERS`, `downloadTemplate()` (header + example `A`), and `parseExcel()` (stored uppercased on each student record). Added `NeoFeeder::updateNilaiPerkuliahanKelas($token, $idRegistrasi, $idKelas, $record)` using `sendMutation('UpdateNilaiPerkuliahanKelas', ...)` with composite key `id_registrasi_mahasiswa` + `id_kelas_kuliah` (key schema verified live via GetDictionary: key `id_registrasi_mahasiswa` + `id_kelas_kuliah`, record `nilai_huruf`/`nilai_angka`/`nilai_indeks`). In `Graduation::finish()`, for each saved student with a non-empty `nilai_skripsi`, the thesis/skripsi course is re-resolved via `getCekTranskripMahasiswa`; a new private helper `findMissingGradeThesis()` finds the thesis row whose grade is currently missing (`hasGrade == false` — `nilai_huruf`/`nilai_angka` empty) and returns its `id_reg_pd`/`id_kls` from the cloud row (both verified live on real data), then `updateNilaiPerkuliahanKelas` is called with only `record.nilai_huruf` = the Excel value. The push happens only when the grade is still missing; noise results are reported in the finish guidance. In `wizard.php` card 3, a thesis row without a grade now shows the Excel value with a "(akan diisi)" tag instead of a bare "Belum ada nilai" when a value was provided. - **Changes:** The Excel template now carries an optional `nilai_skripsi` letter-grade column. A registered-but-ungraded thesis/skripsi course is filled in with the Excel letter grade at submission (`finish()`), only when it currently has no grade; students without a value in that column are left untouched. Card 3 indicates which thesis rows will be filled in. - **Changes:** The Excel template now carries an optional `nilai_skripsi` letter-grade column. A registered-but-ungraded thesis/skripsi course is filled in with the Excel letter grade at submission (`finish()`), only when it currently has no grade; students without a value in that column are left untouched. Card 3 indicates which thesis rows will be filled in. + +### ENH-011 — Verify and fix last-semester IPK in bulk via Excel +- **Status:** `implemented` +- **Issue:** #115 +- **Recorded:** 2026-08-31 +- **Implemented:** 2026-08-31 +- **Problem:** Several (possibly all) students have a last-semester `ipk` that is not up to date in Neo Feeder. The graduation wizard only surfaces the last-semester IPK for the students being processed one at a time; there is no dedicated screen to bulk-verify and correct the last-semester IPK across many students against an external source. +- **Possible Fix:** Add a dedicated read-only "Verifikasi IPK" menu that takes an Excel file (Graduation template: `nim` + `ipk` columns), reads each student's last-semester `ipk` from Neo Feeder (`getAktivitasKuliahMahasiswa`, largest `id_semester`), shows a comparison (Neo Feeder IPK vs Excel IPK, cocok/beda) batch-by-batch, lets the admin tick the rows to fix, and pushes `updatePerkuliahanMahasiswa(['ipk' => ...])` only to the **active** last semester (`a_periode_aktif=1`, ENH-007 rule). State stored in a cache + resume cookie separate from the graduation `WizardProgress` so the two do not collide. Processing is batch-by-batch (one `getAktivitasKuliahMahasiswa` call per student) to avoid the 60 s PHP time limit. +- **Actual Fix:** Added `VerifikasiIpk` controller (`/verifikasi-ipk`, batch-by-batch comparison) + `VerifikasiIpkStore` library (cache prefix `ipk_verif_`, resume cookie `ipk_verif_resume`), routes, sidebar menu, and views (`index`/`verification`/`results`). The push uses a full `UpdatePerkuliahanMahasiswa` record — the whole active last-semester row from `getAktivitasKuliahMahasiswa` (minus the key) plus `id_pembiayaan` resolved via `GetListRiwayatPendidikanMahasiswa` and the `ipk` overridden with the Excel value — because Neo Feeder rejects partial records (`id_status_mahasiswa`, `biaya_kuliah_smt`, `id_pembiayaan` all demanded even though the GetDictionary schema lists only `id_status_mahasiswa` as NOT NULL). Per-row results (success/failure with the Neo Feeder error message) are shown on the `results` page. `apply()` uses `set_time_limit(0)` for large batches. +- **Actual Implemented:** 2026-08-31 +- **Changes:** New `app/Controllers/VerifikasiIpk.php`, `app/Libraries/VerifikasiIpkStore.php`, `app/Views/verifikasi_ipk/*`; `NeoFeeder.php` gained `getListRiwayatPendidikanMahasiswa()`; routes + sidebar menu added.