Lewati ke isi

CBT Exam Workspace & Enrollment — Implementation Plan

Tanggal: 2026-06-11
Versi: 1.2
Status: Active — Phase 1–3 selesai
Mode: Server · Root: /home/scola/odoo

Dokumen acuan

Dokumen Peran
docs/ai-guidelines/development-guide.md Workflow QC & commit
docs/ai-guidelines/architecture-api.md Same-origin API
docs/domains/cbt/README.md SSOT domain CBT
docs/domains/cbt/fe-be-question-exam-sync-recon-2026-05-27.md Kontrak FE/BE §5.5–5.6
docs/domains/cbt/cbt-qa-runbook-2026-05-28.md Diagnosa enroll independent
docs/qa/cbt-independent-admission-uat-end-to-end.md UAT admission/independent
docs/user-guide/quick-start/buat-ujian-cbt.md Quick start operator

1. Latar belakang & masalah

1.1 Gejala operasional (sebelum perbaikan)

  • Guru membuat ujian Independent, memilih rombel, mengira siswa otomatis terdaftar — padahal enroll batch hanya jalan saat create dan satu rombel.
  • Halaman /faculty/cbt/exams/:id terasa read-only + modal terfragmentasi; penambahan peserta internal satu per satu.
  • Import Peserta hanya bulk untuk peserta external (Nama,KODE), bukan siswa sekolah.
  • Dropdown rombel menampilkan [CBT] Independent / [CBT] Admission — rombel teknis sistem, bukan kelompok peserta.
  • Admission seharusnya sync dari SPMB; UI detail masih menampilkan pola manual seperti independent.

1.2 Root cause (audit teknis — historis)

Lapisan Temuan awal Status setelah Phase 1–3
BE _seed_independent_participants_from_batch hanya di create_exam ✅ API enroll-batches post-create
BE lookup/batches mengembalikan rombel [CBT]* ✅ Filter purpose=enrollment
BE Import tidak resolve NIS/NISN ✅ Resolve nid/nsn/student_id
FE Monolith detail + Edit modal terfragmentasi ✅ Tab workspace + Pengaturan inline
FE Create form duplikat detail ✅ Create ringkas → redirect tab Pengaturan

1.3 Target UX (best practice — tercapai)

Satu Exam Management Workspace per ujian dengan:

  1. Tab Ringkasan — status, token, checklist siap publish
  2. Tab Pengaturan — semua field editable (dengan lock per state)
  3. Tab PesertaEnrollment Center (multi-rombel, import internal/external, bulk block/remove)
  4. Tab Penilaian — reuse section existing

Context-aware:

  • Independent → Enrollment Center penuh
  • Admission → panel Integrasi SPMB (read-only peserta + link sync)
  • Learning → attendee dari rombel (existing)

1.4 Route workspace (Phase 3)

Route Tab default Catatan
/faculty/cbt/exams/:examId overview Faculty independent/admission
/faculty/cbt/exams/:examId/settings settings Redirect setelah create ringkas
/faculty/cbt/exams/:examId/participants participants Deep-link enrollment
/faculty/cbt/exams/:examId/grading grading Deep-link penilaian
/admin/spmb/cbt/exams/:examId/:tab? sama SPMB admin
/admin-staff/admissions/cbt/exams/:examId/:tab? sama Admin staff SPMB

Konstanta tab: src/constants/cbtExamWorkspace.js (overview, settings, participants, grading).


2. Arsitektur target

flowchart LR
  subgraph fe ["Frontend"]
    List["CBTExamList<br/>create ringkas"]
    Workspace["CBTExamDetail<br/>Kelola Ujian + Tabs"]
    Enroll["CBTExamEnrollmentPanel"]
    Checklist["CBTExamPublishChecklist"]
    Admission["CBTExamAdmissionSyncPanel"]
  end

  subgraph be ["Backend scola_cbt"]
    Lookup["lookup/batches?purpose=enrollment"]
    EnrollAPI["participants/enroll-batches"]
    BulkAPI["participants/bulk-state|bulk-remove"]
    ImportAPI["participants/import"]
    Seed["_seed_independent_participants_from_batch"]
  end

  List -->|"redirect settings"| Workspace
  Workspace --> Enroll
  Workspace --> Checklist
  Workspace --> Admission
  Enroll --> Lookup
  Enroll --> EnrollAPI
  Enroll --> BulkAPI
  Enroll --> ImportAPI
  EnrollAPI --> Seed

3. Fase implementasi

Phase 1 — P0 Quick wins ✅

ID Item BE FE Acceptance
P1-01 Filter rombel teknis [CBT]* dari dropdown enrollment Dropdown enroll tidak menampilkan [CBT] Independent/Admission
P1-02 min_marks + remedial di form edit KKM dapat diedit saat draft/schedule (tab Pengaturan)
P1-03 Rename UX: Detail → Kelola Ujian; Participant → Peserta Label konsisten Bahasa Indonesia
P1-04 Import internal: NIS/NISN per baris Paste NIS/NISN → participant student
P1-05 Checklist siap publish + empty state actionable Banner peringatan jika independent tanpa peserta
P1-06 Admission: panel Integrasi SPMB Tombol manual import disembunyikan; hint sync jadwal

Phase 2 — P1 Enrollment Center ✅

ID Item BE FE Acceptance
P2-01 API POST .../participants/enroll-batches Multi-rombel post-create; dry_run preview
P2-02 student_count di lookup batches enrollment Preview jumlah siswa per rombel
P2-03 Tab workspace di detail ujian AppTabs: Ringkasan, Pengaturan, Peserta, Penilaian
P2-04 Komponen CBTExamEnrollmentPanel Multi-select rombel + enroll + import tabs
P2-05 Lookup siswa by batch_id Filter siswa saat tambah manual per rombel

Phase 3 — P2 Polish ✅

ID Item Catatan Status
P3-01 Create ringkas → redirect workspace Tab Pengaturan Modal create: nama + context + tipe + question set
P3-02 Bulk block/remove peserta (checkbox multi-select) API bulk-state / bulk-remove + panel
P3-03 E2E multi-rombel enroll → student schedule SM-CBT-008
P3-04 Sub-route /exams/:id/:tab? Sync tab ↔ URL via cbtExamWorkspace.js
P3-05 CSV upload template download Unduh template + upload file di import modal

4. Kontrak API baru / diperluas

4.1 POST /api/scola_cbt/lookup/batches

Params tambahan:

{
  "active_only": true,
  "limit": 100,
  "purpose": "enrollment"
}

Perilaku purpose=enrollment:

  • Exclude batch dengan name diawali [CBT] (rombel teknis non-learning).
  • Response tambahan: student_count per batch.

4.2 POST /api/scola_cbt/exams/<exam_id>/participants/enroll-batches

Request:

{
  "batch_ids": [12, 15, 18],
  "skip_existing": true,
  "dry_run": false
}

Response:

{
  "success": true,
  "data": {
    "batch_count": 3,
    "created": 85,
    "skipped": 2,
    "failed": 0,
    "details": [
      { "batch_id": 12, "batch_name": "8A", "created": 32, "skipped": 0 }
    ]
  }
}

Guard:

  • Hanya exam_context === 'independent'.
  • State exam: draft atau schedule (tidak saat held/done).
  • User: author/proctor manager/CBT manager (sama dengan create participant).

4.3 POST /api/scola_cbt/exams/<exam_id>/participants/import

Row extended (internal):

{ "identity_type": "student", "nid": "3275081501120001" }
{ "identity_type": "student", "nsn": "0057348291" }
{ "identity_type": "student", "student_id": 42 }

Backend resolve nid/nsnstudent_id sebelum get_or_create_for_student.

4.4 POST /api/scola_cbt/lookup/students

Params tambahan: batch_id (optional) — filter siswa by rombel.

4.5 POST /api/scola_cbt/exams/<exam_id>/participants/bulk-state

Request:

{
  "participant_ids": [1, 2, 3],
  "state": "blocked"
}

Guard: sama dengan enroll-batches (independent, draft/schedule).

4.6 POST /api/scola_cbt/exams/<exam_id>/participants/bulk-remove

Request:

{
  "participant_ids": [1, 2, 3]
}

Response: summary removed, deactivated, failed (attempt aktif dinonaktifkan, bukan hard-delete).


5. Perubahan frontend (file map)

File Perubahan
src/constants/cbtExamWorkspace.js Baru — tab valid + helper route params
src/services/cbt/examService.js listEnrollmentBatches, enrollParticipantsFromBatches, listCbtStudents, bulkUpdateParticipantState, bulkRemoveParticipants
src/components/CBT/CBTExamEnrollmentPanel.vue Enrollment center: multi-rombel, import, bulk, CSV template
src/components/CBT/CBTExamPublishChecklist.vue Readiness checklist publish
src/components/CBT/CBTExamAdmissionSyncPanel.vue Hint SPMB sync
src/views/ExamManagement/Faculty/Exam/CBTExamDetail.vue Tabs workspace, tab Pengaturan inline, route sync
src/views/ExamManagement/Faculty/Exam/CBTExamList.vue Create ringkas, redirect settings
src/router/teacherRouteFragments/assessment.js Route :examId/:tab(overview\|settings\|participants\|grading)?
src/router/admissionsRoutes.js Route tab sama untuk SPMB/admin-staff
tests/e2e/smoke/cbt_independent_enrollment.spec.ts SM-CBT-008 multi-rombel enroll
tests/e2e/helpers/cbt.ts fetchEnrollmentBatchIds, enrollExamBatches

6. Perubahan backend (file map)

File Perubahan
scola_cbt/controllers/cbt_api.py Shared _seed_independent_participants_from_batch
scola_cbt/controllers/exam.py Delegate ke shared seed
scola_cbt/controllers/participant.py enroll_batches, bulk-state, bulk-remove, resolve nid/nsn import
scola_cbt/controllers/exam_lookup_api.py Filter [CBT]*, student_count, batch_id filter students
scola_cbt/tests/test_participant_enrollment_unit.py Unit test enroll-batches seed
scola_cbt/__manifest__.py 17.0.1.0.12 (Phase 2), 17.0.1.0.13 (bulk Phase 3)

7. Aturan edit per state exam

Field draft schedule held done
Nama, question set, jadwal, durasi, KKM
Shuffle, show result, remedial
Enroll rombel / import peserta
Bulk block/remove peserta
Token regenerate ⚠️ policy
Publish / transition

8. Alur operator (Independent — setelah Phase 3)

  1. Buat ujian di /faculty/cbt/exams → modal ringkas (nama, context, tipe, question set).
  2. Redirect otomatis ke tab Pengaturan → lengkapi jadwal, durasi, KKM, opsi CBT → Simpan Pengaturan.
  3. Tab Peserta → pilih satu atau lebih rombel → Daftarkan dari rombel (preview opsional).
  4. Alternatif: import NIS/NISN (internal) atau Nama,KODE (external) via modal import + template CSV.
  5. Tab Ringkasan → cek checklist publish → transisi draft → schedule → held.
  6. Siswa internal: /student/cbt — peserta external: /cbt/public.

9. QC gates

Backend

python3 -m py_compile custom_addons_scola/gcgscola/scola_cbt/controllers/*.py
python3 custom_addons_scola/gcgscola/scola_cbt/tests/test_participant_enrollment_unit.py
# + existing scola_cbt unit suites

Frontend

cd scola-fe-v2
npm run lint:diff
npm run type-check
npm run build
npx playwright test tests/e2e/smoke/cbt_independent_enrollment.spec.ts --workers=1

Manual smoke (Independent)

  1. Buat ujian independent → redirect tab Pengaturan → simpan jadwal.
  2. Tab Peserta → multi-rombel → Daftarkan dari rombel.
  3. Login siswa → /student/cbt → ujian muncul.
  4. Import NIS/NISN internal + external Nama,KODE; unduh/upload template CSV.
  5. Bulk block/remove via checkbox tabel peserta.
  6. Negative: rombel [CBT]* tidak muncul di dropdown enrollment.

Manual smoke (Admission)

  1. Detail ujian admission → panel SPMB, tanpa tombol import manual.
  2. Sync peserta dari /admin/spmb/test tab CBT Admission.

10. Risiko & mitigasi

Risiko Mitigasi
Enroll massal duplikat get_or_create_for_student + skip_existing
Enroll saat ujian sudah held API reject state held/done
Performance multi-rombel besar Batch loop per rombel; audit log metadata
Regression learning/admission Context guard di setiap endpoint baru
Bulk remove saat attempt aktif Deactivate participant, bukan hard-delete

11. Definisi selesai (Phase 1–3)

  • [x] Dokumen plan (file ini)
  • [x] API enroll-batches + lookup filter (BE 17.0.1.0.12)
  • [x] FE workspace tabs + enrollment panel
  • [x] Unit test enroll seed (test_participant_enrollment_unit.py)
  • [x] Phase 3: create ringkas, tab Pengaturan, route tab, bulk peserta, CSV import, E2E SM-CBT-008
  • [ ] Manual smoke P1-01–P3-05 PASS (operator)
  • [x] UAT doc diperbarui (cbt-manual-uat.md §9, quick-start, domain README)

12. Riwayat

Tanggal Versi Perubahan
2026-06-13 1.0 Dokumen awal + kickoff implementasi Phase 1–2
2026-06-11 1.1 Phase 3 polish: tab Pengaturan, create ringkas, bulk peserta, route tab, E2E SM-CBT-008
2026-06-11 1.2 Dokumentasi diselaraskan: API bulk, alur operator, definisi selesai Phase 1–3