Rapikan tampilan nilai, ganti NPM->NIM, fitur ganti password, kunci RPS view-only
- Tampilan "Isi Per Komponen Penilaian" diganti dari tombol bertumpuk teks jadi tabel (Komponen/Sub-CPMK/Bobot/Status/Aksi) dengan status berupa stempel, lebih mudah dipindai. - Filter pencarian MK (ketik kode/nama) di kotak penugasan dosen /admin. - Istilah NPM diseragamkan jadi NIM di seluruh aplikasi (label, header, template Excel, dokumen portofolio), termasuk migrasi kolom database mahasiswa.npm -> nim yang aman (ALTER TABLE RENAME COLUMN, otomatis saat startup, tanpa kehilangan data; parser Excel tetap terima file lama berheader NPM). - Fitur ganti password mandiri (/akun): verifikasi password lama, sesi lain otomatis keluar setelah berhasil, sesi yang dipakai tetap aktif. - RPS: dosen RPS+MK kini bisa menyesuaikan redaksi kalimat Sub-CPMK (bagian D) untuk MK yang diampu -- kode & kaitan CPMK/CPL tetap dari kurikulum, hanya teksnya yang bisa disesuaikan. Penyesuaian otomatis konsisten di dropdown mingguan (F), checklist komponen (G), serta unduhan RPS & portofolio, tanpa menyentuh data kurikulum induk atau halaman nilai/ dashboard prodi. - Form RPS dibungkus <fieldset disabled> untuk dosen tanpa hak edit -- seluruh field benar-benar terkunci (bukan cuma tombol simpan hilang).
This commit is contained in:
@@ -265,12 +265,12 @@ def build_portofolio(d: dict) -> bytes:
|
||||
skor_sub = d.get("skor_sub", {})
|
||||
if nilai.get("mode") == "per_mahasiswa":
|
||||
mhs = nilai.get("mahasiswa", [])
|
||||
akhir = {a["npm"]: a["akhir"] for a in d.get("akhir", [])}
|
||||
akhir = {a["nim"]: a["akhir"] for a in d.get("akhir", [])}
|
||||
kol_sub = [s["kode"] for s in subs]
|
||||
tf = doc.add_table(rows=2 + len(mhs) + 3, cols=3 + len(kol_sub) + 1)
|
||||
_borders(tf)
|
||||
_hdr(tf.cell(0, 0), "No.")
|
||||
_hdr(tf.cell(0, 1), "NPM")
|
||||
_hdr(tf.cell(0, 1), "NIM")
|
||||
_hdr(tf.cell(0, 2), "Nama")
|
||||
for j, sk in enumerate(kol_sub):
|
||||
_hdr(tf.cell(0, 3 + j), sk, size=7)
|
||||
@@ -285,13 +285,13 @@ def build_portofolio(d: dict) -> bytes:
|
||||
align=WD_ALIGN_PARAGRAPH.CENTER)
|
||||
for i, m in enumerate(mhs, 2):
|
||||
_ct(tf.cell(i, 0), str(i - 1), size=8, align=WD_ALIGN_PARAGRAPH.CENTER)
|
||||
_ct(tf.cell(i, 1), m.get("npm", ""), size=8)
|
||||
_ct(tf.cell(i, 1), m.get("nim", ""), size=8)
|
||||
_ct(tf.cell(i, 2), m.get("nama", ""), size=8)
|
||||
for j, sk in enumerate(kol_sub):
|
||||
v = (m.get("skor") or {}).get(sk)
|
||||
_ct(tf.cell(i, 3 + j), _f(v, 0) if v is not None else "",
|
||||
size=8, align=WD_ALIGN_PARAGRAPH.CENTER)
|
||||
_ct(tf.cell(i, 3 + len(kol_sub)), _f(akhir.get(m.get("npm", "")), 1),
|
||||
_ct(tf.cell(i, 3 + len(kol_sub)), _f(akhir.get(m.get("nim", "")), 1),
|
||||
size=8, bold=True, align=WD_ALIGN_PARAGRAPH.CENTER)
|
||||
# baris statistik per sub
|
||||
base = 2 + len(mhs)
|
||||
|
||||
Reference in New Issue
Block a user