SanctionDesk — SaaS Development
Budget: ₹1,500 – ₹12,500 INR
# SanctionDesk — Developer Brief
## What this is
A SaaS tool for faculty (Principal Investigators) that auto-generates procurement
paperwork — cover letter, supply order, inspection note, sanction order, and (when
applicable) a 3-firm comparative statement — from three scanned source documents
(quotation, invoice, delivery challan). It also maintains a running expenditure sheet
and stock register per project. Access is subscription-gated (paid, per PI, annual).
## What's already built (attached in this package)
- **`rules.py` / `generate.py`** — a working Python engine that takes structured project
+ purchase data and produces the correctly dated, numbered, and formatted Word
document set. Tested against a real institute document set and matches it exactly.
- **`institutes/aiims/profile.json`** — institute-specific rules (numbering format,
comparison threshold, date rules, clause wording, signatory roles), kept separate
from the engine itself. See "Multi-institute architecture" below.
- **`sample_input.json`** — example input showing the full data shape the engine expects.
- **`generated_document_set.docx`** — sample output from the engine.
- **`sanctiondesk_prototype.html`** — a clickable front-end mockup (login, project
dashboard, upload flow, document list, expenditure sheet, stock register). Static/demo
only — not wired to a real backend — but shows exactly the intended UX, styling, and
screen flow.
## Multi-institute architecture (build this in from day one)
This product is intended to eventually serve more than one institute, each with its own
document numbering format, comparison threshold, date rules, and clause wording. Rather
than forking the codebase per institute, the engine already separates:
- **Engine (shared, institute-agnostic)** — date math, working-day logic, amount-in-words,
table/PDF rendering, extraction, database, auth, billing. Identical for every institute.
- **Institute profile (swappable, one JSON file per institute)** — numbering format string,
comparison threshold, whether working-day rules apply, sanction-order clause text,
accounts-office heading, signatory roles, which documents are enabled at all.
`generate.py`'s `generate()` function takes a `profile_path` argument — pointing it at a
different institute's `profile.json` changes the numbering, thresholds, and wording with
**no code changes**. This has already been tested against a second, hypothetical
institute profile with a different numbering format, a different GST/threshold, and a
reduced document set, and it worked without touching the engine.
**What this means for scope:** a new institute onboarding is "create a new profile.json
(and, if their document wording differs beyond what the profile covers, new/adjusted
template functions) and point their account at it" — not a rebuild. When you plan the
database schema, each account/project should reference an `institute_id`, and the app
should load the matching profile at generation time.
## What needs to be built
1. **Auth & accounts** — one login per PI (email/password is fine). Recommend a managed
service (e.g. Supabase Auth) rather than building from scratch.
2. **Database** — suggested shape:
- `users` (PI account: name, email, department, PI initials)
- `subscriptions` (user_id, status: active / past_due / inactive, razorpay_subscription_id,
current_period_end)
- `projects` (user_id, project_code, financial_year, budget_head, PI name/designation)
- `documents` (project_id, type, generated_at, file_url, numbering fields)
- `expenditure_entries` (project_id, date, bill_no, vendor, items, amount, payment_date)
- `stock_register_entries` (project_id, date, item, qty, supply_order_no, page_ref)
3. **Data extraction** — read the scanned quotation/invoice/challan (clear printed scans)
and extract vendor name/address, item list, rates, dates, and document numbers. This
can be done with an LLM vision call (e.g. the Anthropic API) — a well-structured prompt
returning JSON in the exact shape of `sample_input.json` above.
4. **Document engine integration** — wire the extracted data + the project's stored
fields into `generate.py`'s logic, so "Generate documents" in the UI produces the
real files.
5. **Subscription & billing (Razorpay)**
- Razorpay Subscriptions API for recurring annual per-PI billing (UPI/net
banking/cards).
- Webhook listener updates `subscriptions.status` automatically on payment
success/failure/cancellation.
- Status logic: `active` → full access. `past_due` → 3–5 day grace period, access
continues with a renewal banner. `inactive` → blocked from generating new documents,
but existing projects/data remain visible and intact.
- Access check happens on every login and before any document generation — not just
at signup.
6. **Hosting** — app on Vercel or Render, database on Supabase (or similar managed
Postgres), on the client's own domain.
7. **Admin override** — a simple internal toggle to manually activate/deactivate any
account, as a safety net independent of the payment webhook.
## Business rules the engine already encodes (must be preserved)
- Supply order date: must be after the quotation date, on a working day.
- Inspection order date: must be after the invoice date or challan date, whichever is
later, on a working day.
- Sanction order date: the date the document set is generated.
- Document numbering: `Department/FinancialYear/ProjectCode/PIInitials`
(e.g. `Biophy/25-26/I-BT2213/PS`).
- If total order value exceeds ₹2,00,000, a 3-quotation comparative statement is
required and auto-generated, showing the lowest bidder.
## Suggested build order
1. Extraction step (get real vendor data flowing into the existing engine)
2. Database + auth (single user, no billing yet) — validate the full document flow
end-to-end
3. Multi-project support per account
4. Razorpay subscription + webhook + access gating
5. Polish UI against the provided prototype, deploy to domain
## Pricing model
Flat annual subscription per PI/investigator, unlimited projects.
## What this is
A SaaS tool for faculty (Principal Investigators) that auto-generates procurement
paperwork — cover letter, supply order, inspection note, sanction order, and (when
applicable) a 3-firm comparative statement — from three scanned source documents
(quotation, invoice, delivery challan). It also maintains a running expenditure sheet
and stock register per project. Access is subscription-gated (paid, per PI, annual).
## What's already built (attached in this package)
- **`rules.py` / `generate.py`** — a working Python engine that takes structured project
+ purchase data and produces the correctly dated, numbered, and formatted Word
document set. Tested against a real institute document set and matches it exactly.
- **`institutes/aiims/profile.json`** — institute-specific rules (numbering format,
comparison threshold, date rules, clause wording, signatory roles), kept separate
from the engine itself. See "Multi-institute architecture" below.
- **`sample_input.json`** — example input showing the full data shape the engine expects.
- **`generated_document_set.docx`** — sample output from the engine.
- **`sanctiondesk_prototype.html`** — a clickable front-end mockup (login, project
dashboard, upload flow, document list, expenditure sheet, stock register). Static/demo
only — not wired to a real backend — but shows exactly the intended UX, styling, and
screen flow.
## Multi-institute architecture (build this in from day one)
This product is intended to eventually serve more than one institute, each with its own
document numbering format, comparison threshold, date rules, and clause wording. Rather
than forking the codebase per institute, the engine already separates:
- **Engine (shared, institute-agnostic)** — date math, working-day logic, amount-in-words,
table/PDF rendering, extraction, database, auth, billing. Identical for every institute.
- **Institute profile (swappable, one JSON file per institute)** — numbering format string,
comparison threshold, whether working-day rules apply, sanction-order clause text,
accounts-office heading, signatory roles, which documents are enabled at all.
`generate.py`'s `generate()` function takes a `profile_path` argument — pointing it at a
different institute's `profile.json` changes the numbering, thresholds, and wording with
**no code changes**. This has already been tested against a second, hypothetical
institute profile with a different numbering format, a different GST/threshold, and a
reduced document set, and it worked without touching the engine.
**What this means for scope:** a new institute onboarding is "create a new profile.json
(and, if their document wording differs beyond what the profile covers, new/adjusted
template functions) and point their account at it" — not a rebuild. When you plan the
database schema, each account/project should reference an `institute_id`, and the app
should load the matching profile at generation time.
## What needs to be built
1. **Auth & accounts** — one login per PI (email/password is fine). Recommend a managed
service (e.g. Supabase Auth) rather than building from scratch.
2. **Database** — suggested shape:
- `users` (PI account: name, email, department, PI initials)
- `subscriptions` (user_id, status: active / past_due / inactive, razorpay_subscription_id,
current_period_end)
- `projects` (user_id, project_code, financial_year, budget_head, PI name/designation)
- `documents` (project_id, type, generated_at, file_url, numbering fields)
- `expenditure_entries` (project_id, date, bill_no, vendor, items, amount, payment_date)
- `stock_register_entries` (project_id, date, item, qty, supply_order_no, page_ref)
3. **Data extraction** — read the scanned quotation/invoice/challan (clear printed scans)
and extract vendor name/address, item list, rates, dates, and document numbers. This
can be done with an LLM vision call (e.g. the Anthropic API) — a well-structured prompt
returning JSON in the exact shape of `sample_input.json` above.
4. **Document engine integration** — wire the extracted data + the project's stored
fields into `generate.py`'s logic, so "Generate documents" in the UI produces the
real files.
5. **Subscription & billing (Razorpay)**
- Razorpay Subscriptions API for recurring annual per-PI billing (UPI/net
banking/cards).
- Webhook listener updates `subscriptions.status` automatically on payment
success/failure/cancellation.
- Status logic: `active` → full access. `past_due` → 3–5 day grace period, access
continues with a renewal banner. `inactive` → blocked from generating new documents,
but existing projects/data remain visible and intact.
- Access check happens on every login and before any document generation — not just
at signup.
6. **Hosting** — app on Vercel or Render, database on Supabase (or similar managed
Postgres), on the client's own domain.
7. **Admin override** — a simple internal toggle to manually activate/deactivate any
account, as a safety net independent of the payment webhook.
## Business rules the engine already encodes (must be preserved)
- Supply order date: must be after the quotation date, on a working day.
- Inspection order date: must be after the invoice date or challan date, whichever is
later, on a working day.
- Sanction order date: the date the document set is generated.
- Document numbering: `Department/FinancialYear/ProjectCode/PIInitials`
(e.g. `Biophy/25-26/I-BT2213/PS`).
- If total order value exceeds ₹2,00,000, a 3-quotation comparative statement is
required and auto-generated, showing the lowest bidder.
## Suggested build order
1. Extraction step (get real vendor data flowing into the existing engine)
2. Database + auth (single user, no billing yet) — validate the full document flow
end-to-end
3. Multi-project support per account
4. Razorpay subscription + webhook + access gating
5. Polish UI against the provided prototype, deploy to domain
## Pricing model
Flat annual subscription per PI/investigator, unlimited projects.