# SDM Backend — Project Overview

## What This System Is

The **SDM (Satsang Diksha Mahotsav)** platform is a multi-role event management and registration system for a large-scale religious event. It handles:

- Couple registrations with OTP-based phone verification
- Multi-tier payment collection (online via Razorpay, cash via karyakarta hierarchy)
- Role-based access across SUPER_ADMIN → PRADESH_ADMIN → MANDAL_ADMIN → KARYAKARTA → PERSONAL
- Nimit Sevak (volunteer) registration and seva management
- Cashflow settlement from mandals up to super admin
- Analytics dashboards, notifications, receipt generation
- Admin panel for accounts and data management

---

## Tech Stack

| Layer | Technology |
|---|---|
| Runtime | Node.js (ESM, `"type": "module"`) |
| Framework | Express 5 |
| ORM | Prisma 7 |
| Database | PostgreSQL (Neon serverless) |
| Auth | JWT (`jsonwebtoken`) |
| File Storage | Firebase Storage (`firebase-admin`) |
| Payments | Razorpay |
| Logging | Logtail (`@logtail/node`) + structured request logging |
| Notifications | In-DB notification table + Slack + WhatsApp |

---

## Repository Structure

```
sdm-backend/
├── src/
│   ├── app.js                    # Express app entry point
│   ├── config/                   # DB client, Firebase init
│   ├── constants/
│   │   ├── auth.js               # JWT TTL (AUTH_TOKEN_EXPIRES_IN)
│   │   └── roles.js              # Role constants & normalization helpers
│   ├── controllers/              # Route handler logic
│   │   ├── adminController.js
│   │   ├── analyticsController.js
│   │   ├── authController.js
│   │   ├── cashflowController.js
│   │   ├── dbEditorController.js
│   │   ├── formController.js
│   │   ├── karyakartaDataController.js
│   │   ├── notificationController.js
│   │   ├── paymentController.js
│   │   ├── registrationController.js
│   │   └── transactionController.js
│   ├── middleware/
│   │   ├── authMiddleware.js
│   │   ├── chequeUploadMiddleware.js
│   │   ├── dbEditorMiddleware.js
│   │   ├── haridhamReceiptUploadMiddleware.js
│   │   ├── karyakartaDataUploadMiddleware.js
│   │   ├── loggingMiddleware.js
│   │   ├── profileImageUploadMiddleware.js
│   │   └── registrationUploadMiddleware.js
│   ├── routes/                   # Express routers (maps 1-to-1 with controllers)
│   ├── services/
│   │   ├── analyticsService.js
│   │   ├── firebaseStorageService.js
│   │   ├── haridhamReceiptFetchService.js
│   │   ├── nimitSevakReceiptApiService.js
│   │   ├── nimitSevakReceiptService.js
│   │   ├── notificationService.js
│   │   ├── otpPolicyService.js
│   │   ├── receiptService.js
│   │   ├── registrationDocumentService.js
│   │   ├── slackService.js
│   │   └── whatsappTemplateService.js
│   └── utils/
│       └── logger.js
├── prisma/
│   ├── schema.prisma             # Full data model
│   ├── prisma-seed.js
│   └── daily-db-backup.js
├── private-seeds/                # One-off migration/seed scripts (not committed to prod flow)
├── docs/                         # ← Backend documentation (start at 00-docs-index.md)
├── .env                          # Production env (DATABASE_URL points to production DB)
├── .env.local                    # Local dev env (DATABASE_URL points to dev DB)
├── package.json
└── prisma.config.ts              # Prisma 7 config (reads DOTENV_FILE)
```

---

## API Base Path

All routes are prefixed with `/api`:

| Route prefix | Module |
|---|---|
| `/api/auth` | Authentication |
| `/api/registration` | Registration CRUD |
| `/api/form` | Public form data (rates, hierarchy, karyakarta lookup) |
| `/api/payment` | Razorpay payment sessions + webhook |
| `/api/transaction` | Transaction management |
| `/api/cashflow` | Cashflow bunch settlement |
| `/api/analytics` | Dashboard analytics |
| `/api/admin` | Admin panel: registrations, accounts, transactions, mahayag rates, svayam seva |
| `/api/notifications` | In-app notifications |
| `/api/karyakarta-data` | KaryakartaDataTable CRUD |
| `/api/db-editor` | Privileged raw DB editing (super admin only) |
| `/api/observability` | Health/observability endpoints |

---

## Environment Variables

### Required

```dotenv
DATABASE_URL=postgresql://...
JWT_SECRET=...
FIREBASE_SERVICE_ACCOUNT_PATH=...    # Or use GOOGLE_APPLICATION_CREDENTIALS
RAZORPAY_KEY_ID=...
RAZORPAY_KEY_SECRET=...
```

### Optional (with defaults)

```dotenv
AUTH_TOKEN_EXPIRES_IN=7d
DB_APPLICATION_NAME=sdm-backend-api
PG_POOL_MAX=10
PG_IDLE_TIMEOUT_MS=30000
PG_CONNECT_TIMEOUT_MS=10000
FORM_CACHE_TTL_MS=300000          # Cache for mahayag-rates and hierarchy
FORM_DETAIL_CACHE_TTL_MS=120000   # Cache for karyakarta/:code lookup
DOTENV_FILE=.env                   # Which env file to load (set by npm scripts)
```

---

## npm Scripts

| Script | Purpose |
|---|---|
| `npm run dev` | Start with `.env.local` (dev DB) + nodemon |
| `npm run prod` | Start with `.env` (production DB) |
| `npm run build` | `prisma generate` only |
| `npm run prisma:push:local` | Push schema to dev DB |
| `npm run prisma:push:prod` | Push schema to prod DB (use carefully — see DB doc) |
| `npm run prisma:migrate:prod` | Apply migrations to prod DB with owner credentials |
| `npm run prisma:studio:local` | Open Prisma Studio against dev DB |
| `npm run backup:daily` | Run DB backup script |
| `npm run seed:core-data` | Seed Pradesh/Mandal master data |

---

## Logging

- `console.log/warn/error` are overridden at startup to route through the structured `logger` (Logtail).
- Request logging middleware attaches `x-request-id` to every inbound request.
- Use `x-request-id` to correlate frontend actions with backend log entries in production.
- Filter Neon query logs by `application_name = sdm-backend-api` to isolate API traffic from seed scripts.
