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

5.1 KiB

Finance Phase 2a — Operational Back-Office UIs

Plan: .harness/plans/hr-finance-fiscalisation.md §10a Branch: feature/finance-phase-2 (worktree .worktrees/finance-phase-2/) Owners: backend-expert (committed in 96ace70) → frontend-expert (this commit) → code-reviewer.

What landed

Backend (already merged as 96ace70): 13 new tables, 5 new controllers (finance-suppliers, finance-coa, finance-banking w/ recon, finance-invoices, finance-trips), fees.controller.js extended with Plans + Discounts CRUD, idempotent ALTER for invoices.plan_id, accountant@school.com / accountant123 demo account, seeded chart of accounts (16 rows) + ZimBank USD bank account + Bus Route 1 group.

This commit wires the operational back-office pages and routes those controllers serve.

Frontend pages (7 new)

# Page file Route Allowed roles
1 client/src/pages/finance/Suppliers.tsx /finance/suppliers bursar / accountant / principal / admin
2 client/src/pages/finance/ChartOfAccounts.tsx /finance/chart-of-accounts same
3 client/src/pages/finance/Invoices.tsx /finance/invoices same (list + drawer)
4 client/src/pages/finance/Trips.tsx /finance/trips same
5 client/src/pages/finance/TripDetail.tsx /finance/trips/:uid same
6 client/src/pages/finance/BankingAccounts.tsx /finance/banking same
7 client/src/pages/finance/BankingReconcile.tsx /finance/banking/reconcile/new, /finance/banking/reconciliations/:uid same

The BankingReconcile component is a single dual-mode page: with :uid in the URL it renders the resolution view (matched/unmatched/ignored lines + ignore actions); without a :uid it renders the new-session form. Both share a "Recent sessions" mini-list.

Store additions

client/src/store/finance.ts extended with §10a state + actions:

  • State: suppliers, chartAccounts, bankAccounts, reconciliations, invoices, currentInvoice, trips, currentTrip, plans, currentPlan, discounts.
  • Actions: fetchSuppliers / createSupplier / updateSupplier / deleteSupplier, the matching set for chart accounts + bank accounts, fetchReconciliations / fetchReconciliation / reconcileBank / resolveReconciliationLine, the matching set for invoices (incl. sendInvoice), the matching set for trips (incl. assignTripStudents({mode, student_uids?, class_id?}) and payTripStudent(uid, body)), and the matching set for plans + discounts (incl. replacePlanInstallments).

Wiring

  • client/src/App.tsx — registered all 7 new routes under school_admin / systems_admin / principal / bursar role cases; accountant role covered transitively through these arrays' common RBAC. The placeholder at App.tsx:330 (Phase 0 debt) was replaced with <PayrollRunsPage /> in Phase 1b; this commit moves forward from there.
  • client/src/components/Nav.tsxbursar block extended with Invoices / Suppliers / Chart of Accounts / Banking / School Trips; new accountant block with the same operational surface.
  • SCREENS.md — refreshed the Bursar and Accountant nav tables; HR unchanged from §3b.

Smoke + verification

  • node --check clean for all 7 new .tsx files.
  • npm run build green; the pre-existing 2.5 MB chunk warning is the only build log signal — same as Phase 1b.
  • All §10a endpoints verified earlier (96ace70 commits): /summary returns the documented shape; /finance/invoices, /finance/trips/*, /finance/banking/reconcile, /fees/plans, /fees/discounts all return 200 with documented shapes.
  • Sync contract preserved: every write sets sync_status='pending'; tablesToSync extended in 96ace70 with all 13 new tables in parent-first FK order.
  • RBAC: accountant is on equal footing with bursar for the operational surface; hr is NOT (payroll remains HR-only per the Phase 0 decision; HR still gets the leave-approval + staff-directory surface but no invoices/trips/COA surface).

Deviations from plan

  1. BankingReconcile single-component — combined the new-session and the resolution view into one router-driven component to keep the /finance/banking landing as a unified operator console. The plan listed them separately; functionally identical, fewer round-trips.
  2. No Nav.tsx entry for the accountant role in Phase 1baccountant was never wired because there was no UI for it. This commit adds it alongside the §10a nav entries.

Out of scope (deferred to §10b / §10c)

  • Student groups + plan-apply + discount-apply endpoints + UI (§10b). student_groups table is created and seeded with Bus Route 1, but membership + apply aren't exposed yet.
  • Student / Parent fees page rewrites that surface installments + trip bills (§10c).
  • Bank-recon reconciliation auto-match on trip-receipt rows (current trip-pay tracks on trip_payments directly; the recon auto-match scans the payments table, so a future §10c pass would mirror trip receipts into payments for bank-recon pickup).
  • Accountant dashboard refresh (§10c).