Skip to content

veerpatta/schoolfees

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

509 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

๐Ÿซ VPPS Fee Management

Internal fee-office platform for Shri Veer Patta Senior Secondary School

One school ยท one tenant ยท built for the office, accounts team, and admins โ€” not parents, not the public.

Next.js React TypeScript Supabase Tailwind CSS Vitest Deployed on Vercel

๐Ÿ”— Live app: schoolfees-two.vercel.app ยท ๐Ÿ“ฆ Repo: github.com/veerpatta/schoolfees


โœจ TL;DR

A fast, append-only, audit-ready fee desk that replaces the office Excel workbook. Staff maintain Students and Fee Setup; everything else โ€” dues, dashboards, defaulters, receipts, exports โ€” derives automatically. Money records are immutable; corrections flow through adjustments. It's production-live for AY 2026-27 with real data. ๐ŸŸข

๐ŸŽฏ Audience Office staff, accounts team, school admins (internal only)
๐Ÿงพ Core job Collect fees, print receipts, track dues, chase defaulters
๐Ÿ”’ Promise Posted payments/receipts are never edited in place
๐Ÿ”„ Magic Change a fee โ†’ unpaid dues update everywhere, no manual sync
โ˜๏ธ Stack Next.js 16 (App Router) ยท Supabase (Postgres + RLS, Mumbai) ยท Vercel

๐Ÿงญ Table of Contents


๐Ÿ—๏ธ Architecture

flowchart TB
    subgraph Browser["๐Ÿง‘โ€๐Ÿ’ผ Office Browser (PWA)"]
        UI["shadcn/ui ยท Tailwind ยท React 19"]
    end

    subgraph Vercel["โ–ฒ Vercel (Next.js 16 App Router)"]
        RSC["React Server Components"]
        SA["Server Actions"]
        API["Route Handlers /api"]
        CRON["โฐ Vercel Cron"]
    end

    subgraph Supabase["๐ŸŸข Supabase ยท Mumbai (ap-south-1)"]
        AUTH["Auth (JWT)"]
        PG[("Postgres + RLS")]
        RPC["SECURITY DEFINER RPCs"]
        MV["Materialized views\n(financial projection)"]
        PGCRON["pg_cron */2"]
    end

    UI -->|navigation / forms| RSC
    UI -->|mutations| SA
    UI -->|data fetch| API
    RSC --> PG
    SA --> RPC
    API --> PG
    RPC --> PG
    PG --> MV
    PGCRON --> MV
    CRON -->|nightly backup ยท auto day-close| API
    AUTH -. row-level security .-> PG
Loading

Why it's shaped like this

  • ๐Ÿง  Server-first โ€” RSC + Server Actions keep logic and secrets on the server; the browser only renders.
  • ๐Ÿ” Two-layer auth โ€” app-layer guards (requireStaffPermission) and Postgres RLS. Defense in depth.
  • โšก Read/write split โ€” writes hit live RPCs; heavy dashboards read pre-computed materialized views kept fresh on every write (with a 2-min cron backstop, see Automation).

๐Ÿ”‘ The one rule: Source of Truth

Students + Fee Setup are canonical. Everything else derives from them โ€” automatically.

flowchart LR
    A["๐Ÿ‘จโ€๐ŸŽ“ Students"] --> R{{"โ™ป๏ธ Dues\nregeneration"}}
    B["๐Ÿ“‹ Fee Setup\n(fees ยท fee heads ยท dates)"] --> R
    R --> I["๐Ÿงพ Installments\n(unpaid rows only)"]
    I --> MV["๐Ÿ“Š Materialized views"]
    MV --> D["๐Ÿ“ˆ Dashboard"]
    MV --> DF["๐Ÿ“ž Defaulters"]
    MV --> EX["๐Ÿ“ค Exports"]
    MV --> TX["๐Ÿ“š Transactions"]
    PD["๐Ÿ’ต Payment Desk"] -->|live snapshot| I
    style R fill:#fde68a,stroke:#d97706,color:#000
    style I fill:#bbf7d0,stroke:#16a34a,color:#000
Loading
  • Edit a fee, fee head, or due date โ†’ only unpaid installments are rebuilt (paid rows are frozen โ€” see safety).
  • The Payment Desk always previews/posts against a live allocation snapshot, so collection is never stale.
  • Dashboards/exports refresh on every write; worst-case catch-up is โ‰ค 2 minutes.

๐Ÿงฉ Modules

All staff modules live under app/protected/ with a parallel three-layer shape: app/protected/<module> (routes) + components/<module> (UI) + lib/<module> (domain logic).

Module Route What it does
๐Ÿ“Š Dashboard /protected/dashboard Read-only analytics: collected, pending, %, class-wise, top defaulters
๐Ÿ‘จโ€๐ŸŽ“ Students /protected/students Student master + per-student fee exceptions & discounts
๐Ÿ“‹ Fee Setup /protected/fee-setup Yearly policy: tuition, transport, due dates, late fee, fee heads
๐Ÿ’ต Payment Desk /protected/payments The only place payments are posted; prints receipts
๐Ÿ“š Transactions /protected/transactions Read-only receipts, dues, ledger, class register
๐Ÿ“ž Defaulters /protected/defaulters Daily call list with smart heat ranking & follow-up
๐Ÿ“ค Exports /protected/exports XLSX download center + AI context bundle
๐Ÿ› ๏ธ Admin Tools /protected/admin-tools Year transfer, refunds, day-close, settings, staff, audit
๐Ÿงพ Receipts /protected/receipts Lookup & reprint (A4)
๐Ÿ’ณ Finance Controls /protected/finance-controls Auto day-close view, refunds, correction review
๐Ÿ—‚๏ธ Master Data /protected/master-data Sessions, classes, routes, fee heads, payment modes
๐Ÿ‘ฎ Staff /protected/staff Accounts & RBAC
๐Ÿ“ฅ Imports /protected/imports Staged student import (upload โ†’ map โ†’ dry-run โ†’ commit)

๐Ÿ‘ฅ Roles & Access

Five roles (lib/auth/roles.ts). Navigation visibility and landing routes are permission-driven.

Role ๐Ÿ  Lands on Can do
๐Ÿ‘‘ admin Dashboard Everything
๐Ÿงฎ accountant Payment Desk Collect, refunds, finance controls, reports
๐ŸŽ teacher Students Students, dues, defaulters (read payments)
๐Ÿ“ž fee_collector Defaulters Follow-up + student reads
๐Ÿ‘€ view_only Dashboard Read-only

Legacy aliases still resolve: read_only_staff โ†’ view_only, defaulter_followup โ†’ fee_collector.


๐Ÿ’ฐ Financial integrity (read this)

Money is append-only. payments and receipts are never updated or deleted โ€” Postgres triggers physically block it. Corrections happen as new payment_adjustments rows with an audit trail. Refunds post a reversal adjustment.

The three reductions โ€” never conflate them ๐Ÿง 

flowchart TD
    F["Annual fee a student owes"]
    F -->|"1๏ธโƒฃ tuition discount\n(RTE / staff child / 3rd child)"| F2["Lower base due"]
    F2 -->|"collect cash"| P["Total paid ๐Ÿ’ต"]
    F2 -->|"2๏ธโƒฃ discount close-out\n(write-off, mode='discount')"| W["Pending cleared\nโ—NOT counted as paid"]
    LF["Late fee (โ‚น1,000 flat)"] -->|"3๏ธโƒฃ late-fee waiver"| LF2["Reduced/zero late fee"]
    style P fill:#bbf7d0,stroke:#16a34a,color:#000
    style W fill:#fecaca,stroke:#dc2626,color:#000
Loading
# Reduction Affects Counted as paid?
1๏ธโƒฃ Tuition discount lowers the base fee โŒ no
2๏ธโƒฃ Discount close-out (write-off) clears pending balance โŒ no
3๏ธโƒฃ Late-fee waiver waives late fee only โŒ no

The "paid" formula (per installment, in the projection view):

applied_amount = max( real_cash_payments + payment_adjustments , 0 )
total_paid     = ฮฃ applied_amount          # excludes discount-mode receipts & tuition discounts

So Total due โˆ’ Total paid is not always Outstanding when a write-off exists โ€” always trust the Outstanding column, which nets everything. โœ…


๐Ÿ” Year-end: Transfer to Next Session

One click in Admin Tools โ†’ Transfer to Next Session rolls the school forward.

sequenceDiagram
    actor Admin
    participant T as Transfer flow
    participant DB as Supabase
    Admin->>T: From 2026-27 โ†’ To 2027-28
    T->>DB: Create session + copy classes, fee policy,<br/>discount policies, fee settings
    T->>DB: Build promotion preview (Class N โ†’ N+1)
    Admin->>T: Review & Apply โœ…
    T->>DB: Promote students, carry credit forward
    Note over Admin,DB: ๐Ÿงฏ Roll back anytime ยท ๐Ÿ—‘๏ธ delete a<br/>โ‰ค30-day, zero-payment session by mistake
Loading
  • ๐Ÿ“‹ Copies classes, fee policy, conventional discount policies, and per-class fee settings โ€” all editable afterwards.
  • ๐ŸšŒ Transport routes are global, shared across years automatically.
  • ๐Ÿ—‘๏ธ A session created by mistake can be hard-deleted within 30 days only if it has zero posted payments/receipts (immutability-safe).

๐Ÿค– Automation (cron)

No manual buttons. The system keeps itself in sync and closed.

โฐ Job Schedule What it does
๐ŸŒ™ Nightly backup 0 18 * * * UTC (23:30 IST) CSV dump of core tables โ†’ Supabase Storage
๐Ÿ”’ Auto day-close 30 18 * * * UTC (00:00 IST) Snapshots yesterday's collections โ†’ collection_closures (read-only, no approval)
โ™ป๏ธ Mat-view refresh */2 * * * * (pg_cron) Backstop that re-refreshes financial views if a write-time refresh was skipped

Day close is fully automatic โ€” staff never tap a button. Finance Controls shows it read-only.


๐Ÿ“ค Exports (incl. the AI bundle)

Every export streams all rows (no page caps) as XLSX. ๐Ÿงพ

  • ๐Ÿ‘จโ€๐ŸŽ“ All students ยท ๐Ÿ“Š Class-wise dues ยท ๐Ÿ“ž Defaulters ยท ๐Ÿงพ Receipt register ยท ๐ŸŽ Conventional-discount students
  • ๐Ÿค– AI context bundle โ€” a single workbook designed to feed an LLM: _README (data dictionary) ยท Students (all statuses) ยท Installments ยท Payments ยท Adjustments ยท Refunds ยท Classes ยท Routes ยท Discounts ยท Defaulters ยท Recovery Follow-Up ยท Previous Year Dues ยท Left Student Recovery ยท Sessions. Every sheet joins on SR no.

๐Ÿงฎ Fee engine internals

Engine: workbook_v1 (lib/fees/, lib/workbook/).

Object Role
v_workbook_student_financials Per-student projection (materialized)
v_workbook_installment_balances Installment-level balances (materialized)
v_student_financial_state Pending vs credit/refund projection
preview_workbook_payment_allocation Date-aware live preview RPC
post_student_payment Posting RPC (idempotency + advisory locks)
process_refund_with_adjustment Posts reversal adjustments for a refund
delete_academic_session_safe Guarded โ‰ค30-day, zero-payment session delete

๐Ÿ“ Canonical fee rules: docs/product/school-rules.md + lib/config/fee-rules.ts.


๐Ÿš€ Quick start

git clone https://github.com/veerpatta/schoolfees.git
cd schoolfees
npm install
cp .env.example .env.local   # fill in Supabase keys
npm run dev                  # โ†’ http://localhost:3000

Common commands

npm run dev          # ๐Ÿ”ฅ dev server
npm run check        # โœ… lint + typecheck
npm run test         # ๐Ÿงช vitest (777 tests)
npm run build        # ๐Ÿ“ฆ production build
npx vitest run tests/integration/payment-desk-workflow.test.ts   # single file

๐Ÿ”ง Environment variables

Copy .env.example โ†’ .env.local.

Variable Required Notes
NEXT_PUBLIC_SUPABASE_URL โœ… Supabase project URL
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY โœ… Anon / publishable key
SUPABASE_SERVICE_ROLE_KEY โœ… Server-only โ€” never in browser/NEXT_PUBLIC_*
NEXT_PUBLIC_SITE_URL โœ… Prod domain (http://localhost:3000 locally)
NEXT_PUBLIC_SCHOOL_NAME โœ… Shri Veer Patta Senior Secondary School
NEXT_PUBLIC_APP_MODE โœ… internal-admin
CRON_SECRET โœ… (prod) Authorizes Vercel cron routes
BOOTSTRAP_*_PASSWORD โš™๏ธ One-time staff seeding only

๐Ÿ—„๏ธ Database & migrations

Project: vgqyilgstjvgohrsiwkb ยท Supabase Mumbai (ap-south-1).

supabase migration new <short_snake_case_name>
# edit supabase/migrations/<timestamp>_<name>.sql
supabase db push

๐Ÿ”Ž Operational verifiers

Read-only health checks (need Supabase env vars; see scripts/README.md for the full list):

node scripts/verify-phase1-migrations.mjs   # phase-1 session-sync migration/readiness check
node scripts/verify-required-sessions.mjs   # confirms required academic sessions exist
node scripts/verify-live-fee-health.mjs     # production fee-health verification
node scripts/verify-live-sync-health.mjs    # system sync verification

โœ… Quality gates

Run before every PR (AGENTS.md order): typecheck โ†’ lint โ†’ test โ†’ build.

โœ” tsc --noEmit        clean
โœ” eslint .            0 errors / 0 warnings
โœ” vitest run          777 / 777 passing
โœ” next build          green

Test layout: tests/unit (pure/domain) ยท tests/integration (workflows) ยท tests/ui (routes/components).


๐Ÿ›ก๏ธ Hard safety rules

  1. ๐Ÿšซ Never edit/delete posted payments or receipts โ€” correct via payment_adjustments.
  2. ๐Ÿ”‘ SUPABASE_SERVICE_ROLE_KEY stays server-only.
  3. ๐Ÿ™… Public signup stays disabled after bootstrap.
  4. ๐Ÿ’ต No payment-posting path outside the Payment Desk.
  5. ๐ŸŸฅ 2026-27 is live production data โ€” use TEST-2026-27 for all testing; never post test payments against real students.
  6. ๐Ÿ“‹ Fee Setup publish must preview impact and protect paid/partial/adjusted rows.

๐Ÿ“š Docs map

Path What's inside
docs/product/ Project context, MVP scope, school rules, roadmap
docs/modules/ Per-module guides (import, payment-desk, exports, โ€ฆ)
docs/maps/ Folder map, database map, module map, danger zones
docs/workflows/ Test-data setup, production operations
CLAUDE.md / AGENTS.md Contributor + agent guide
PRODUCTION_OPERATIONS_CHECKLIST.md ยท UAT_CHECKLIST.md Go-live & UAT

Internal software for Shri Veer Patta Senior Secondary School. Not for public distribution.

Built with โค๏ธ for the fee office ยท maintained with append-only discipline ๐Ÿ”’

About

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors