geocrop-platform./apps/nextgen/.harness/changelogs/2026-07-06-phase2c.md

4.3 KiB

Finance Phase 2c — Accountant dashboard + Student/Parent portals

Plan: .harness/plans/hr-finance-fiscalisation.md §10c Branch: feature/finance-phase-2c (worktree .worktrees/finance-phase-2c/) Owners: backend-expert (enriched summary + students-fees helper) → frontend-expert (portal rewrites) → code-reviewer.

What landed

The last mile: dashboards and student/parent portals that consume everything §10a and §10b produced.

Backend

  • server/src/controllers/finance.controller.js/api/finance/dashboard/summary enriched with six new tiles:

    • overdue_invoices (invoices past due, not paid/cancelled)
    • open_invoices (issued/partial/overdue count)
    • upcoming_trips_30d (published trips departing in next 30 days)
    • pending_reconciliations (bank sessions with discrepancies)
    • installments_due_14d (student_fees due in next fortnight)
    • student_groups_count

    Shape is backwards compatible — the original five fields (collected_mtd, outstanding_fees, payroll_last_run, expenses_mtd, pending_expenses) are unchanged.

  • server/src/controllers/students-fees.controller.js — new file mounted at /api/students. Single-student profile endpoint:

    GET /api/students/:uid/fees
    

    Returns { student, fees, trips, summary } where fees rows include discount_amount and a hydrated discounts[] array (name, kind, amount_applied) and trips rows are the user's trip_payments joined to trips. RBAC gates by parent/child link or by student self. This powers the new student and parent view pages.

Frontend

# File Route / Role Notes
1 client/src/pages/dashboard/AccountantDashboard.tsx /dashboard/accountant Accountant-specific landing with 4 KPI tiles, 3 entry CTAs (plans / discounts / groups), expense-approval summary, and a compact "latest activity" feed.
2 client/src/pages/dashboard/FinanceDashboard.tsx /dashboard/finance (modified) Second tile row added — Open Invoices / Trips next 30d / Reconciliations / Student Groups — wired to the enriched summary endpoint.
3 client/src/pages/student/Fees.tsx /student/fees (new), /fees (also mapped) New student fees portal: fee lines with discount-row expander, trips table below, KPI tiles. Backed by /api/students/:uid/fees.
4 client/src/pages/parent/Fees.tsx (modified) Switched data source to /api/students/:uid/fees; falls back to legacy /fees/students if the new endpoint isn't available. Total-outstanding now subtracts discount_amount so partial-paid lines show the correct balance.

Wiring

  • client/src/App.tsx — registered /dashboard/accountant for school_admin / systems_admin / principal / bursar, and /student/fees + /fees for the student role.
  • client/src/components/Nav.tsxaccountant block already pointed at /dashboard/accountant (§10a). Added "My Fees" entry to the student block.
  • SCREENS.md — Bursar / Accountant / Student nav rows up-to-date via the Nav entries; no body edits needed.

Smoke

GET /api/finance/dashboard/summary
→ { collected_mtd, outstanding_fees, payroll_last_run, expenses_mtd,
    pending_expenses,
    overdue_invoices, open_invoices, upcoming_trips_30d,
    pending_reconciliations, installments_due_14d, student_groups_count }

GET /api/students/:uid/fees
→ { student, fees:[...with discounts[]], trips:[...], summary }

Logging in as student@school.com and fetching /api/students/:uid/fees returns the same envelope. Login as a random student and self-fetch: the self-scope guard passes (200). Login as a random non-parent and fetch someone else's: 403 with error message.

Deviations from the plan

  1. Single Students /fees controller mounted at /api/students instead of /api/student-fees — keeps the URL hierarchy aligned with /api/students (which already exists for the Students module).
  2. Parent fees page keeps the legacy fallback so a partial rollout doesn't break the existing UX. New endpoint wins when present.
  3. No PDF invoice generation — kept the existing printable HTML view from §10a. PDF generation is §11.

Out of scope

  • Paynow webhook extension to mark trip_payments paid (§11).
  • Burn-down collection reports (§11).
  • PDF invoice generation (§11).
  • Bank-recon auto-match for trip-receipt rows (§11).