取代纸质登记和手动收费,专为马来西亚补习中心/培训学院设计的一站式管理系统
* Preview is for reference only. Actual results may vary depending on the AI model, variable values, and tools used.
You are a senior full-stack engineer. Build a complete **Student Management & Tuition Fee System** designed for Malaysian tuition centers and training academies, replacing paper registration and manual fee tracking.
## Project Overview
Center name: {center_name}
Center type: {center_type}
Number of classes: {num_classes}
Fee billing cycle: {fee_cycle}
Currency: {currency}
Brand primary color: {primary_color}
## Tech Stack
- **Frontend**: Next.js 16 (App Router) + Tailwind CSS 4
- **Backend/Database**: Supabase (Postgres + Auth + RLS + Realtime)
- **Deployment**: Vercel
- **Notifications**: Simulated (console.log + toast, with WhatsApp API stub)
## Data Model (Supabase Postgres)
### students table
- id (uuid, PK), center_id (uuid, FK)
- name_zh (text, Chinese name), name_en (text, English name)
- ic_number (text, MyKad format YYMMDD-XX-XXXX)
- date_of_birth (date), gender (enum: 'male'|'female')
- school_name (text), current_form (text, e.g. 'Form 4'/'Standard 5')
- education_level (enum: 'primary'|'lower_secondary'|'upper_secondary'|'pre_university'|'adult')
- photo_url (text, nullable)
- status (enum: 'active'|'inactive'|'graduated'|'withdrawn')
- enrollment_date (date), withdrawal_date (date, nullable)
- notes (text, nullable)
- created_at (timestamptz), updated_at (timestamptz)
- Indexes: center_id, ic_number (unique), status
### parents table
- id (uuid, PK), student_id (uuid, FK)
- name (text), relationship (enum: 'father'|'mother'|'guardian')
- phone (text, +60 format), phone_secondary (text, nullable)
- email (text, nullable), whatsapp_number (text, nullable)
- is_primary_contact (boolean, default true)
- portal_pin (text, 4-digit numeric, for parent portal login)
- Indexes: student_id, phone
### classes table
- id (uuid, PK), center_id (uuid, FK)
- name_zh (text), name_en (text)
- subject (text, e.g. 'Mathematics'/'Bahasa Melayu'/'Science'/'Physics')
- education_level (enum, same as students)
- target_exam (text, nullable, e.g. 'SPM'/'PT3'/'UPSR'/'STPM'/'UEC')
- teacher_id (uuid, FK)
- schedule_day (text), schedule_time (time), schedule_end_time (time)
- duration_minutes (int), room (text)
- capacity (int), current_enrollment (int, default 0)
- fee_amount (numeric, per {fee_cycle})
- fee_type (enum: 'monthly'|'per_term'|'per_class')
- term_start (date, nullable), term_end (date, nullable)
- is_active (boolean, default true)
- created_at (timestamptz)
- Indexes: center_id, teacher_id, subject, is_active
### teachers table
- id (uuid, PK), center_id (uuid, FK)
- name_zh (text), name_en (text)
- phone (text, +60 format), email (text, nullable)
- subjects (text[], list of subjects taught)
- qualification (text)
- is_active (boolean, default true)
- created_at (timestamptz)
- Indexes: center_id
### enrollments table
- id (uuid, PK), student_id (uuid, FK), class_id (uuid, FK)
- enrolled_date (date), status (enum: 'active'|'dropped'|'completed')
- dropped_date (date, nullable), drop_reason (text, nullable)
- Indexes: student_id, class_id, (student_id, class_id) UNIQUE
### attendance table
- id (uuid, PK), class_id (uuid, FK), student_id (uuid, FK)
- date (date), status (enum: 'present'|'absent'|'late'|'excused')
- remarks (text, nullable)
- marked_by (uuid, FK, nullable)
- created_at (timestamptz)
- Indexes: (class_id, date), (student_id, date), (class_id, student_id, date) UNIQUE
### fees table
- id (uuid, PK), student_id (uuid, FK), class_id (uuid, FK)
- billing_period (text, e.g. '2026-04' or '2026-Term1')
- amount (numeric), discount (numeric, default 0)
- discount_reason (text, nullable)
- net_amount (numeric, generated column: amount - discount)
- status (enum: 'pending'|'partial'|'paid'|'overdue'|'waived')
- due_date (date)
- created_at (timestamptz), updated_at (timestamptz)
- Indexes: student_id, class_id, status, due_date, billing_period
### payments table
- id (uuid, PK), fee_id (uuid, FK), student_id (uuid, FK)
- amount (numeric)
- payment_method (enum: 'cash'|'bank_transfer'|'ewallet_tng'|'ewallet_grabpay'|'ewallet_boost'|'online_banking')
- payment_date (date), reference_number (text, nullable)
- receipt_number (text, auto-generated, format RCP-YYYYMMDD-XXXX)
- notes (text, nullable), recorded_by (text)
- created_at (timestamptz)
- Indexes: fee_id, student_id, payment_date, receipt_number UNIQUE
### performance_notes table
- id (uuid, PK), student_id (uuid, FK), class_id (uuid, FK)
- teacher_id (uuid, FK)
- date (date), note_type (enum: 'progress'|'behavior'|'exam_result'|'homework'|'general')
- content (text)
- is_visible_to_parent (boolean, default true)
- created_at (timestamptz)
- Indexes: student_id, class_id, date
### center_settings table
- id (uuid, PK), center_id (uuid, FK)
- center_name (text), address (text), phone (text)
- logo_url (text, nullable)
- receipt_prefix (text, default 'RCP')
- receipt_footer (text, default 'Thank you for your payment')
- overdue_days (int, default 14)
- sibling_discount_percent (numeric, default 10)
- created_at (timestamptz)
## RLS Security Policies
- **No public read**: All data requires authentication
- **Admin full access**: All tables CRUD via auth.uid() matching admins table
- **Teacher limited access**: Read/write attendance and performance_notes for own classes only
- **Parent portal**: Verify via phone + portal_pin, read-only access to own child's attendance, fees, payments, performance_notes
- Wrap auth calls with `(select auth.uid())` to avoid per-row function evaluation
## Business Logic
### Fee Calculation
#### Monthly billing
- Auto-generate bills on the 1st of each month for all active enrollments
- net_amount = class.fee_amount - discount
- Sibling discount: 2nd child onwards from the same parent gets sibling_discount_percent% off
- New students: pro-rate first month based on enrollment date (net_amount * remaining_days / total_days_in_month)
#### Per-term billing
- Generate one bill at term start for the entire term
- Mid-term withdrawal: refund pro-rated by remaining weeks
#### Per-class billing
- Generate a bill after each class session
- Excused absences: no charge. Unexcused absences: still charged
### Overdue Handling
- Bills unpaid after due_date + overdue_days automatically marked 'overdue'
- Overdue bills highlighted in red on admin dashboard
- Simulated parent reminder notification
### Attendance Rate Calculation
- attendance_rate = (present_count + late_count) / total_class_days * 100
- Below 75%: yellow warning badge
- Below 50%: red warning badge
- Displayed in parent portal and admin reports
### Outstanding Balance Calculation
- outstanding = SUM(fees.net_amount WHERE status IN ('pending','partial','overdue')) - SUM(related payments.amount)
- Dashboard shows per-student outstanding totals
- Summary reports by class and by education level
### Receipt Generation
- Auto-generate receipt number on payment: {receipt_prefix}-YYYYMMDD-0001 (incrementing)
- Receipt includes: center name, address, student name, class, fee breakdown, payment method, date
- Printable receipt page (print-friendly CSS)
- Footer shows receipt_footer text from settings
## Frontend Pages (Admin — Desktop-First)
### /admin/dashboard
- **Top stat cards**: Total active students (with this month's new count), monthly fees receivable, collected amount + collection rate %, overdue amount (red highlight)
- **Overdue student list**: Name, class, amount owed, days overdue, contact parent button
- **Today's timetable**: Classes scheduled today with time, room, teacher, enrollment count
- **Recent payments**: Last 10 payment transactions
### /admin/students — Student Management
- **Student table**: Name (CN/EN), IC, form/grade, status badge, enrolled classes count, outstanding balance
- **Filters**: By education level, status, class
- **Search**: By name or IC number
- **New student form**:
- Basic info: CN/EN names, IC (auto-calculate DOB from MyKad), gender, school, form
- Parent contact: Parent name, relationship, phone (+60), WhatsApp, email
- Class enrollment: Checkboxes for available classes (show remaining capacity)
- On submit: auto-generate first month/term fee bills
- **Student detail page**: Info card, enrolled classes + attendance rates, fee history (status badges: paid=green, partial=yellow, overdue=red), payment records, performance notes timeline
### /admin/classes — Class Management
- **Class list**: Subject, level, teacher, schedule, room, enrollment/capacity
- **Add/edit form**: Name (CN/EN), subject, target exam, teacher, schedule, room, capacity, fee
- **Class detail**: Student roster + attendance overview, attendance records (date-based quick checkmark), fee collection status
### /admin/attendance — Attendance Management
- **Quick marking UI**: Select class > show today's student list > one row per student, tap to toggle present/absent/late/excused
- **Bulk action**: One-click mark all present
- **Reports**: By class/student/date range, attendance rate percentages
- **Calendar view**: Monthly grid per student (green dot=present, red=absent, yellow=late)
### /admin/fees — Fee Management
- **Bill list**: Student, class, billing period, amount due, amount paid, status
- **Filters**: By status, class, billing period
- **Bulk bill generation**: Select class + period > one-click generate bills for all active students
- **Record payment**:
- Select student > show unpaid bills
- Enter amount, method (cash/bank transfer/TNG/GrabPay/Boost/online banking)
- Auto-allocate to oldest unpaid bill first
- Partial payment marks bill as 'partial'
- Full payment marks as 'paid'
- Auto-generate receipt number
- **Receipt view/print**: Standard receipt format with center info, student info, fee details, payment info
### /admin/fees/outstanding — Outstanding Fee Dashboard
- **Summary cards**: Total outstanding, number of overdue students, average days overdue
- **Detail table**: Student name, parent phone, amount owed, earliest overdue date, actions (send reminder / record payment)
- **By-class summary**: Collection rate pie chart per class
- **Monthly trend**: Collection rate line chart
### /admin/teachers — Teacher Management
- **Teacher list**: Name, subjects, number of classes
- **Teacher schedule view**: Weekly calendar showing each teacher's class schedule
### /admin/timetable — Timetable Overview
- **Weekly grid**: X-axis = Monday to Saturday, Y-axis = time slots, each cell shows class name + room + teacher
- **Filter by room**: View a specific room's occupancy
- **Conflict detection**: Red highlight if two classes share the same room at the same time
### /admin/reports — Report Center
- **Fee reports**: Monthly/term revenue summary, collection rates
- **Attendance reports**: Center-wide attendance rate, ranked by class
- **Student reports**: New enrollment / withdrawal trends
- **CSV export**: All reports support export
## Frontend Pages (Parent Portal — Mobile-First)
### /parent — Parent Login
- Enter phone (+60) + 4-digit PIN
- No registration needed; PIN is set by admin during student registration
### /parent/dashboard
- **Child info card**: Name, form, school, photo
- **Enrolled classes list**: Subject, teacher, schedule
- **This month's attendance overview**: Attendance rate % + calendar view
- **Fee status**: This month's due / paid / outstanding amounts
- **Quick actions**: View receipts, contact center
### /parent/attendance
- Tabbed by class
- Calendar view: Color-coded days (green=present, red=absent, yellow=late, grey=no class)
- Stats cards: Overall rate, this month rate, consecutive attendance streak
### /parent/fees
- **Unpaid bills**: Class, period, amount, due date, status badge
- **Payment history**: All paid records with receipt numbers (clickable to view receipt)
- **Receipt page**: Standard format, screenshot/print-friendly
### /parent/notes
- Teacher notes timeline (only showing is_visible_to_parent = true)
- Tabbed by class
- Each note: date, teacher, type badge (progress/behavior/exam/homework), content
## Frontend Pages (Teacher View — Tablet-First)
### /teacher/schedule
- Weekly calendar showing all classes for this teacher
- Each cell: class name, time, room, student count
### /teacher/attendance
- Select today's class > student list > quick mark present/absent
- Large button design for tablet use
### /teacher/notes
- Select class > select student > write performance note
- Toggle parent visibility
## Malaysian Education Localization
- Trilingual UI: Simplified Chinese primary, English toggle, Malay for subject names (Bahasa Melayu, Sejarah, etc.)
- Phone: +60 prefix, Malaysian number validation
- Currency: {currency} (default RM/MYR)
- Timezone: Asia/Kuala_Lumpur (UTC+8)
- Grade system:
- Primary: Standard 1-6 (UPSR reference)
- Lower secondary: Form 1-3 (PT3)
- Upper secondary: Form 4-5 (SPM)
- Pre-university: Form 6 (STPM) / UEC
- Subject name mapping (Chinese / English / Malay):
- 数学 / Mathematics / Matematik
- 科学 / Science / Sains
- 国语 / Bahasa Melayu / BM
- 英语 / English / BI
- 华语 / Chinese / BC
- 历史 / History / Sejarah
- 物理 / Physics / Fizik
- 化学 / Chemistry / Kimia
- 生物 / Biology / Biologi
- 高数 / Additional Mathematics / Matematik Tambahan
## Sample Data
Generate the following test data:
**Center**: {center_name} ({center_type}), address: Jalan SS15/4, Subang Jaya, Selangor
**Teachers (3)**:
1. Mr. Chan 陈老师 — Mathematics/Add Maths, B.Ed Mathematics, 10 years experience
2. Ms. Lim 林老师 — Science/Physics/Chemistry, M.Sc Chemistry
3. Cikgu Aminah — Bahasa Melayu/Sejarah, SPM Master Teacher
**Classes ({num_classes})**:
1. SPM Mathematics 数学冲刺班 — Form 4-5, Mr. Chan, Tue 8:00PM-9:30PM, Room A, cap 20, RM180/month
2. SPM Add Maths 高数强化班 — Form 4-5, Mr. Chan, Thu 8:00PM-9:30PM, Room A, cap 15, RM200/month
3. PT3 Science 科学班 — Form 1-3, Ms. Lim, Wed 4:00PM-5:30PM, Room B, cap 20, RM150/month
4. SPM Physics 物理班 — Form 4-5, Ms. Lim, Sat 10:00AM-11:30AM, Room B, cap 15, RM180/month
5. SPM Bahasa Melayu 国语班 — Form 4-5, Cikgu Aminah, Fri 8:00PM-9:30PM, Room C, cap 25, RM150/month
6. PT3 Bahasa Melayu 国语班 — Form 1-3, Cikgu Aminah, Sat 2:00PM-3:30PM, Room C, cap 20, RM130/month
**Students (12)**: 8 active (enrolled in 2-3 classes each), 2 inactive (withdrawn), 2 new (enrolled this month). Complete parent contacts with PINs.
**Attendance**: This month, 4 sessions per class with mixed statuses.
**Fees**: Monthly bills generated for all active students. 6 fully paid, 2 partial, 2 overdue. Payment records with mixed methods (3 cash, 2 bank transfer, 2 TNG, 1 GrabPay).
**Performance notes**: 5 teacher notes (progress encouragement, exam results, homework feedback).
## Supabase Realtime Configuration
- Subscribe to attendance changes > live update on admin dashboard when teacher marks attendance
- Subscribe to payments changes > live update dashboard when payment is recorded
- Subscribe to fees changes > reflect bill status updates in real time
## Key Requirements
1. Admin: desktop-first. Parent portal: mobile-first. Teacher view: tablet-first.
2. Attendance marking must be fast — teacher should complete a full class in under 30 seconds.
3. Payment records must be accurate; receipts must look professional.
4. Overdue reminders should be firm but polite (professional tone, not debt-collection language).
5. All monetary calculations use numeric type to avoid floating-point precision issues.
6. Code comments in bilingual Chinese/English.
7. Use Tailwind CSS 4 + shadcn/ui components.
8. Deploy to Vercel, environment variables via .env.local.