AI-powered loan origination, risk assessment, and application management system for Non-Banking Financial Companies.
This system digitises the complete loan lifecycle β from lead capture to automated risk scoring. It replaces manual Excel-based workflows with a structured database, multi-step digital application forms, and a machine learning model that predicts applicant creditworthiness.
- Lead Capture β Staff or customers create leads via a digital form
- Application Submission β Multi-step wizard collects personal, financial, and KYC data
- Document Processing β PDFs are uploaded and text is extracted automatically via OCR
- AI Risk Assessment β A Random Forest classifier scores each application (High Risk / Low Risk)
- Admin Dashboard β NBFC staff review applications in a table or pipeline view, sorted by risk score
- Status Management β Applications move through the pipeline: New β Under Review β Approved β Rejected β Disbursed
| Component | Technology |
|---|---|
| Frontend | Next.js 16, React 19, Tailwind CSS 4 |
| Backend | Python, Flask, Flask-CORS |
| Database | Supabase (PostgreSQL) |
| Auth | Supabase Auth (email/password) |
| AI/ML | Scikit-learn (Random Forest) |
| OCR | pdfplumber (PDF text extraction) |
| Icons | Lucide React |
NBFCs/
βββ backend/
β βββ app.py # Flask API β all endpoints
β βββ train_model.py # ML training script
β βββ risk_model.pkl # Trained Random Forest model
β βββ migration.sql # SQL migration for Supabase
β βββ requirements.txt # Python dependencies
β βββ .env # Environment variables (not committed)
β
βββ frontend/
β βββ src/
β β βββ app/
β β β βββ page.tsx # Dashboard home with stats
β β β βββ layout.tsx # Root layout with navigation
β β β βββ login/page.tsx # Supabase Auth login
β β β βββ leads/
β β β β βββ page.tsx # Leads list with search
β β β β βββ new/page.tsx # Create lead form
β β β β βββ [lead_id]/page.tsx # Lead detail + applicants
β β β βββ applications/
β β β βββ page.tsx # Admin dashboard (table + pipeline)
β β β βββ new/page.tsx # Multi-step application wizard
β β β βββ [application_id]/page.tsx # Application detail + risk gauge
β β βββ components/
β β β βββ AuthNav.tsx # Sign in / sign out nav
β β β βββ RequireAuth.tsx # Auth guard wrapper
β β βββ lib/
β β βββ api.ts # API client + TypeScript types
β β βββ supabaseClient.ts # Supabase client init
β βββ package.json
β βββ .env.local # Environment variables (not committed)
β
βββ README.md
- Python 3.10+
- Node.js 18+
- A Supabase project
Run the following SQL in Supabase Dashboard β SQL Editor:
-- Add risk assessment columns to application table
ALTER TABLE application ADD COLUMN IF NOT EXISTS risk_score float;
ALTER TABLE application ADD COLUMN IF NOT EXISTS risk_label text DEFAULT 'pending';
ALTER TABLE application ADD COLUMN IF NOT EXISTS app_status text DEFAULT 'New';
-- Document table for uploaded files
CREATE TABLE IF NOT EXISTS document (
document_id serial PRIMARY KEY,
application_id int REFERENCES application(application_id),
applicant_id int REFERENCES applicant(applicant_id),
doc_type text NOT NULL,
file_url text NOT NULL,
ocr_text text,
ocr_verified boolean DEFAULT false,
uploaded_at timestamptz DEFAULT now()
);cd backend
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
pip install -r requirements.txtCreate backend/.env:
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_ROLE_KEY=your-service-role-key
PORT=5001
Train the ML model (one-time):
python train_model.pyStart the server:
python app.pyBackend runs at http://localhost:5001
cd frontend
npm installCreate frontend/.env.local:
NEXT_PUBLIC_API_BASE_URL=http://localhost:5001
NEXT_PUBLIC_SUPABASE_URL=https://your-project.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=your-anon-key
Start the dev server:
npm run devFrontend runs at http://localhost:3000
| Method | Path | Description |
|---|---|---|
| GET | /api/health |
Health check |
| Method | Path | Description |
|---|---|---|
| GET | /api/leads |
List leads (optional ?q= search) |
| POST | /api/leads |
Create a lead |
| GET | /api/leads/:id |
Get lead by ID |
| DELETE | /api/leads/:id |
Delete a lead |
| GET | /api/leads/:id/applicants |
List applicants for a lead |
| GET | /api/applicants |
List all applicants |
| POST | /api/applicants |
Create an applicant |
| GET | /api/applications |
List all applications |
| POST | /api/applications |
Create an application |
| GET | /api/applications/:id |
Get application by ID |
| PATCH | /api/applications/:id/status |
Update application status |
| POST | /api/applications/:id/assess |
Run AI risk assessment on application |
| POST | /api/risk-assess |
Standalone risk prediction |
| POST | /api/documents/upload |
Upload PDF + OCR extraction |
| GET | /api/documents/:application_id |
List documents for an application |
| GET | /api/stats |
Dashboard summary statistics |
The risk engine uses a Random Forest Classifier trained on synthetic NBFC loan data.
Features used:
monthly_incomecibil_scoreemployment_type(encoded: salaried, self_employed, business, freelancer, retired)loan_amountloan_tenureagedebt_to_income(derived)emi_to_income(derived)
Output:
risk_scoreβ probability of Low Risk (0.0 to 1.0)risk_labelβ "Low Risk" or "High Risk"
Model performance: 87% accuracy on held-out test set.
The model can be retrained on real historical data by modifying train_model.py and running it again.
- Create, search, view, and delete leads
- Linked applicant information
- 4-step wizard: Personal Info β Financial Details β Documents β Review
- Client-side validation (age >= 18, CIBIL >= 300, etc.)
- Live AI risk preview before submission
- PDF upload with automatic text extraction
- OCR verification status badges
- Table view β all applications sorted by risk score
- Pipeline view β Kanban-style columns by status
- Inline status updates and AI assessment triggers
- SVG risk score gauge
- Loan details grid
- Document list with extracted text preview
| Variable | Description |
|---|---|
SUPABASE_URL |
Your Supabase project URL |
SUPABASE_SERVICE_ROLE_KEY |
Service role key from Supabase |
PORT |
Server port (default: 5001) |
| Variable | Description |
|---|---|
NEXT_PUBLIC_API_BASE_URL |
Flask backend URL (e.g. http://localhost:5001) |
NEXT_PUBLIC_SUPABASE_URL |
Your Supabase project URL |
NEXT_PUBLIC_SUPABASE_ANON_KEY |
Anon/public key from Supabase |