- Get Started
- Localhost
- Architecture
- Structure
- Pattern
- Page
- Layout
- Content
- Types
- Config
- Actions
- Queries
- Authorization
- Validation
- Form
- Table
- Detail
- Card
- Util
- Hooks
- List Params
- Views
- README.md
- ISSUE.md
- Technology Stack
- Database
- File
- CDN Assets
- Entry Points
- Dashboard
- Authentication
- Credentials
- OAuth
- Flow Diagrams
- Multi-Tenancy
- Offline
- Onboarding
- Onboarding Videos
- Add Values
- Admission
- Application
- Attendance
- Compliance
- Profile
- Exams
- Exam Wizard
- Timetable
- Classrooms
- Notifications
- Conference
- LMS (Lumos)
- Finance
- Fee Management
- Invoice
- Wallet
- Salary
- Payroll
- Timesheet
- Expenses
- Budget
- Receipt
- Accounts
- Banking
- Reports
- Dashboard
- Permissions
- Messages
- Integration Flow
- Provision
- AI Document Processing
- Document Intelligence
- Internationalization
- Translation
- Translation Guide
- Icons
- Docs Factory
- Inspiration
- Listings
- Teachers
- Students
- Catalog
- Library
- Contributing
- Code of conduct
- GitHub Workflow
- Database Seeds
- Database Safety
- Test Accounts
- Bulk import
- Playwright
- Prettier
- Block Rebound
- Transportation
Define what the school charges, assign fees to students, collect online or offline, track installments, and notify on lifecycle events. A 9 AM cron detects overdue fees and dispatches urgent reminders.
Lists on a phone
The fee structures, assignments, payments, fines and scholarships lists open on cards on a phone — name, amount in the school's currency, status chips, date, and the same actions menu as the table row. The view toggle switches to the table. Amounts in these lists are formatted in School.currency.
Pipeline
1. Admin creates a Fee Structure (tuition, transport, uniform, …)
2. Admin assigns fees to students (individual or bulk)
3. Student + guardians notified (in-app + email)
4. Student pays online (Stripe) or admin records manual payment
5. System tracks installments — PAID / PARTIAL / OVERDUE
6. Daily cron at 9 AM detects overdue → urgent reminders
7. PDF receipt generated for every payment
Fee structure
Defined under Finance → Fees → Fee Structures.
| Field | Description |
|---|---|
| Name | "Tuition Fee", "Transport Fee" |
| Amount | Total fee amount |
| Category | TUITION, TRANSPORT, UNIFORM, EXAM, ACTIVITY, LIBRARY, LAB, HOSTEL, OTHERS |
| Academic year | "2025-2026" |
| Grade | Optional — the grade it charges; empty = every grade (school-wide) |
| Installments | Number of installments (default 1) |
| Payment schedule | Optional — exact dates and amounts |
| Late fee | Optional — FIXED, PERCENTAGE, DAILY, MONTHLY |
| Discount policy | Optional — sibling, early payment |
Assignment
Two modes:
- Individual — select student → pick structure → optional custom amount → assign
- Bulk — tick students (or select all) → pick structure → assign
On assignment: FeeAssignment row created with status PENDING, student + all guardians get fee_due notification (in-app + email), sibling discount auto-calculated (e.g. 2nd child 10%, 3rd child 20%).
Automatic. A student placed in a grade — through admission, the add-student wizard, or an edit that changes the grade — gets every structure of the year that charges their grade, plus the school-wide ones. A structure charges a grade, never a class (since 2026-10-04); older class-linked structures were moved to their class's grade.
Payment
Online (student self-service)
Login → My Fees → click "Pay Online" → Stripe Checkout (Visa, MC, Apple Pay)
→ on success, webhook records Payment automatically
→ fee_paid notification (student + guardians)
Offline (admin records)
Finance → Fees → Payments → New Payment
→ select fee assignment → enter amount, method, optional reference
→ Payment record + status update + fee_paid notification
Methods
| Method | Status | Markets |
|---|---|---|
| Stripe | Live | Global (Visa, MC, Apple Pay, Google Pay) |
| Tap | Coming Soon | Gulf (mada, KNET, STC Pay) |
| Cash | Live | All |
| Bank Transfer | Live | All |
| Mobile Money | Live | Sudan (Bankak, mBOK) |
Gateway is selected automatically based on the school's country.
Installments
Two modes:
- Explicit — admin sets exact dates and amounts (e.g. 5,000 SAR Sep 1 / 5,000 SAR Dec 1 / 5,000 SAR Mar 1)
- Equal split — admin sets count, system divides equally with monthly due dates
| Status | Meaning |
|---|---|
| PAID | Fully covered |
| PARTIAL | Some payment, balance remaining |
| PENDING | Not yet due |
| OVERDUE | Past due date, not fully paid |
Students see a visual timeline with green / yellow / red / gray indicators and a progress bar.
Notifications
| Event | Recipients | Priority | Channels |
|---|---|---|---|
| Fee assigned | Student + guardians | High | In-app + Email |
| Payment received | Student + guardians | Normal | In-app + Email |
| Fee overdue | Student + guardians | Urgent | In-app + Email |
Overdue cron
Daily at 9:00 AM:
- Scan all
PENDINGandPARTIALassignments - Check if any installment due date has passed
- Update status to
OVERDUE - Dispatch urgent notification (amount + fee name)
The overdue notification fires once — when status first changes to OVERDUE. Repeated reminders to already-overdue accounts is a planned enhancement (re-notify if last notification > 7 days).
User preferences: notification types, channels (in-app / email), quiet hours, digest mode (daily / weekly).
Tracking
| Who | Where | Sees |
|---|---|---|
| Student | My Fees | Assigned fees, payment history, installment timeline |
| Guardian | Notifications | Due / overdue / paid alerts (in-app + email) |
| Admin | Finance → Fees → Payments | All payments, filterable by student / status / method |
| Accountant | Finance → Fees | Full payment ledger with journal entries |
Payment record fields: payment number (unique), receipt number (unique), amount, date, method, external transaction ID (online), status (PENDING → SUCCESS → REFUNDED?), journal entry link.
Every successful payment generates a downloadable PDF receipt with school branding, payment details, and remaining balance.
Refunds
Refund requests track: request date, reason, approval (processedBy, approvalNotes), supporting documents, status through the refund lifecycle.
Discounts
Sibling discounts
Auto-detected through shared guardians. Configurable percentages (e.g. 2nd child 10%, 3rd child 20%). Applied at assignment time.
Scholarships
Custom amount or percentage, linked to specific fee assignments, full audit trail.
Late fees
Per fee structure:
| Type | Example |
|---|---|
| FIXED | 100 SAR flat |
| PERCENTAGE | 5% of outstanding |
| DAILY | 10 SAR per day overdue |
| MONTHLY | 200 SAR per month overdue |
Key files
| Component | Path |
|---|---|
| Server actions | src/components/school-dashboard/finance/fees/actions.ts |
| Queries | src/components/school-dashboard/finance/fees/queries.ts |
| Payment form | src/components/school-dashboard/finance/fees/payment-form.tsx |
| My Fees (student) | src/components/school-dashboard/finance/fees/my-fees.tsx |
| Pay Online button | src/components/school-dashboard/finance/fees/pay-online-button.tsx |
| Installment timeline | src/components/school-dashboard/finance/fees/installment-timeline.tsx |
| Receipt PDF | src/components/school-dashboard/finance/fees/receipt-pdf.tsx |
| Overdue cron | src/app/api/cron/fee-overdue/route.ts |
| Payment providers | src/lib/payment/providers/ |
| Gateway config | src/lib/payment/gateway-config.ts |
| Stripe webhook | src/app/api/webhooks/stripe/route.ts |
| Schema | prisma/models/finance-fees.prisma |
See also
- Finance — finance block overview + status matrix
- Invoice — invoice auto-generation from fee assignments
- Notifications —
fee_due,fee_paid,fee_overdue - Admission — enrollment creates fee assignments