05 — Screen Inventory (Fees Module)
- 1. Fees Home
/fees(Dues summary) - 2. Fee Structures List
/fees/structures - 3. Fee Structure Detail
/fees/structures/:id - 4. Create / Edit Fee Structure
/fees/structures/new,/fees/structures/:id/edit - 5. Student Invoices
/fees/students/:studentId/invoices - 6. Invoice Detail
/fees/invoices/:id - 7. Record Payment (till)
/fees/invoices/:id/pay(sheet or page) - 8. Dues List
/fees/dues - 9. Dues Report
/fees/dues/report(proposed) - 10. Payments (online, v2) — shared with Payments module
- 11. Receipts
/payments/receipts,/payments/receipts/:id - 12. Reminders Screen
/fees/reminders(planned) - 13. Payment status chips (shared across screens)
- Shared components used
- Analytics events
(proposed)— 00-shared/10 §8 - Keyboard, landscape, tablet, desktop
Complete inventory of client screens. Every screen maps to a real endpoint (12_API_Mapping.md); screens for unimplemented surfaces are marked. Legend:
(planned)= backend planned, not implemented;(proposed)= client-side composition;(forward-looking)= requires future backend capability.
1. Fees Home /fees (Dues summary)
- Purpose: landing page after Fees destination: outstanding total, status distribution (issued/partial/overdue), quick actions.
- Backend:
GET /fees/dues?page&limit(fees.controller.ts:76-80); onlyissued|partial|overdue(fees.service.ts:190-212). - Elements: stat tiles (total due, count of overdue, count of partial), dues
preview list (top 5 rows: student ref, amount,
due), FAB "Collect payment", chips filter. - Empty: "No outstanding dues"
AppEmptyState. - Analytics:
(proposed)screen_view + tile taps.
2. Fee Structures List /fees/structures
- Purpose: browse all structures (active + archived) for a tenant.
- Backend:
GET /fees/structurespaginated (fees.controller.ts:34-38); no server filtering —sort/q/status filter are client-side today (pagination-query.dto.ts:21-29). - Elements:
AppSearchBar(client filter), status chips (Active/Archived fromisActive,fee-structure.schema.ts:36-37), structure cards: name, class/year refs,totalAmount,currency,dueDate, item count,lateFee. - FAB: "New structure" (
AppFAB.extended). - Row menu: Edit; Delete (soft; confirm dialog); Duplicate
(planned)(IMPLEMENTATION_PLAN.md:205). - Empty: "No fee structures yet" + FAB.
- Analytics:
(proposed)list_loaded, structure_opened, structure_deleted.
3. Fee Structure Detail /fees/structures/:id
- Purpose: full structure view → line items, totals, and the "Generate invoice" action.
- Backend:
GET /fees/structures/:id(fees.controller.ts:40-44); 404 →AppEmptyState"This structure was removed." - Elements: header card (name, active badge, class/year), info rows (
currency,dueDate,lateFee,isActive), line items table (items[{name,amount}],fee-structure.schema.ts:18-22) with sum check (server doesn't validate sum of items ==totalAmount— flag when mismatch), total row, actions: Edit, Generate invoice (dialog), Delete. - Analytics:
(proposed)structure_detail_view, invoice_generate_tap.
4. Create / Edit Fee Structure /fees/structures/new, /fees/structures/:id/edit
- Purpose: capture/amend structure fields incl. dynamic line items.
- Backend:
POST /fees/structures(fees.controller.ts:28-32),PATCH /fees/structures/:id(fees.controller.ts:46-50). - Fields: see 08_Form_Specifications.md §1-§2 (name, classId, academicYearId, items[], totalAmount, currency, dueDate, lateFee, isActive).
- Edit note:
classId/academicYearIdare immutable after create — not inUpdateFeeStructureDto(update-fee-structure.dto.ts:15-54). - Analytics:
(proposed)structure_saved, structure_updated.
5. Student Invoices /fees/students/:studentId/invoices
- Purpose: one student's invoice history (per term).
- Backend:
GET /fees/students/:studentId/invoices(fees.controller.ts:64-68) — non-paginated array (fees.service.ts:142-144), insertion order (invoice.repository.ts:17-21). - Elements: student header (resolved from Students module), invoice cards:
term/structure ref,
totalAmount,paidAmount,due,dueDate, status chip (draft|issued|partial|paid|overdue|cancelled—invoice.schema.ts:7-14). - Empty: "No invoices for this student."
- Analytics:
(proposed)student_invoices_view.
6. Invoice Detail /fees/invoices/:id
- Purpose: authoritative per-invoice state: amount, discounts, dues, payment history, receipt access.
- Backend (composition): invoices from the student-invoices list (no
GET /fees/invoices/:idendpoint exists — OQ-3); payment history viaGET /payments/invoice/:invoiceId(payments.controller.ts:57-61). - Elements: header card (status chip, total/paid/due amounts), discounts block
(
discounts[]snapshot,invoice.schema.ts:46-50), due date (overdue styling), payment history rows (v2 payments:transactionReference, amount, status,gateway), actions: Record payment (till), Pay online(forward-looking), View receipt(proposed)(from v2 receipt). - Empty payments: "No payments recorded yet."
- Analytics:
(proposed)invoice_detail_view, payment_record_tap.
7. Record Payment (till) /fees/invoices/:id/pay (sheet or page)
- Purpose: post an offline payment against an invoice.
- Backend:
POST /fees/invoices/:id/payments(fees.controller.ts:70-74). - Elements: amount field (prefilled with
due), payment method selector (cash|bank_transfer|mobile_money|cheque|other—record-payment.dto.ts:21-25), reference, paid date (AppDatePicker), notes; submit with idempotency key. - States: success → snackbar + receipt hint; 409 (paid/cancelled) → info banner; replay-key behavior never double-posts.
- Analytics:
(proposed)payment_recorded, payment_record_failed.
8. Dues List /fees/dues
- Purpose: everything outstanding with
due = total − paid. - Backend:
GET /fees/duespaginated (fees.controller.ts:76-80);data: [{invoice, due}](fees.service.ts:213-216). - Elements: filter chips (Issued/Partial/Overdue), rows: student ref, structure,
due(mono tabular), status chip,dueDate; row tap → invoice detail; "Collect" inline button → record payment sheet;RefreshIndicator+ infinite scroll (pagination,pagination-query.dto.ts:13-19). - Empty: "All settled — nothing outstanding."
- Analytics:
(proposed)dues_view, dues_collect_tap.
9. Dues Report /fees/dues/report (proposed)
- Purpose: admin aggregation (totals by class/status).
- Backend: none —
GET /fees/reports(Fees.md:31) is not implemented; client composes from paginated dues (acceptable at small scale)(proposed). - Elements:
AppCharts(bar/donut), totals, export (CSV)(proposed). - Analytics:
(proposed)report_view.
10. Payments (online, v2) — shared with Payments module
- Purpose: transaction history, gateway status, refunds.
- Backend:
GET /payments(list, page/limit —payments.controller.ts:45-49),GET /payments/:id(:51-55),GET /payments/invoice/:invoiceId(:57-61),POST /payments/refund(:30-34). - Elements: rows (transactionReference, amount,
gateway, status chip fromPaymentStatusincl.partially_refunded,payments/schema/payment.schema.ts:18-26), detail withgatewayResponse,refundedAmount; refund dialog. - Empty: "No transactions."
11. Receipts /payments/receipts, /payments/receipts/:id
- Purpose: receipt list + printable receipt view.
- Backend:
GET /payments/receipts(payments.controller.ts:63-67),GET /payments/receipts/:id(:69-73). - Elements: receipt doc rendered as document (
receipt.schema.ts:7-41): receiptNumber, payer, amount,fee, currency, paymentMethod, description, issuedAt; actions: Print / Share (share sheet)(proposed). - Empty: "No receipts yet."
12. Reminders Screen /fees/reminders (planned)
- Purpose: see which invoices are about to be / were reminded.
- Backend: none — reminder fan-out exists only as a queue job
(
fee-reminder.job.ts:16-42,send-payment-reminderonpayment-reminder), no list endpoint, no worker. UI deferred until backend wiring (OQ-6). - Elements: read-only list of dues due within 3 days (client-computed mirror of
the job's query
now ≤ dueDate ≤ now+3d,fee-reminder.job.ts:20-23), marked(planned).
13. Payment status chips (shared across screens)
| Status | Chip | Source |
|---|---|---|
invoice draft | neutral | invoice.schema.ts:8 |
invoice issued | primary outline | :9 |
invoice partial | tertiary | :10 |
invoice paid | success | :11 |
invoice overdue | error | :12 |
invoice cancelled | neutral | :13 |
payment pending/processing/failed/refunded/partially_refunded/cancelled | per status | payments/schema/payment.schema.ts:18-26 |
structure isActive | success/neutral | fee-structure.schema.ts:36-37 |
Shared components used
AppCard, AppListTile, AppBadge (chips), AppButton, AppFAB, AppDialog,
AppBottomSheet, AppTextField, AppDropdown, AppDatePicker, AppSearchBar,
AppChips, AppCharts, AppStatTile, AppInfoRow, AppSkeleton,
AppEmptyState, AppErrorState, AppOfflineBanner, AppSnackbar — all from
00-shared/03 (see 07_Component_Library.md for module additions).
Analytics events (proposed) — 00-shared/10 §8
fees.screen_view(dues|structures|structure|invoices|invoice|payment|receipts),
fees.invoice_generate(ok|duplicate), fees.payment_recorded,
fees.payment_failed(code), fees.structure_created/updated/deleted,
fees.report_view. All wired through shared AnalyticsService when it lands.
Keyboard, landscape, tablet, desktop
- Phone: bottom-sheet payment form; tablet: 2-column dues/structure lists
(≥ 840 dp master-detail per 00-shared/02 §8); desktop: navigation rail,
hover states, full-width report
(proposed). - Keyboard:
.nextthrough forms,Ctrl/Cmd+Entersubmit on desktop,N= new structure (desktop).