Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

02 — User Personas (Fees Module)

Who touches fees, what they can do on the current backend, and what the client should do for them. Permissions reflect permissions.constants.ts and the system roles in role.schema.ts:42-48 — fees endpoints today are guarded by JwtAuthGuard only (fees.controller.ts:21-24), so RBAC below is the intended model (planned).


1. Admin / Bursar — defines fee structures

  • Job: set up the fee structures for each class and term (tuition, transport, lab, library…), due dates, whether active.
  • API surface: POST/PATCH/DELETE /fees/structures… (fees.controller.ts:28-56).
  • Constraints: structure requires name, classId, academicYearId, items[], totalAmount, dueDate; currency defaults XAF, lateFee defaults 0 (fee-structure.schema.ts:9-34; create-fee-structure.dto.ts:26-68). Deletion is soft (base.repository.ts:68-74) — structures remain visible history; invoices already generated are unaffected.
  • Pain points to solve: creating a season of structures fast (duplicate structure endpoint is (planned), IMPLEMENTATION_PLAN.md:205); seeing which structures are active vs archived; avoiding a totalAmount that doesn't match the sum of line items (server does not validate the sum).

2. Accountant / Cashier — records payments

  • Summary: collects cash/mobile-money at the till and posts against an invoice.
  • Own surface: POST /fees/invoices/:id/payments (fees.controller.ts:70-74), reads dues via GET /fees/dues (fees.controller.ts:76-80).
  • Role perms: default Accountant role = ['fees.collect', 'student.read'] (role.schema.ts:42-48).
  • Constraints: every payment needs a fresh idempotencyKey; replay with the same key returns the original payment (never doublesfees.service.ts:148-152). Payment method must be cash|bank_transfer|mobile_money|cheque|other (record-payment.dto.ts:21-25).
  • Pain points: concurrent keyboards double-submitting (mitigated by idempotency); accidentally overpaying (no cap server-side); chasing an exact "make paid" state when partial payments exist (PARTIAL is derived from paidTotal >= total, fees.service.ts:169-172).

3. Parent / Guardian — pays and tracks dues

  • Summary: sees the child's invoices and balance, pays online, reads receipts.
  • Surface (read): GET /fees/students/:studentId/invoices (fees.controller.ts:64-68) — child studentId comes from the Students/Profiles module (no parent-scoped endpoint). Online pay goes through Payments: POST /payments (process-payment.dto.ts), receipts via GET /payments/receipts (payments.controller.ts:63-67).
  • Role perms: default Parent = ['student.read'] (role.schema.ts:50-56); no fees.* perms — parent fees UI is about the data surfaces the parent role can already reach + gap flagged (OQ-9/12_API).
  • Constraints: overpay/partial allowed; server derives status from sums. Receipt is print/shareable client-side from the receipts doc.

4. Org Admin — financial oversight

  • Summary: sees all structures, invoices, dues; reconciles odd states.
  • Surface today: everything under /fees/** + /payments/**; no admin-specific fees endpoint (dues report (planned), IMPLEMENTATION_PLAN.md:208 discounts, :211 statement).

5. Platform Admin (cross-tenant support)

  • Summary: support agent; BaseRepository.scopedFilter bypasses tenant scope for platform admin (base.repository.ts:20-23) — a support-only, read-mostly surface on the same endpoints (planned) across tenants.

6. Role × fees-appearance matrix

ScreenAdmin/BursarAccountantParentOrg admin
Fee structures list/detailCRUD (fees.controller.ts:28-56)readread
Student invoices✓ (:64-68)child only
Record payment✓ (till)via POST /paymentsview only
Dues✓ (76-80)child dues (derived)✓ (e.g. aggregation)
Payments v2 + receiptspayments.read (81)receipts.read (85)view

All rows are guidance until per-endpoint @Permissions() metadata lands (OQ-9). Fees endpoints today require only a valid JWT.