tukar nama MB Ipoh Perak kepada MBIP
This commit is contained in:
722
manual/generate_manual.py
Normal file
722
manual/generate_manual.py
Normal file
@@ -0,0 +1,722 @@
|
||||
"""
|
||||
Penjana Manual Pengguna eCert MBIP
|
||||
Format: Microsoft Word (.docx)
|
||||
"""
|
||||
|
||||
from docx import Document
|
||||
from docx.shared import Pt, Cm, RGBColor, Inches
|
||||
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
||||
from docx.enum.table import WD_TABLE_ALIGNMENT
|
||||
from docx.oxml.ns import qn
|
||||
from docx.oxml import OxmlElement
|
||||
import datetime
|
||||
|
||||
BASE_URL = "https://mysijil.mbip.my"
|
||||
|
||||
doc = Document()
|
||||
|
||||
# ── Margin halaman ────────────────────────────────────────────────────────────
|
||||
for section in doc.sections:
|
||||
section.top_margin = Cm(2.5)
|
||||
section.bottom_margin = Cm(2.5)
|
||||
section.left_margin = Cm(3.0)
|
||||
section.right_margin = Cm(2.5)
|
||||
|
||||
# ── Helpers ───────────────────────────────────────────────────────────────────
|
||||
def add_heading(text, level=1):
|
||||
h = doc.add_heading(text, level=level)
|
||||
h.runs[0].font.color.rgb = RGBColor(0x1a, 0x3a, 0x6b)
|
||||
return h
|
||||
|
||||
def add_body(text):
|
||||
p = doc.add_paragraph(text)
|
||||
p.runs[0].font.size = Pt(11)
|
||||
return p
|
||||
|
||||
def add_bullet(text):
|
||||
p = doc.add_paragraph(text, style='List Bullet')
|
||||
p.runs[0].font.size = Pt(11)
|
||||
return p
|
||||
|
||||
def add_screenshot_box(caption, url, height_cm=7):
|
||||
"""Kotak placeholder untuk tangkapan skrin."""
|
||||
doc.add_paragraph()
|
||||
|
||||
# Jadual satu sel sebagai kotak
|
||||
tbl = doc.add_table(rows=1, cols=1)
|
||||
tbl.alignment = WD_TABLE_ALIGNMENT.CENTER
|
||||
cell = tbl.cell(0, 0)
|
||||
|
||||
# Warna latar
|
||||
tc = cell._tc
|
||||
tcPr = tc.get_or_add_tcPr()
|
||||
shd = OxmlElement('w:shd')
|
||||
shd.set(qn('w:val'), 'clear')
|
||||
shd.set(qn('w:color'), 'auto')
|
||||
shd.set(qn('w:fill'), 'EEF2FF')
|
||||
tcPr.append(shd)
|
||||
|
||||
# Tinggi sel
|
||||
trPr = tbl.rows[0]._tr.get_or_add_trPr()
|
||||
trHeight = OxmlElement('w:trHeight')
|
||||
trHeight.set(qn('w:val'), str(int(height_cm * 567)))
|
||||
trHeight.set(qn('w:hRule'), 'exact')
|
||||
trPr.append(trHeight)
|
||||
|
||||
# Teks dalam kotak
|
||||
p = cell.paragraphs[0]
|
||||
p.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
run = p.add_run(f"\n\n[ TANGKAPAN SKRIN ]\n\n{caption}")
|
||||
run.font.size = Pt(10)
|
||||
run.font.color.rgb = RGBColor(0x64, 0x74, 0x8B)
|
||||
run.font.italic = True
|
||||
|
||||
# Label URL
|
||||
p2 = doc.add_paragraph()
|
||||
p2.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
run2 = p2.add_run(f"URL: {url}")
|
||||
run2.font.size = Pt(9)
|
||||
run2.font.color.rgb = RGBColor(0x1a, 0x56, 0xa0)
|
||||
run2.font.italic = True
|
||||
doc.add_paragraph()
|
||||
|
||||
def add_note(text):
|
||||
p = doc.add_paragraph()
|
||||
p.add_run("Nota: ").bold = True
|
||||
run = p.add_run(text)
|
||||
run.font.size = Pt(10)
|
||||
run.font.italic = True
|
||||
p.paragraph_format.left_indent = Cm(0.5)
|
||||
|
||||
def page_break():
|
||||
doc.add_page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# HALAMAN TAJUK
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
doc.add_paragraph()
|
||||
doc.add_paragraph()
|
||||
doc.add_paragraph()
|
||||
|
||||
t = doc.add_paragraph("eCert MBIP")
|
||||
t.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
r = t.runs[0]
|
||||
r.font.size = Pt(32)
|
||||
r.font.bold = True
|
||||
r.font.color.rgb = RGBColor(0x1a, 0x3a, 0x6b)
|
||||
|
||||
t2 = doc.add_paragraph("Sistem Pengurusan Sijil Digital")
|
||||
t2.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
r2 = t2.runs[0]
|
||||
r2.font.size = Pt(18)
|
||||
r2.font.color.rgb = RGBColor(0x1a, 0x3a, 0x6b)
|
||||
|
||||
doc.add_paragraph()
|
||||
|
||||
t3 = doc.add_paragraph("MANUAL PENGGUNA — PENTADBIR")
|
||||
t3.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
r3 = t3.runs[0]
|
||||
r3.font.size = Pt(16)
|
||||
r3.font.bold = True
|
||||
r3.font.color.rgb = RGBColor(0x55, 0x55, 0x55)
|
||||
|
||||
doc.add_paragraph()
|
||||
doc.add_paragraph()
|
||||
|
||||
t4 = doc.add_paragraph("Majlis Bandaraya Ipoh Perak (MBIP)")
|
||||
t4.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
t4.runs[0].font.size = Pt(12)
|
||||
|
||||
t5 = doc.add_paragraph(f"Versi 1.0 · {datetime.date.today().strftime('%B %Y')}")
|
||||
t5.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
||||
t5.runs[0].font.size = Pt(11)
|
||||
t5.runs[0].font.color.rgb = RGBColor(0x88, 0x88, 0x88)
|
||||
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# ISI KANDUNGAN (placeholder manual)
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("Isi Kandungan", level=1)
|
||||
|
||||
toc_items = [
|
||||
("1", "Pengenalan"),
|
||||
("2", "Log Masuk ke Sistem"),
|
||||
("3", "Dashboard Utama"),
|
||||
("4", "Pengurusan Program"),
|
||||
(" 4.1", "Cipta Program Baru"),
|
||||
(" 4.2", "Kemaskini Maklumat Program"),
|
||||
(" 4.3", "Tetapan Check-in dan Muat Turun"),
|
||||
(" 4.4", "Publish dan Tutup Program"),
|
||||
("5", "Pengurusan Peserta"),
|
||||
(" 5.1", "Lihat Senarai Peserta"),
|
||||
(" 5.2", "Tambah Peserta Satu-Satu"),
|
||||
(" 5.3", "Import Peserta dari Excel"),
|
||||
(" 5.4", "Export Senarai Peserta"),
|
||||
("6", "Kod QR Check-in"),
|
||||
("7", "Template Sijil"),
|
||||
(" 7.1", "Muat Naik Template"),
|
||||
(" 7.2", "Konfigurasi Kedudukan Teks"),
|
||||
(" 7.3", "Jana Pratonton Sijil"),
|
||||
("8", "Soalselidik Program"),
|
||||
("9", "Pengurusan Sijil"),
|
||||
("10", "Statistik Program"),
|
||||
("11", "Set Soalselidik"),
|
||||
(" 11.1", "Cipta Set Soalselidik"),
|
||||
(" 11.2", "Tambah dan Urus Soalan"),
|
||||
("12", "Pengurusan Pengguna (Super Admin)"),
|
||||
("13", "Profil Pengguna"),
|
||||
]
|
||||
|
||||
for num, title in toc_items:
|
||||
p = doc.add_paragraph()
|
||||
p.paragraph_format.left_indent = Cm(0.5) if num.startswith(" ") else Cm(0)
|
||||
r = p.add_run(f"{num.strip()} {title}")
|
||||
r.font.size = Pt(11)
|
||||
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 1: PENGENALAN
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("1. Pengenalan")
|
||||
add_body(
|
||||
"eCert MBIP ialah sistem pengurusan sijil digital yang dibangunkan untuk Majlis Bandaraya Ipoh Perak (MBIP). "
|
||||
"Sistem ini membolehkan pentadbir mengurus program, menguruskan peserta, menjana sijil digital secara automatik, "
|
||||
"dan mengumpul maklum balas peserta melalui soalselidik dalam talian."
|
||||
)
|
||||
doc.add_paragraph()
|
||||
add_body("Fungsi utama sistem:")
|
||||
add_bullet("Pengurusan program dan peserta")
|
||||
add_bullet("Check-in peserta melalui kod QR")
|
||||
add_bullet("Jana dan hantar sijil digital secara automatik")
|
||||
add_bullet("Pengurusan template sijil")
|
||||
add_bullet("Kutipan maklum balas melalui soalselidik")
|
||||
add_bullet("Laporan statistik kehadiran dan penyertaan")
|
||||
doc.add_paragraph()
|
||||
add_body("Manual ini ditujukan kepada pentadbir sistem (Admin dan Super Admin) untuk menggunakan semua fungsi yang tersedia.")
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 2: LOG MASUK
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("2. Log Masuk ke Sistem")
|
||||
add_body("Untuk mengakses sistem eCert MBIP, pentadbir perlu log masuk menggunakan alamat emel dan kata laluan yang telah diberikan.")
|
||||
doc.add_paragraph()
|
||||
add_body("Langkah-langkah log masuk:")
|
||||
add_bullet(f"Buka pelayar web dan pergi ke: {BASE_URL}/login")
|
||||
add_bullet("Masukkan Alamat Emel yang berdaftar.")
|
||||
add_bullet("Masukkan Kata Laluan.")
|
||||
add_bullet("Klik butang Log Masuk.")
|
||||
doc.add_paragraph()
|
||||
|
||||
add_screenshot_box(
|
||||
"Halaman Log Masuk — Borang emel dan kata laluan",
|
||||
f"{BASE_URL}/login"
|
||||
)
|
||||
|
||||
add_note(
|
||||
"Jika terlupa kata laluan, klik pautan 'Terlupa Kata Laluan?' di bawah borang log masuk. "
|
||||
"Pautan set semula kata laluan akan dihantar ke alamat emel yang didaftarkan."
|
||||
)
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 3: DASHBOARD
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("3. Dashboard Utama")
|
||||
add_body(
|
||||
"Selepas log masuk, pentadbir akan dibawa ke halaman Dashboard. Dashboard memaparkan ringkasan aktiviti sistem "
|
||||
"termasuk jumlah program aktif, jumlah peserta, dan sijil yang dijana."
|
||||
)
|
||||
doc.add_paragraph()
|
||||
add_body("Elemen pada Dashboard:")
|
||||
add_bullet("Jumlah program yang sedang aktif")
|
||||
add_bullet("Senarai program terkini")
|
||||
add_bullet("Pautan pantas ke fungsi utama")
|
||||
|
||||
add_screenshot_box(
|
||||
"Dashboard Utama — Ringkasan statistik dan senarai program",
|
||||
f"{BASE_URL}/admin/dashboard"
|
||||
)
|
||||
|
||||
add_body("Bar navigasi di sebelah kiri (sidebar) menyediakan akses pantas ke semua modul sistem.")
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 4: PENGURUSAN PROGRAM
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("4. Pengurusan Program")
|
||||
add_body(
|
||||
"Modul Program adalah teras sistem eCert MBIP. Setiap program mewakili satu acara atau kursus yang dianjurkan. "
|
||||
"Pentadbir boleh mencipta, mengemaskini, dan mengurus status program dari modul ini."
|
||||
)
|
||||
|
||||
add_screenshot_box(
|
||||
"Senarai Program — Semua program yang telah dicipta",
|
||||
f"{BASE_URL}/admin/programs"
|
||||
)
|
||||
|
||||
# 4.1
|
||||
add_heading("4.1 Cipta Program Baru", level=2)
|
||||
add_body("Langkah-langkah mencipta program baru:")
|
||||
add_bullet("Klik butang + Cipta Program di halaman Senarai Program.")
|
||||
add_bullet("Isi maklumat program:")
|
||||
|
||||
fields_program = [
|
||||
("Tajuk Program", "Nama program atau acara (wajib)"),
|
||||
("Penerangan", "Huraian ringkas program"),
|
||||
("Tarikh Mula / Tamat", "Tarikh pelaksanaan program"),
|
||||
("Lokasi", "Tempat program diadakan"),
|
||||
("Benarkan Walk-in", "Aktifkan jika peserta luar dibenarkan daftar semasa check-in"),
|
||||
]
|
||||
for field, desc in fields_program:
|
||||
p = doc.add_paragraph()
|
||||
p.paragraph_format.left_indent = Cm(1)
|
||||
r1 = p.add_run(f"{field}: ")
|
||||
r1.bold = True
|
||||
r1.font.size = Pt(11)
|
||||
p.add_run(desc).font.size = Pt(11)
|
||||
|
||||
add_bullet("Klik Simpan untuk menyimpan program.")
|
||||
|
||||
add_screenshot_box(
|
||||
"Borang Cipta Program Baru — Isi maklumat program",
|
||||
f"{BASE_URL}/admin/programs/create"
|
||||
)
|
||||
|
||||
# 4.2
|
||||
add_heading("4.2 Kemaskini Maklumat Program", level=2)
|
||||
add_body(
|
||||
"Untuk mengedit program sedia ada, klik ikon Edit (pensel) pada senarai program atau klik nama program "
|
||||
"kemudian pilih tab Butiran."
|
||||
)
|
||||
add_screenshot_box(
|
||||
"Halaman Butiran Program — Tab maklumat, peserta, template, soalselidik, sijil",
|
||||
f"{BASE_URL}/admin/programs/{{uuid}}"
|
||||
)
|
||||
|
||||
# 4.3
|
||||
add_heading("4.3 Tetapan Check-in dan Muat Turun", level=2)
|
||||
add_body("Pentadbir perlu menetapkan waktu check-in dan tempoh muat turun sijil dalam tetapan program:")
|
||||
|
||||
settings_table = [
|
||||
("Mula Check-in", "Tarikh dan masa check-in dibuka untuk peserta"),
|
||||
("Tamat Check-in", "Tarikh dan masa check-in ditutup"),
|
||||
("Mula Muat Turun Sijil", "Peserta boleh muat turun sijil selepas tempoh ini"),
|
||||
("Tamat Muat Turun Sijil", "Tempoh muat turun sijil tamat"),
|
||||
]
|
||||
for field, desc in settings_table:
|
||||
p = doc.add_paragraph()
|
||||
p.paragraph_format.left_indent = Cm(1)
|
||||
r1 = p.add_run(f"{field}: ")
|
||||
r1.bold = True
|
||||
r1.font.size = Pt(11)
|
||||
p.add_run(desc).font.size = Pt(11)
|
||||
|
||||
add_note("Semua masa menggunakan waktu Malaysia (MYT, UTC+8).")
|
||||
|
||||
# 4.4
|
||||
add_heading("4.4 Publish dan Tutup Program", level=2)
|
||||
add_body("Program perlu di-publish sebelum peserta dapat menggunakan pautan check-in QR.")
|
||||
add_bullet("Klik butang Publish untuk mengaktifkan program. Status bertukar kepada Aktif.")
|
||||
add_bullet("Klik butang Tutup untuk menamatkan program. Peserta tidak lagi dapat check-in.")
|
||||
add_note("Program yang telah ditutup tidak boleh dibuka semula secara automatik.")
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 5: PENGURUSAN PESERTA
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("5. Pengurusan Peserta")
|
||||
add_body("Modul Peserta membolehkan pentadbir mengurus senarai peserta bagi setiap program.")
|
||||
|
||||
# 5.1
|
||||
add_heading("5.1 Lihat Senarai Peserta", level=2)
|
||||
add_body("Klik tab Peserta dalam halaman butiran program untuk melihat semua peserta berdaftar.")
|
||||
add_body("Maklumat yang dipaparkan:")
|
||||
add_bullet("Nama peserta")
|
||||
add_bullet("No. Kad Pengenalan")
|
||||
add_bullet("Status check-in (Hadir / Belum Hadir)")
|
||||
add_bullet("Status sijil (Belum Jana / Dijana / Dihantar)")
|
||||
add_bullet("Sumber pendaftaran (Pra-daftar / Walk-in)")
|
||||
|
||||
add_screenshot_box(
|
||||
"Senarai Peserta — Status kehadiran dan sijil setiap peserta",
|
||||
f"{BASE_URL}/admin/programs/{{uuid}}/participants"
|
||||
)
|
||||
|
||||
# 5.2
|
||||
add_heading("5.2 Tambah Peserta Satu-Satu", level=2)
|
||||
add_body("Untuk menambah peserta secara manual:")
|
||||
add_bullet("Klik butang + Tambah Peserta.")
|
||||
add_bullet("Isi Nama Penuh dan No. Kad Pengenalan (12 digit).")
|
||||
add_bullet("Isi maklumat tambahan jika perlu (emel, telefon, agensi).")
|
||||
add_bullet("Klik Simpan.")
|
||||
|
||||
add_screenshot_box(
|
||||
"Borang Tambah Peserta — Isi maklumat peserta",
|
||||
f"{BASE_URL}/admin/programs/{{uuid}}/participants/create"
|
||||
)
|
||||
|
||||
# 5.3
|
||||
add_heading("5.3 Import Peserta dari Excel", level=2)
|
||||
add_body("Untuk mendaftar ramai peserta sekaligus:")
|
||||
add_bullet("Klik butang Import Excel.")
|
||||
add_bullet("Muat turun templat Excel yang disediakan.")
|
||||
add_bullet("Isi maklumat peserta dalam templat (Nama, No. KP, Emel, Telefon, Agensi).")
|
||||
add_bullet("Muat naik semula fail Excel yang telah diisi.")
|
||||
add_bullet("Semak ringkasan import dan klik Sahkan.")
|
||||
|
||||
add_screenshot_box(
|
||||
"Halaman Import Peserta — Muat naik fail Excel",
|
||||
f"{BASE_URL}/admin/programs/{{uuid}}/participants/import"
|
||||
)
|
||||
add_note("Sistem akan abaikan baris yang No. KP-nya sudah wujud dalam program yang sama.")
|
||||
|
||||
# 5.4
|
||||
add_heading("5.4 Export Senarai Peserta", level=2)
|
||||
add_body("Klik butang Export Excel untuk memuat turun senarai lengkap peserta beserta status check-in dan sijil ke dalam fail Excel.")
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 6: KOD QR CHECK-IN
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("6. Kod QR Check-in")
|
||||
add_body(
|
||||
"Setiap program mempunyai Kod QR unik yang digunakan peserta untuk check-in. "
|
||||
"Peserta mengimbas kod ini menggunakan telefon pintar untuk mendaftarkan kehadiran."
|
||||
)
|
||||
add_body("Cara menjana dan menggunakan Kod QR:")
|
||||
add_bullet("Klik tab Kod QR dalam halaman butiran program.")
|
||||
add_bullet("Klik Jana QR Code jika belum dijana.")
|
||||
add_bullet("Paparkan Kod QR pada skrin besar atau cetak untuk peserta mengimbas.")
|
||||
add_bullet("Klik Muat Turun untuk menyimpan imej Kod QR.")
|
||||
|
||||
add_screenshot_box(
|
||||
"Halaman Kod QR — Jana, papar, dan muat turun QR Code",
|
||||
f"{BASE_URL}/admin/programs/{{uuid}}/qr"
|
||||
)
|
||||
|
||||
add_note(
|
||||
"Kod QR boleh dinyahaktifkan (Deactivate) dan dijana semula jika diperlukan. "
|
||||
"Kod lama tidak akan berfungsi selepas dinyahaktifkan."
|
||||
)
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 7: TEMPLATE SIJIL
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("7. Template Sijil")
|
||||
add_body(
|
||||
"Modul Template Sijil membolehkan pentadbir menyediakan reka bentuk sijil yang akan digunakan "
|
||||
"untuk menjana sijil digital peserta."
|
||||
)
|
||||
|
||||
# 7.1
|
||||
add_heading("7.1 Muat Naik Template", level=2)
|
||||
add_body("Langkah-langkah muat naik template sijil:")
|
||||
add_bullet("Klik tab Template Sijil dalam halaman butiran program.")
|
||||
add_bullet("Klik butang Pilih Fail dan pilih imej template (format JPG atau PNG, maksimum 10MB).")
|
||||
add_bullet("Resolusi disyorkan: 1754 × 1240 piksel (A4 landscape) atau 1240 × 1754 piksel (portrait).")
|
||||
add_bullet("Klik Muat Naik.")
|
||||
|
||||
add_screenshot_box(
|
||||
"Halaman Muat Naik Template — Pilih fail imej sijil",
|
||||
f"{BASE_URL}/admin/programs/{{uuid}}/template"
|
||||
)
|
||||
|
||||
# 7.2
|
||||
add_heading("7.2 Konfigurasi Kedudukan Teks", level=2)
|
||||
add_body(
|
||||
"Selepas template dimuat naik, pentadbir perlu menetapkan kedudukan teks pada sijil. "
|
||||
"Koordinat dikira dari sudut kiri atas imej (piksel)."
|
||||
)
|
||||
add_body("Medan yang boleh dikonfigurasi:")
|
||||
|
||||
config_fields = [
|
||||
("Nama Peserta", "Kedudukan X, Y, saiz font, warna, dan penjajaran (kiri/tengah/kanan)"),
|
||||
("No. IC", "Saiz font No. IC yang dipaparkan di bawah nama"),
|
||||
("No. Sijil (Pilihan)", "Aktifkan togol 'Papar' untuk menambah No. Sijil pada sijil. Tetapkan kedudukan X, Y."),
|
||||
]
|
||||
for field, desc in config_fields:
|
||||
p = doc.add_paragraph()
|
||||
p.paragraph_format.left_indent = Cm(1)
|
||||
r1 = p.add_run(f"{field}: ")
|
||||
r1.bold = True
|
||||
r1.font.size = Pt(11)
|
||||
p.add_run(desc).font.size = Pt(11)
|
||||
|
||||
add_bullet("Klik Simpan Konfigurasi untuk menyimpan tetapan.")
|
||||
|
||||
add_screenshot_box(
|
||||
"Konfigurasi Template — Tetapkan kedudukan teks nama dan No. Sijil",
|
||||
f"{BASE_URL}/admin/programs/{{uuid}}/template"
|
||||
)
|
||||
|
||||
# 7.3
|
||||
add_heading("7.3 Jana Pratonton Sijil", level=2)
|
||||
add_body("Untuk menyemak kedudukan teks sebelum menjana sijil sebenar:")
|
||||
add_bullet("Masukkan nama contoh dalam kotak Jana Pratonton.")
|
||||
add_bullet("Klik butang Pratonton.")
|
||||
add_bullet("Imej pratonton akan dipaparkan dengan teks pada koordinat yang ditetapkan.")
|
||||
add_note("Pratonton menggunakan nilai koordinat terkini walaupun belum disimpan.")
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 8: SOALSELIDIK PROGRAM
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("8. Soalselidik Program")
|
||||
add_body(
|
||||
"Pentadbir boleh mengaitkan set soalselidik dengan program. Peserta akan diminta mengisi soalselidik "
|
||||
"selepas check-in sebelum sijil boleh dimuat turun."
|
||||
)
|
||||
add_body("Cara mengaitkan soalselidik dengan program:")
|
||||
add_bullet("Klik tab Soalselidik dalam halaman butiran program.")
|
||||
add_bullet("Pilih Set Soalselidik yang ingin digunakan daripada senarai tersedia.")
|
||||
add_bullet("Klik Lampirkan Soalselidik.")
|
||||
add_bullet("Klik Sahkan untuk mengesahkan penggunaan soalselidik ini.")
|
||||
add_bullet("Klik Pratonton untuk melihat soalan yang akan dijawab peserta.")
|
||||
|
||||
add_screenshot_box(
|
||||
"Halaman Soalselidik Program — Lampirkan dan pratonton soalselidik",
|
||||
f"{BASE_URL}/admin/programs/{{uuid}}/questionnaire"
|
||||
)
|
||||
|
||||
add_note("Soalselidik yang telah disahkan tidak boleh ditukar. Sah kan hanya apabila sudah pasti.")
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 9: PENGURUSAN SIJIL
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("9. Pengurusan Sijil")
|
||||
add_body(
|
||||
"Modul Sijil membolehkan pentadbir menjana dan menghantar sijil digital kepada semua peserta yang hadir."
|
||||
)
|
||||
add_body("Fungsi yang tersedia:")
|
||||
add_bullet("Jana Semua Sijil — Menjana sijil untuk semua peserta yang telah check-in.")
|
||||
add_bullet("Hantar Emel Semua — Menghantar sijil kepada peserta melalui emel secara pukal.")
|
||||
add_body("Status sijil setiap peserta:")
|
||||
|
||||
status_sijil = [
|
||||
("Belum Jana", "Sijil belum dijana untuk peserta ini"),
|
||||
("Dijana", "Sijil sudah dijana dan sedia untuk dihantar"),
|
||||
("Dihantar", "Sijil telah dihantar melalui emel"),
|
||||
("Dimuat Turun", "Peserta telah memuat turun sijil mereka"),
|
||||
]
|
||||
for status, desc in status_sijil:
|
||||
p = doc.add_paragraph()
|
||||
p.paragraph_format.left_indent = Cm(1)
|
||||
r1 = p.add_run(f"{status}: ")
|
||||
r1.bold = True
|
||||
r1.font.size = Pt(11)
|
||||
p.add_run(desc).font.size = Pt(11)
|
||||
|
||||
add_screenshot_box(
|
||||
"Halaman Sijil — Senarai sijil dan fungsi jana/hantar pukal",
|
||||
f"{BASE_URL}/admin/programs/{{uuid}}/certificates"
|
||||
)
|
||||
|
||||
add_note("Pastikan template sijil telah dikonfigurasi terlebih dahulu sebelum menjana sijil.")
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 10: STATISTIK PROGRAM
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("10. Statistik Program")
|
||||
add_body(
|
||||
"Halaman Statistik memaparkan data analitik terperinci bagi setiap program. "
|
||||
"Pentadbir boleh memantau prestasi program melalui laporan yang disediakan."
|
||||
)
|
||||
add_body("Data yang dipaparkan:")
|
||||
add_bullet("Jumlah peserta berdaftar vs. jumlah yang hadir")
|
||||
add_bullet("Pecahan mengikut sesi (Slot masa check-in)")
|
||||
add_bullet("Pecahan mengikut sumber pendaftaran (Pra-daftar / Walk-in)")
|
||||
add_bullet("Status sijil (Dijana, Dihantar, Dimuat Turun)")
|
||||
add_bullet("Keputusan soalselidik (jika soalselidik dikaitkan)")
|
||||
|
||||
add_screenshot_box(
|
||||
"Halaman Statistik — Graf dan data analitik program",
|
||||
f"{BASE_URL}/admin/programs/{{uuid}}/statistics"
|
||||
)
|
||||
|
||||
add_body("Klik butang Export Excel untuk memuat turun laporan statistik dalam format Excel.")
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 11: SET SOALSELIDIK
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("11. Set Soalselidik")
|
||||
add_body(
|
||||
"Modul Set Soalselidik membolehkan pentadbir membina borang soalan yang boleh digunakan semula "
|
||||
"merentasi pelbagai program."
|
||||
)
|
||||
|
||||
add_screenshot_box(
|
||||
"Senarai Set Soalselidik — Semua set yang telah dicipta",
|
||||
f"{BASE_URL}/admin/questionnaires"
|
||||
)
|
||||
|
||||
# 11.1
|
||||
add_heading("11.1 Cipta Set Soalselidik", level=2)
|
||||
add_body("Langkah-langkah mencipta set soalselidik baru:")
|
||||
add_bullet("Klik butang + Cipta Set Soalselidik.")
|
||||
add_bullet("Masukkan Nama Set dan Penerangan (pilihan).")
|
||||
add_bullet("Klik Simpan.")
|
||||
|
||||
add_screenshot_box(
|
||||
"Borang Cipta Set Soalselidik — Nama dan penerangan",
|
||||
f"{BASE_URL}/admin/questionnaires/create"
|
||||
)
|
||||
|
||||
# 11.2
|
||||
add_heading("11.2 Tambah dan Urus Soalan", level=2)
|
||||
add_body("Selepas set dicipta, tambah soalan melalui halaman butiran set soalselidik.")
|
||||
add_body("Jenis soalan yang tersedia:")
|
||||
|
||||
jenis_soalan = [
|
||||
("Tajuk (Seksyen)", "Pengepala bahagian — boleh menjadi parent kepada soalan Rating"),
|
||||
("Rating (1-5)", "Penilaian skala 1 hingga 5 — mesti diletakkan di bawah Tajuk"),
|
||||
("Pilihan Tunggal", "Peserta pilih satu jawapan sahaja"),
|
||||
("Pilihan Berganda", "Peserta boleh pilih lebih dari satu jawapan"),
|
||||
("Teks Pendek", "Jawapan dalam satu baris"),
|
||||
("Teks Panjang", "Jawapan berbilang baris"),
|
||||
]
|
||||
for jenis, desc in jenis_soalan:
|
||||
p = doc.add_paragraph()
|
||||
p.paragraph_format.left_indent = Cm(1)
|
||||
r1 = p.add_run(f"{jenis}: ")
|
||||
r1.bold = True
|
||||
r1.font.size = Pt(11)
|
||||
p.add_run(desc).font.size = Pt(11)
|
||||
|
||||
add_screenshot_box(
|
||||
"Halaman Set Soalselidik — Senarai soalan dan borang tambah soalan",
|
||||
f"{BASE_URL}/admin/questionnaires/{{id}}"
|
||||
)
|
||||
|
||||
add_body("Ciri-ciri tambahan:")
|
||||
add_bullet("Soalan Rating: Pentadbir boleh tetapkan label teks untuk setiap nilai (1-5) pada peringkat Tajuk.")
|
||||
add_bullet("Susunan soalan boleh diubah dengan seret-dan-lepas (drag-and-drop).")
|
||||
add_bullet("Soalan Rating tidak boleh dipindahkan keluar dari Tajuk induknya.")
|
||||
add_bullet("Tetapkan soalan sebagai Wajib atau tidak wajib.")
|
||||
|
||||
add_note(
|
||||
"Set soalselidik perlu di-Publish sebelum boleh dikaitkan dengan program. "
|
||||
"Selepas di-Publish, soalan tidak boleh diubah."
|
||||
)
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 12: PENGURUSAN PENGGUNA (SUPER ADMIN)
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("12. Pengurusan Pengguna")
|
||||
add_body(
|
||||
"Modul ini hanya boleh diakses oleh Super Admin. "
|
||||
"Super Admin boleh mencipta dan mengurus akaun pentadbir lain dalam sistem."
|
||||
)
|
||||
add_body("Fungsi yang tersedia:")
|
||||
add_bullet("Lihat senarai semua pentadbir")
|
||||
add_bullet("Cipta akaun pentadbir baru")
|
||||
add_bullet("Kemaskini maklumat pentadbir")
|
||||
add_bullet("Padam akaun pentadbir")
|
||||
|
||||
add_screenshot_box(
|
||||
"Halaman Pengurusan Pengguna — Senarai pentadbir (Super Admin sahaja)",
|
||||
f"{BASE_URL}/admin/users"
|
||||
)
|
||||
|
||||
add_body("Jenis peranan pengguna:")
|
||||
add_bullet("Super Admin — Akses penuh termasuk Pengurusan Pengguna")
|
||||
add_bullet("Admin Program — Akses kepada semua program dan soalselidik, kecuali Pengurusan Pengguna")
|
||||
|
||||
add_note("Setiap sistem perlu sekurang-kurangnya satu akaun Super Admin yang aktif.")
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# BAB 13: PROFIL PENGGUNA
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("13. Profil Pengguna")
|
||||
add_body(
|
||||
"Setiap pentadbir boleh mengurus maklumat akaun peribadi mereka melalui halaman Profil. "
|
||||
"Klik nama pengguna atau butang Profil di bar navigasi kiri untuk mengakses halaman ini."
|
||||
)
|
||||
add_body("Fungsi yang tersedia:")
|
||||
|
||||
add_heading("Tukar Alamat Emel", level=2)
|
||||
add_bullet("Masukkan Kata Laluan Semasa untuk pengesahan.")
|
||||
add_bullet("Masukkan Emel Baru.")
|
||||
add_bullet("Klik Kemaskini Emel.")
|
||||
|
||||
add_heading("Tukar Kata Laluan", level=2)
|
||||
add_bullet("Masukkan Kata Laluan Semasa.")
|
||||
add_bullet("Masukkan Kata Laluan Baru (minimum 8 aksara).")
|
||||
add_bullet("Masukkan semula Kata Laluan Baru untuk pengesahan.")
|
||||
add_bullet("Klik Tukar Kata Laluan.")
|
||||
|
||||
add_screenshot_box(
|
||||
"Halaman Profil — Tukar emel dan kata laluan",
|
||||
f"{BASE_URL}/admin/profile"
|
||||
)
|
||||
|
||||
add_note("Kata laluan baru mestilah sekurang-kurangnya 8 aksara. Simpan kata laluan di tempat yang selamat.")
|
||||
page_break()
|
||||
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
# LAMPIRAN: ALIRAN KERJA SISTEM
|
||||
# ═══════════════════════════════════════════════════════════════════════════════
|
||||
add_heading("Lampiran: Aliran Kerja Tipikal")
|
||||
add_body("Berikut adalah urutan langkah yang disyorkan untuk menjalankan sebuah program dari mula hingga selesai:")
|
||||
|
||||
workflow = [
|
||||
("1", "Cipta Set Soalselidik", "Bina soalan maklum balas di Modul Set Soalselidik dan publish."),
|
||||
("2", "Cipta Program", "Isi maklumat program, tarikh, dan tetapan check-in."),
|
||||
("3", "Import Peserta", "Muat naik senarai peserta melalui Excel."),
|
||||
("4", "Muat Naik Template Sijil", "Upload reka bentuk sijil dan konfigurasi kedudukan teks."),
|
||||
("5", "Lampirkan Soalselidik", "Kaitkan set soalselidik dengan program dan sahkan."),
|
||||
("6", "Publish Program", "Aktifkan program supaya peserta boleh check-in."),
|
||||
("7", "Jana & Papar Kod QR", "Paparkan QR Code semasa acara untuk peserta mengimbas."),
|
||||
("8", "Pantau Statistik", "Semak kehadiran dan maklum balas dalam masa nyata."),
|
||||
("9", "Jana dan Hantar Sijil", "Selepas program tamat, jana sijil dan hantar melalui emel."),
|
||||
]
|
||||
|
||||
tbl = doc.add_table(rows=1, cols=3)
|
||||
tbl.style = 'Table Grid'
|
||||
hdr = tbl.rows[0].cells
|
||||
hdr[0].text = "Langkah"
|
||||
hdr[1].text = "Tindakan"
|
||||
hdr[2].text = "Penerangan"
|
||||
for cell in hdr:
|
||||
cell.paragraphs[0].runs[0].bold = True
|
||||
cell.paragraphs[0].runs[0].font.size = Pt(10)
|
||||
|
||||
for step, action, desc in workflow:
|
||||
row = tbl.add_row().cells
|
||||
row[0].text = step
|
||||
row[1].text = action
|
||||
row[2].text = desc
|
||||
for cell in row:
|
||||
cell.paragraphs[0].runs[0].font.size = Pt(10)
|
||||
|
||||
doc.add_paragraph()
|
||||
add_body(f"Untuk sokongan teknikal, hubungi pentadbir sistem atau lawati: {BASE_URL}")
|
||||
|
||||
# ── Simpan dokumen ─────────────────────────────────────────────────────────────
|
||||
output_path = r"C:\Users\User\Aplikasi\ecert\manual\Manual_Pengguna_eCert_MBIP.docx"
|
||||
doc.save(output_path)
|
||||
print(f"Manual berjaya dijana: {output_path}")
|
||||
Reference in New Issue
Block a user