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

05 — Screen Inventory (Fees Module)

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); only issued|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/structures paginated (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 from isActive, 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/academicYearId are immutable after create — not in UpdateFeeStructureDto (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|cancelledinvoice.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/:id endpoint exists — OQ-3); payment history via GET /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|otherrecord-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/dues paginated (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: noneGET /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 from PaymentStatus incl. partially_refunded, payments/schema/payment.schema.ts:18-26), detail with gatewayResponse, 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-reminder on payment-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)

StatusChipSource
invoice draftneutralinvoice.schema.ts:8
invoice issuedprimary outline:9
invoice partialtertiary:10
invoice paidsuccess:11
invoice overdueerror:12
invoice cancelledneutral:13
payment pending/processing/failed/refunded/partially_refunded/cancelledper statuspayments/schema/payment.schema.ts:18-26
structure isActivesuccess/neutralfee-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: .next through forms, Ctrl/Cmd+Enter submit on desktop, N = new structure (desktop).