type
Data Model
title
Students, enrollments & fees
description
The student master record, its per-year enrollment, the year-expense fee catalogue it inherits from, and the concrete charges those become.
tags
students, enrollments, fees, transfers
status
stable
stale_after
Fri Apr 30 2027 02:00:00 GMT+0200 (Central European Summer Time)
generated
techwriter/mimo-v2.6-flash · Sat Oct 31 2026 11:02:38 GMT+0100 (Central European Standard Time)
sources
001_schema.sql → internal/infrastructure/sqlite/migrations/001_schema.sql; studentsvc → internal/application/student/service.go; feedomain → internal/domain/student/fee.go

Students, enrollments & fees

One student row for life; one enrollment per (student, academic year); fees materialised per enrollment from the year's expense catalogue or added by hand; transfers recorded as history, never by mutating the student.

Table Columns (keys) Notes
students id PK · code UNIQUE (auto) · full_name · gender · birth_date · phone · email · guardian_name · guardian_phone · status (default active) · grade_id FK · class_id FK · created_by · created_at grade/class are the student's current placement; bulk CSV import/export hangs off the same table
student_transfers id PK · student_id FK · from_grade_id/to_grade_id FK · from_class_id/to_class_id FK · transfer_type · note · date · created_by within/across grades and classes, plus leave/dropout/expelled and no-destination moves; the transfer form also updates the student's placement
enrollments id PK · student_id FK · academic_year_id FK · grade_id FK · class_id FK · status (default active) one row per year; bulk class assignment writes here; promotion copies rows forward
year_fees id PK · academic_year_id FK · name · amount · currency (default SYP) the year's expense catalogue ("year expenses" in the UI): defined once per academic year, inherited by every enrollment of that year
student_fees id PK · enrollment_id FK · student_id FK · academic_year_id FK · year_fee_id (nullable) · name · amount · amount_paid · currency · status (unpaid/partially_paid/paid) · payment_id the concrete charge; year_fee_id marks inheritance (null = ad-hoc); amount_paid moves via ApplyPayment/RevertPayment inside the payment posting/void transactions

Relationships

students 1 —< enrollments >— academic_years; enrollments 1 —< student_fees; year_fees 1 —< student_fees (inheritance); students 1 —< student_fees; students 1 —< student_transfers.

Invariants worth keeping in mind

Rendered from simple-lms/data-model/students.md · OKF bundle · regenerate with npm run render