Skip to content

Commit f4d4c5f

Browse files
committed
Optimize import/export performance and add PWA support
- Fix bulkAppendCharges: ~400x faster with batch operations - Fix bulkAppendPayments: ~400x faster with batch operations - Fix releaseUploadDeferred: ~100x faster with collectionGroup query - Fix recalcAll: ~100x faster with collectionGroup query - Fix importAll: ~100x faster with data integrity (collectionGroup delete + batch write) - Remove first-time historical register import option - Rename to 'Upload charges or payments' with column selection - Add payment mode support (Cash/Bank) - Add 3 export options: all households, by period, owing list - Add delete all data function with safety confirmations - Add PWA manifest.json and service worker - Add PWA meta tags to index.html
0 parents  commit f4d4c5f

4 files changed

Lines changed: 2442 additions & 0 deletions

File tree

README.md

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
# NSNVC Citizen Contribution Tracker
2+
3+
A lightweight web app for the **New Serchhip North Village Council (NSNVC)**, Mizoram, India, to track monthly citizen contributions (derived from MGNREGA wages) for each household — and let citizens look up their own balance.
4+
5+
**Live site:** https://enga018.github.io/nsnvc-contribution/
6+
7+
It is a single HTML file. No build step, no server of its own — just static hosting plus Firebase for data and admin login.
8+
9+
---
10+
11+
## What it does
12+
13+
### For citizens (public, no login)
14+
- Look up a contribution balance by typing the **job card number** (the part after the slash is enough).
15+
- See a clean statement: name, status (Cleared / Due / Partly paid), the amount still to pay, and a collapsible payment history (oldest first).
16+
- Browse the list of households who still owe.
17+
- **Pay Now (UPI):** opens the citizen's UPI app (GPay / PhonePe / Paytm) with the council's UPI ID and amount pre-filled. The council confirms the payment manually once it arrives.
18+
19+
### For the council (admin, email/password login)
20+
- Dashboard with a single **"Still to collect"** figure (total outstanding + number of pending households).
21+
- Filter households by **Pending / Paid / Deferred / All**, and by **period** ("Pending: January", etc.).
22+
- Open any household to add a contribution, record a payment, **mark fully paid**, **forgive** part or all of a balance, or **defer** a charge (for someone still awaiting their wages).
23+
- **Edit or delete** any history entry; balances recompute from the ledger automatically.
24+
- **Import from Excel:**
25+
- First-time historical register (one-time, with a guard against duplicating existing data).
26+
- Monthly update file — detects the layout and asks you to confirm which column is the job card, name and amount, so fixed header names aren't required.
27+
- Bank payment file — records payments and flags rows it can't match.
28+
- A duplicate-period guard warns before re-importing a period already added.
29+
- **Export** the owing list (with payment detail) as CSV.
30+
- **Backup & restore:** download a full JSON backup of every household and its history, or restore from one.
31+
- **Recalculate all balances** — rebuilds every total from its history if anything ever looks off.
32+
33+
---
34+
35+
## Tech stack
36+
37+
- **Vanilla JavaScript**, single `index.html` (no frameworks, no bundler)
38+
- **Firebase Firestore** — database
39+
- **Firebase Authentication** — admin login (email/password)
40+
- **SheetJS (xlsx)** — Excel parsing, loaded on demand from a CDN
41+
- **GitHub Pages** — free static hosting
42+
43+
The app runs in a local **test mode** with sample data if no Firebase config is present, so you can try the UI without a backend.
44+
45+
---
46+
47+
## Setup
48+
49+
### 1. Firebase
50+
1. Create a Firebase project and enable **Firestore** and **Authentication → Email/Password**.
51+
2. Add an admin user under Authentication.
52+
3. Copy your web app config into the `firebaseConfig` object near the top of `index.html`:
53+
54+
```js
55+
const firebaseConfig = {
56+
apiKey: "",
57+
authDomain: "YOUR_PROJECT.firebaseapp.com",
58+
projectId: "YOUR_PROJECT",
59+
storageBucket: "YOUR_PROJECT.firebasestorage.app",
60+
messagingSenderId: "",
61+
appId: ""
62+
};
63+
```
64+
65+
> The web `apiKey` is **not** a secret — it is meant to ship in client code. Access is controlled by Firestore security rules, not by hiding the key.
66+
67+
### 2. Firestore security rules
68+
Public read (so citizens can look up balances), admin-only write:
69+
70+
```
71+
rules_version = '2';
72+
service cloud.firestore {
73+
match /databases/{database}/documents {
74+
75+
match /citizens/{cid} {
76+
allow read: if true;
77+
allow write: if request.auth != null && request.auth.token.email == "YOUR_ADMIN_EMAIL";
78+
match /{sub=**} {
79+
allow read: if true;
80+
allow write: if request.auth != null && request.auth.token.email == "YOUR_ADMIN_EMAIL";
81+
}
82+
}
83+
84+
match /meta/{doc} {
85+
allow read: if true;
86+
allow write: if request.auth != null && request.auth.token.email == "YOUR_ADMIN_EMAIL";
87+
}
88+
89+
}
90+
}
91+
```
92+
93+
Replace `YOUR_ADMIN_EMAIL` with your admin login email. The `meta` rule lets the duplicate-import guard remember which periods have been imported.
94+
95+
### 3. Deploy
96+
Commit `index.html` to the repo and enable **GitHub Pages** (Settings → Pages → deploy from branch). The app is served from the repo's `index.html`.
97+
98+
---
99+
100+
## Data model (brief)
101+
102+
Each household is a document in the `citizens` collection, keyed by its full job card (with `/` encoded). It stores name, job card, totals (`totalCharged`, `totalPaid`, `balance`, `deferredTotal`) and a `ledger` subcollection of entries:
103+
104+
- `charge` — a period's contribution (can be `deferred`)
105+
- `payment` — money received (cash / bank / UPI)
106+
- `forgive` — a waived amount
107+
108+
Balances are derived from the ledger: effective balance = (charges excluding deferred) − payments. Payments are not tied to specific periods; the period filter applies them oldest-first (FIFO).
109+
110+
---
111+
112+
## Backups
113+
114+
The data lives only in Firestore, so **take a backup regularly**: Admin → Backup / Restore → Download backup. Keep the JSON file somewhere safe. Restore reads that file back. There is no automatic off-site backup.
115+
116+
---
117+
118+
## Notes
119+
120+
- Designed for low-end phones and patchy connectivity — minimal, fast, single file.
121+
- Built and maintained for NSNVC, Mizoram.

0 commit comments

Comments
 (0)