ไอเดีย #44: ระบบโหวตเลือกตั้งสภานักเรียน
เลือกตั้งสภานักเรียนแบบกระดาษ ครูต้องเตรียมหีบ บัตร รายชื่อ แล้วนั่งนับคะแนนกันถึงเย็น ส่วนแบบออนไลน์ที่หลายโรงเรียนใช้ฟอร์มสำเร็จรูปแทน ก็มักโดนตั้งคำถามว่ามีคนโหวตซ้ำไหม ใครเห็นว่าใครเลือกใคร และผลที่ประกาศเชื่อถือได้แค่ไหน โจทย์นี้ดูเหมือนแค่ CRUD ธรรมดา แต่จริง ๆ แล้วเป็นแบบฝึกหัดเรื่องความปลอดภัยและความโปร่งใสที่ดีมาก
ใครจะใช้
- นักเรียนผู้มีสิทธิ์ — ยืนยันตัวตนแล้วลงคะแนนได้หนึ่งครั้ง
- ผู้สมัคร — ส่งชื่อพรรคหรือทีม นโยบาย และรูปประจำตัว
- คณะกรรมการการเลือกตั้ง — ครูหรือตัวแทนนักเรียน ที่ตั้งค่า เปิดปิดหีบ และประกาศผล
- ผู้สังเกตการณ์ — ดูจำนวนผู้มาใช้สิทธิ์แบบเรียลไทม์ แต่ไม่เห็นคะแนนจนกว่าจะปิดหีบ
ฟีเจอร์ขั้นต่ำ (MVP)
- นำเข้าบัญชีรายชื่อผู้มีสิทธิ์จากทะเบียนนักเรียน แยกตามระดับชั้น
- ยืนยันตัวตนด้วยรหัสนักเรียนร่วมกับรหัสครั้งเดียวที่แจกในห้องเรียน หรือ OTP
- หน้าลงคะแนนแสดงผู้สมัครพร้อมนโยบาย มีตัวเลือกไม่ประสงค์ลงคะแนน
- ลงคะแนนแบบลับ: แยกตารางบันทึกว่าใครใช้สิทธิ์แล้ว ออกจากตารางบัตรลงคะแนน โดยไม่มี foreign key ถึงตัวผู้โหวต
- กันโหวตซ้ำด้วย unique constraint และทำใน transaction เดียว
- ออกใบรับรองการลงคะแนนเป็นรหัส receipt ให้ผู้โหวตตรวจได้ว่าบัตรถูกนับ
- ปิดหีบตามเวลาแล้วนับผลอัตโนมัติ พร้อมหน้าประกาศผลและกราฟ
ต่อยอดได้อีก
- เข้ารหัสบัตรด้วย public key ของกรรมการ ถอดรหัสได้หลังปิดหีบเท่านั้น
- โหมดตู้ลงคะแนนในห้องคอม ที่ล็อกเครื่องและรีเซ็ตหน้าจอหลังโหวต
- รองรับการเลือกตั้งหลายตำแหน่ง หรือการโหวตแบบจัดอันดับ
- นำไปใช้กับการเลือกตั้งชมรม สหกรณ์ หรือหมู่บ้านจัดสรร
โครงข้อมูลตั้งต้น
elections— id, title, open_at, close_at, status, results_publishedcandidates— id, election_id, number, name, policy, photo_pathvoters— id, election_id, student_code, grade, token_hashvoter_status— voter_id, election_id, voted_at (unique ตามคู่ voter และ election)ballots— id, election_id, candidate_id, receipt_hash, cast_at (ปัดเวลาเป็นช่วง)
ระดับความยาก และสิ่งที่จะได้เรียนรู้
ระดับ ท้าทาย ไม่ใช่เพราะโค้ดเยอะ แต่เพราะต้องคิดเรื่องความลับและความน่าเชื่อถือ ใช้ Yii2 หรือ Laravel + PostgreSQL ก็พอ สิ่งที่จะได้เรียนรู้:
- ออกแบบ schema ที่แยกตัวตนออกจากเนื้อหาบัตรอย่างแท้จริง
- ใช้ transaction และ unique constraint กัน race condition ตอนกดโหวตพร้อมกัน
- ทำ hash, token ครั้งเดียว และ audit log ที่แก้ย้อนหลังไม่ได้
- จัดการโหลดช่วงพีคตอนเปิดหีบหลังเคารพธงชาติ
ข้อควรระวัง
- ถ้าบันทึกเวลาโหวตละเอียดถึงวินาทีในทั้งสองตาราง ผู้ดูแลอาจจับคู่ได้ว่าใครเลือกใคร ควรปัดเวลา หรือสุ่มลำดับการบันทึก
- ผู้ดูแลฐานข้อมูลมีสิทธิ์สูง ควรเปิด log ทุกการเข้าถึง และให้กรรมการหลายคนร่วมกันยืนยันผล
- ข้อมูลนักเรียนเป็นข้อมูลของผู้เยาว์ ควรเก็บเท่าที่จำเป็นและลบเมื่อจบการเลือกตั้งตามนโยบายโรงเรียนและ PDPA
ถ้าเป็นคุณ จะออกแบบให้ "ลับ" และ "ตรวจสอบได้" ไปพร้อมกันยังไงครับ ใครเคยทำระบบโหวตให้โรงเรียนหรือองค์กรจริงแล้วเจอข้อโต้แย้งอะไรบ้าง มาเล่าหรือแชร์โค้ดที่ทำไว้ในกระทู้นี้ได้เลย