Sistem Kehadiran & Cabutan Bertuah MAT — KOIPB
Aplikasi web Laravel 12 + MySQL untuk Mesyuarat Agung Tahunan (MAT) Koperasi Iskandar Puteri Berhad (KOIPB): rekod kehadiran anggota di kaunter dan jalankan cabutan bertuah (wheel of fortune) di skrin projektor.
Jangkaan kehadiran: 150–200 orang.
Teknologi
| Lapisan | Pilihan | Sebab |
|---|---|---|
| Framework | Laravel 12 (PHP 8.5) | Stabil, lengkap |
| Pangkalan data | MySQL 8 | Seperti diminta |
| UI | Blade + Bootstrap 5 (CDN) | Praktikal, responsive, tiada langkah build |
| Interaksi | jQuery + SweetAlert2 | Live search, alert kemas |
| Roda + confetti | Canvas asli + canvas-confetti |
Animasi smooth, projector-friendly |
| Peranan/akses | spatie/laravel-permission |
Role-based standard industri |
| Import/Export | openspout/openspout (CSV/XLSX) |
Serasi PHP 8.5 (maatwebsite/excel TIDAK serasi PHP 8.5) |
| PDF laporan | barryvdh/laravel-dompdf |
Eksport PDF mudah |
Nota penting:
maatwebsite/exceltidak boleh dipasang pada PHP 8.5 (bergantung pada phpspreadsheet 1.x yang dihadkan kepada PHP < 8.5). Sebab itu sistem guna openspout terus untuk baca/tulis CSV & XLSX.
Setup Local
Prasyarat: PHP 8.5, Composer, MySQL berjalan.
# 1. Pasang dependency
composer install
# 2. Fail .env sudah disediakan. Pastikan tetapan DB betul:
# DB_DATABASE=koipb_mat DB_USERNAME=root DB_PASSWORD=1234
# Cipta database jika belum ada:
# CREATE DATABASE koipb_mat CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# 3. Jana app key (jika .env belum ada APP_KEY)
php artisan key:generate
# 4. Migrate + seed (200 anggota, 21 item hadiah, 3 user)
php artisan migrate:fresh --seed
# 5. Jalankan
php artisan serve
# Buka http://127.0.0.1:8000
Logo: letakkan logo sebenar di public/images/logo-koipb.jpg (kini ada placeholder).
Login Default
Semua kata laluan: password
| Peranan | E-mel | Akses |
|---|---|---|
| Admin | admin@koipb.test |
Semua modul |
| Petugas Kaunter | kaunter@koipb.test |
Kaunter kehadiran + senarai kehadiran |
| Petugas Cabutan / Urusetia | cabutan@koipb.test |
Skrin cabutan + laporan |
Route Penting
| URL | Modul | Akses |
|---|---|---|
/login |
Log masuk | Semua |
/dashboard |
Statistik event | Semua login |
/kaunter |
Kaunter kehadiran (live search) | Admin, Kaunter |
/kehadiran |
Senarai kehadiran + tapis + export | Admin, Kaunter |
/cabutan |
Skrin cabutan (roda) — projector | Admin, Cabutan |
/laporan |
Laporan + export Excel/PDF | Admin, Cabutan |
/admin/anggota |
Urus + import anggota | Admin |
/admin/hadiah |
Urus + import hadiah | Admin |
/admin/tetapan |
Tetapan sesi + reset event | Admin |
/admin/audit |
Audit trail | Admin |
Endpoint AJAX cabutan: POST /cabutan/spin, /cabutan/confirm, /cabutan/batal; GET /cabutan/pool.
Cara Import CSV / XLSX
Admin → Anggota / Hadiah → Import. Format CSV atau XLSX. Baris pertama = nama lajur (header dinormalkan: huruf kecil + underscore). Templat contoh boleh dimuat turun dari skrin import (atau public/samples/).
Anggota — lajur: no_anggota, no_pekerja, no_kp, nama, jabatan, bahagian, telefon, status_aktif
namawajib;no_kp&no_pekerjaunik;status_aktifdefault = aktif.- Duplicate (dalam fail atau dalam DB) dilangkau — ringkasan berjaya / duplicate / gagal dipaparkan & disimpan dalam log import.
Hadiah — lajur: kod_hadiah, nama_hadiah, kategori, nilai_anggaran, susunan_cabutan, kuantiti
- Jika
kuantiti > 1, sistem jana item berasingan (cthHamper #1…Hamper #5).
Cara Demo Cabutan (end-to-end)
- Log masuk admin → import/seed anggota & hadiah (seeder sudah sediakan).
- Log masuk kaunter (
/kaunter) → cari nama/no KP/no pekerja → Rekod Hadir.- Hanya anggota berdaftar boleh direkod; bukan anggota → mesej amaran.
- Double attendance dihalang (paras DB + UI).
- Log masuk cabutan (
/cabutan) di projektor:- Pilih hadiah ikut susunan → SPIN (roda berpusing pada peserta hadir).
- Calon pemenang dipaparkan di panel kanan.
- Confirm Pemenang → panel hijau/emas + confetti + "TAHNIAH!".
- Batal / Tiada Di Dewan → panel merah; hadiah jadi perlu cabut semula.
- Cabut Semula → spin sekali lagi untuk hadiah sama (attempt bertambah).
- Laporan (
/laporan) → pemenang, hadiah belum dicabut, cabutan dibatalkan, kehadiran → export Excel/PDF.
Rules / Jaminan Sistem
- Hanya anggota hadir masuk pool cabutan.
- Pemenang disahkan dikeluarkan dari pool — tidak boleh menang lagi.
- Cabutan dibatalkan boleh dicabut semula; setting default kekalkan peserta batal dalam pool.
- Race condition / double-confirm dihalang di paras DB melalui unique index (
confirmed_member_id,confirmed_prize_id) + transactionlockForUpdate. - Double attendance dihalang oleh unique constraint
attendance_records.member_id. - No KP dimask di UI biasa (cth
850101-01-****). - Semua tindakan penting (login, hadir, spin, confirm, batal, import, reset) direkod dalam audit trail.
Skema Database
users, roles/permissions (spatie), members, attendance_records, prizes,
draw_sessions, draw_results, import_logs, audit_logs.
Index utama: members.no_kp, members.no_pekerja, members.nama,
attendance_records.member_id (unique), prizes.draw_order,
draw_results.(prize_id|member_id|status), unique confirmed_member_id & confirmed_prize_id.
Ujian
php artisan test
Liputan: kehadiran tidak duplicate, hanya hadir boleh masuk cabutan, pemenang disahkan tidak boleh menang lagi (paras servis + DB), cabutan batal boleh redraw, akses ikut peranan, import duplicate/kuantiti. (18 ujian, semua lulus.)