30+ tables with strict multi-tenancy (tenant_id on all tenant tables), indexes, and optional RLS policies.
Super admin users for the SaaS platform
| Column | Type | Notes |
|---|---|---|
| id | UUID PK | gen_random_uuid() |
| TEXT UNIQUE NOT NULL | Login identifier | |
| password_hash | TEXT NOT NULL | bcrypt hashed |
| totp_secret | TEXT | TOTP MFA encrypted |
| role | TEXT NOT NULL | 'SUPER_ADMIN' | 'SUPPORT' |
| last_login_at | TIMESTAMPTZ | Track activity |
| created_at | TIMESTAMPTZ DEFAULT NOW() |
All registered Gau Seva organisations
| Column | Type | Notes |
|---|---|---|
| id | UUID PK | Tenant unique ID |
| slug | TEXT UNIQUE NOT NULL | Subdomain slug (sgmm) |
| name | TEXT NOT NULL | Organisation name |
| status | TEXT NOT NULL | ONBOARDING|TRIAL|ACTIVE|GRACE|READ_ONLY|SUSPENDED|TERMINATED |
| plan_id | UUID FK โ saas_plans.id | Current plan |
| subdomain | TEXT UNIQUE | trust1.gaudaan.in |
| custom_domain | TEXT | Optional custom domain |
| branding_config | JSONB | Colors, logo, fonts |
| settings | JSONB | Feature flags, limits |
| trial_ends_at | TIMESTAMPTZ | 14-day trial expiry |
| grace_ends_at | TIMESTAMPTZ | 7-day grace period end |
| created_at | TIMESTAMPTZ DEFAULT NOW() |
Subscription tiers: Starter, Standard, Premium, Enterprise
| Column | Type | Notes |
|---|---|---|
| id | UUID PK | |
| name | TEXT NOT NULL | 'Starter'|'Standard'|'Premium'|'Enterprise' |
| price_monthly | NUMERIC(10,2) | โน999 / โน2499 / โน4999 |
| price_yearly | NUMERIC(10,2) | 15% discount |
| limits | JSONB | max_admins, max_donors, modules[] |
| features | JSONB | Feature flags array |
| is_active | BOOLEAN DEFAULT true |
Active SaaS subscriptions per tenant
| Column | Type | Notes |
|---|---|---|
| id | UUID PK | |
| tenant_id | UUID FK โ tenants.id | Tenant reference |
| plan_id | UUID FK โ saas_plans.id | Current plan |
| status | TEXT | 'ACTIVE'|'PAST_DUE'|'CANCELLED' |
| current_period_start | TIMESTAMPTZ | Billing period start |
| current_period_end | TIMESTAMPTZ | Next renewal date |
| cancel_at_period_end | BOOLEAN DEFAULT false | |
| proration_credit | NUMERIC(10,2) | Prorated amount on upgrade |
| add_ons | JSONB | Array of active add-ons |
Monthly invoices for each tenant
| Column | Type | Notes |
|---|---|---|
| id | UUID PK | |
| tenant_id | UUID FK โ tenants.id | |
| subscription_id | UUID FK | |
| invoice_number | TEXT UNIQUE | 'INV-2025-0248' |
| amount | NUMERIC(10,2) | Total amount |
| tax_amount | NUMERIC(10,2) | GST 18% |
| status | TEXT | 'DRAFT'|'PENDING'|'PAID'|'OVERDUE'|'FAILED' |
| due_date | TIMESTAMPTZ | 7 days from issue |
| paid_at | TIMESTAMPTZ | Payment timestamp |
| pdf_url | TEXT | S3 URL of invoice PDF |
| attempts | INT DEFAULT 0 | Retry count |
App donors/users per tenant
| Column | Type | Notes |
|---|---|---|
| id | UUID PK | |
| tenant_id | UUID FK โ tenants.id NOT NULL | ๐ Multi-tenancy key |
| phone | TEXT | Primary identifier |
| TEXT | Optional | |
| name | TEXT NOT NULL | Full name |
| pan_number | TEXT | Tax receipt eligibility |
| address | JSONB | For 80G certificate |
| profile_photo_url | TEXT | S3 URL |
| fcm_tokens | TEXT[] | Push notification tokens |
| gau_coins_balance | INT DEFAULT 0 | Current balance |
| created_at | TIMESTAMPTZ DEFAULT NOW() |
Tenant admin staff with role assignments
| Column | Type | Notes |
|---|---|---|
| id | UUID PK | |
| tenant_id | UUID FK โ tenants.id NOT NULL | ๐ Multi-tenancy key |
| TEXT NOT NULL | Login email | |
| password_hash | TEXT NOT NULL | bcrypt |
| role | TEXT NOT NULL | TENANT_ADMIN|FINANCE_MANAGER|CONTENT_MANAGER |
| permissions | JSONB | Granular permission overrides |
| totp_secret | TEXT | MFA secret (encrypted) |
| is_active | BOOLEAN DEFAULT true | |
| last_login_at | TIMESTAMPTZ |
Legal and operational trust information
| Column | Type | Notes |
|---|---|---|
| id | UUID PK | |
| tenant_id | UUID UNIQUE FK โ tenants.id | ๐ 1:1 with tenant |
| registration_number | TEXT | Trust reg number |
| pan_number | TEXT | Trust PAN |
| certificate_12a | TEXT | 12A registration |
| certificate_80g | TEXT | 80G certificate |
| fcra_number | TEXT | Optional FCRA |
| bank_account_name | TEXT | |
| bank_account_number_encrypted | TEXT | AES-256 encrypted |
| bank_ifsc | TEXT | IFSC code |
| bank_name | TEXT | |
| visibility_flags | JSONB | Which fields are public |
Donation campaigns and causes per tenant
| id | UUID PK | |
| tenant_id | UUID FK NOT NULL | ๐ Multi-tenancy |
| title | TEXT NOT NULL | Cause title |
| description | TEXT | Rich text |
| category | TEXT | 'gau_seva'|'medical'|'panchgavya'|'goshala' |
| target_amount | NUMERIC(12,2) | Fundraising goal |
| collected_amount | NUMERIC(12,2) DEFAULT 0 | Running total |
| is_featured | BOOLEAN | Show on home screen |
| donation_options | JSONB | Preset amounts array |
| image_url | TEXT | S3 URL |
| is_active | BOOLEAN DEFAULT true | |
| ends_at | TIMESTAMPTZ | Campaign end date |
All payment transactions
| id | UUID PK | |
| tenant_id | UUID FK NOT NULL | ๐ Multi-tenancy |
| user_id | UUID FK โ users.id | Donor |
| cause_id | UUID FK โ causes.id | What they donated to |
| amount | NUMERIC(12,2) NOT NULL | Donation amount |
| coins_used | INT DEFAULT 0 | GauCoins redeemed |
| net_amount | NUMERIC(12,2) | amount - coins_value |
| gateway | TEXT | 'razorpay'|'payu'|'custom' |
| gateway_order_id | TEXT | External order ID |
| gateway_payment_id | TEXT | External payment ID |
| status | TEXT | 'PENDING'|'CAPTURED'|'FAILED'|'REFUNDED' |
| idempotency_key | TEXT UNIQUE | Prevent duplicates |
| receipt_pdf_url | TEXT | S3 URL after generation |
| is_anonymous | BOOLEAN DEFAULT false | |
| metadata | JSONB | Gateway response raw data |
Active recurring donation mandates
| id | UUID PK | |
| tenant_id | UUID FK NOT NULL | ๐ Multi-tenancy |
| user_id | UUID FK โ users.id | Donor |
| cause_id | UUID FK | Target cause |
| amount | NUMERIC(12,2) NOT NULL | Monthly amount |
| frequency | TEXT | 'MONTHLY'|'QUARTERLY'|'YEARLY' |
| mandate_id | TEXT | Gateway mandate ID |
| status | TEXT | 'ACTIVE'|'PAUSED'|'CANCELLED'|'COMPLETED' |
| next_charge_at | TIMESTAMPTZ | Upcoming charge date |
| total_charged | INT DEFAULT 0 | Number of charges |
BYO gateway config per tenant (encrypted)
| id | UUID PK | |
| tenant_id | UUID FK NOT NULL | ๐ Multi-tenancy |
| provider | TEXT NOT NULL | 'razorpay'|'payu'|'custom' |
| key_id_encrypted | TEXT | AES-256-GCM encrypted |
| key_secret_encrypted | TEXT | AES-256-GCM encrypted |
| webhook_secret_encrypted | TEXT | AES-256-GCM encrypted |
| mode | TEXT DEFAULT live | 'test'|'live' |
| is_active | BOOLEAN DEFAULT false | |
| config | JSONB | Extra gateway-specific config |
Idempotency table for webhook deduplication
| id | UUID PK | |
| tenant_id | UUID FK | ๐ Multi-tenancy |
| gateway | TEXT NOT NULL | Gateway name |
| event_id | TEXT NOT NULL | Gateway event unique ID |
| event_type | TEXT | e.g. payment.captured |
| processed_at | TIMESTAMPTZ DEFAULT NOW() | |
| UNIQUE | (tenant_id, gateway, event_id) | Prevents double-processing |