Dealer_Onboarding_Backend/back.md

1271 lines
29 KiB
Markdown

# Royal Enfield Dealership Onboarding System - Backend Documentation
## 📋 Overview
This is a comprehensive Node.js + Express backend for the Royal Enfield Dealership Onboarding System. It handles a multi-stage workflow with 13 different user roles, managing dealer applications, resignations, constitutional changes, relocations, and full F&F settlement processes.
## 🏗️ Architecture
**Tech Stack:**
- **Runtime:** Node.js (v18+)
- **Framework:** Express.js
- **Database:** PostgreSQL (with Sequelize ORM)
- **Authentication:** JWT (JSON Web Tokens)
- **File Storage:** Multer + Local/Cloud storage
- **Email:** Nodemailer
- **Validation:** express-validator
- **Security:** bcryptjs, helmet, cors
## 📁 Project Structure
```
backend/
├── back.md # This comprehensive documentation file
├── package.json # Dependencies and scripts
├── .env.example # Environment variables template
├── server.js # Main entry point
├── config/
│ ├── database.js # Database configuration
│ ├── email.js # Email service configuration
│ └── constants.js # System constants (roles, statuses, stages)
├── models/
│ ├── index.js # Sequelize model loader
│ ├── User.js # User model
│ ├── Application.js # Dealer application model
│ ├── Resignation.js # Resignation request model
│ ├── ConstitutionalChange.js # Constitutional change model
│ ├── RelocationRequest.js # Relocation request model
│ ├── Outlet.js # Dealership/Studio outlet model
│ ├── Worknote.js # Discussion worknotes model
│ ├── Document.js # Document uploads model
│ ├── AuditLog.js # Audit trail model
│ ├── FinancePayment.js # Finance payment tracking
│ ├── FnF.js # Full & Final settlement
│ ├── Region.js # Regional hierarchy model
│ └── Zone.js # Zone model
├── controllers/
│ ├── authController.js # Login, logout, token refresh
│ ├── userController.js # User management
│ ├── applicationController.js # Dealer applications
│ ├── resignationController.js # Resignation workflow
│ ├── constitutionalController.js # Constitutional changes
│ ├── relocationController.js # Relocation requests
│ ├── outletController.js # Outlet management
│ ├── worknoteController.js # Discussion platform
│ ├── financeController.js # Finance operations
│ ├── masterController.js # Master configuration
│ └── dashboardController.js # Dashboard statistics
├── routes/
│ ├── auth.js # Authentication routes
│ ├── users.js # User routes
│ ├── applications.js # Application routes
│ ├── resignations.js # Resignation routes
│ ├── constitutional.js # Constitutional change routes
│ ├── relocations.js # Relocation routes
│ ├── outlets.js # Outlet routes
│ ├── worknotes.js # Worknote routes
│ ├── finance.js # Finance routes
│ ├── master.js # Master configuration routes
│ └── dashboard.js # Dashboard routes
├── middleware/
│ ├── auth.js # JWT verification middleware
│ ├── roleCheck.js # Role-based access control
│ ├── upload.js # File upload middleware
│ ├── validation.js # Input validation
│ └── errorHandler.js # Global error handler
├── utils/
│ ├── emailTemplates.js # Email HTML templates
│ ├── emailService.js # Email sending utilities
│ ├── logger.js # Winston logger
│ └── helpers.js # Helper functions
└── migrations/ # Database migrations
└── initial-setup.js # Initial database schema
```
## 👥 User Roles & Permissions
The system supports 13 distinct roles with hierarchical permissions:
1. **DD (Dealer Development)** - Creates applications, initial review
2. **DD-ZM (DD Zone Manager)** - Zone-level approvals
3. **RBM (Regional Business Manager)** - Regional approvals
4. **ZBH (Zonal Business Head)** - Zonal head approvals
5. **DD Lead** - Organization-wide DD leadership (singular position)
6. **DD Head** - Head of DD department (singular position)
7. **NBH (National Business Head)** - National head (singular position)
8. **DD Admin** - Administrative operations
9. **Legal Admin** - Legal clearance and document verification
10. **Super Admin** - Full system access
11. **DD AM (Area Manager)** - Area-level management
12. **Finance** - Payment tracking and financial approvals
13. **Dealer** - Dealer portal access (resignation, relocation, constitutional changes)
## 🗄️ Database Schema
### Key Tables:
#### 1. **users**
```sql
- id (UUID, PK)
- email (STRING, UNIQUE)
- password (STRING, hashed)
- role (ENUM: DD, DD-ZM, RBM, ZBH, DD Lead, DD Head, NBH, DD Admin, Legal Admin, Super Admin, DD AM, Finance, Dealer)
- name (STRING)
- region (STRING) - East, West, North, South, Central
- zone (STRING)
- status (ENUM: active, inactive)
- createdAt, updatedAt
```
#### 2. **applications**
```sql
- id (UUID, PK)
- applicationId (STRING, UNIQUE) - e.g., APP-2026-001
- applicantName (STRING)
- email (STRING)
- phone (STRING)
- businessType (ENUM: Dealership, Studio)
- proposedLocation (TEXT)
- city, state, pincode
- currentStage (ENUM: DD, DD-ZM, RBM, ZBH, DD Lead, DD Head, NBH, Legal, Finance, Approved, Rejected)
- status (ENUM: Pending, In Review, Approved, Rejected)
- ranking (INTEGER) - DD ranking system
- submittedBy (UUID, FK -> users)
- submittedAt (DATE)
- progressPercentage (INTEGER)
- documents (JSON) - Array of document references
- createdAt, updatedAt
```
#### 3. **outlets**
```sql
- id (UUID, PK)
- code (STRING, UNIQUE) - e.g., DL-MH-001, ST-MH-002
- name (STRING)
- type (ENUM: Dealership, Studio)
- address (TEXT)
- city (STRING)
- state (STRING)
- pincode (STRING)
- latitude (DECIMAL)
- longitude (DECIMAL)
- status (ENUM: Active, Pending Resignation, Closed)
- establishedDate (DATE)
- dealerId (UUID, FK -> users)
- region (STRING)
- zone (STRING)
- createdAt, updatedAt
```
#### 4. **resignations**
```sql
- id (UUID, PK)
- resignationId (STRING, UNIQUE) - e.g., RES-001
- outletId (UUID, FK -> outlets)
- dealerId (UUID, FK -> users)
- resignationType (ENUM: Voluntary, Retirement, Health Issues, Business Closure, Other)
- lastOperationalDateSales (DATE)
- lastOperationalDateServices (DATE)
- reason (TEXT)
- additionalInfo (TEXT)
- currentStage (ENUM: ASM, RBM, ZBH, NBH, DD Admin, Legal, Finance, Completed, Rejected)
- status (STRING)
- progressPercentage (INTEGER)
- submittedOn (DATE)
- documents (JSON)
- createdAt, updatedAt
```
#### 5. **constitutional_changes**
```sql
- id (UUID, PK)
- requestId (STRING, UNIQUE) - e.g., CC-001
- outletId (UUID, FK -> outlets)
- dealerId (UUID, FK -> users)
- changeType (ENUM: Ownership Transfer, Partnership Change, LLP Conversion, Company Formation, Director Change)
- currentStructure (STRING)
- proposedStructure (STRING)
- reason (TEXT)
- effectiveDate (DATE)
- currentStage (ENUM: DD Admin Review, Legal Review, NBH Approval, Finance Clearance, Completed, Rejected)
- status (STRING)
- progressPercentage (INTEGER)
- submittedOn (DATE)
- documents (JSON)
- createdAt, updatedAt
```
#### 6. **relocation_requests**
```sql
- id (UUID, PK)
- requestId (STRING, UNIQUE) - e.g., REL-001
- outletId (UUID, FK -> outlets)
- dealerId (UUID, FK -> users)
- relocationType (ENUM: Within City, Intercity, Interstate)
- currentAddress (TEXT)
- currentLatitude (DECIMAL)
- currentLongitude (DECIMAL)
- proposedAddress (TEXT)
- proposedLatitude (DECIMAL)
- proposedLongitude (DECIMAL)
- proposedCity (STRING)
- proposedState (STRING)
- proposedPincode (STRING)
- distance (DECIMAL) - in kilometers
- reason (TEXT)
- effectiveDate (DATE)
- currentStage (ENUM: DD Admin Review, RBM Review, NBH Approval, Legal Clearance, Completed, Rejected)
- status (STRING)
- progressPercentage (INTEGER)
- submittedOn (DATE)
- documents (JSON)
- createdAt, updatedAt
```
#### 7. **worknotes**
```sql
- id (UUID, PK)
- requestId (UUID) - Generic reference to any request
- requestType (ENUM: application, resignation, constitutional, relocation)
- userId (UUID, FK -> users)
- userName (STRING)
- userRole (STRING)
- message (TEXT)
- attachments (JSON)
- timestamp (DATE)
- createdAt, updatedAt
```
#### 8. **documents**
```sql
- id (UUID, PK)
- filename (STRING)
- originalName (STRING)
- mimeType (STRING)
- size (INTEGER)
- path (STRING)
- uploadedBy (UUID, FK -> users)
- relatedTo (STRING) - application/resignation/etc
- relatedId (UUID)
- documentType (STRING) - GST, PAN, Aadhaar, etc
- uploadedAt (DATE)
- createdAt, updatedAt
```
#### 9. **audit_logs**
```sql
- id (UUID, PK)
- userId (UUID, FK -> users)
- userName (STRING)
- userRole (STRING)
- action (STRING) - CREATED, UPDATED, APPROVED, REJECTED, etc
- entityType (STRING) - application, resignation, etc
- entityId (UUID)
- changes (JSON) - Before/after values
- ipAddress (STRING)
- timestamp (DATE)
- createdAt, updatedAt
```
#### 10. **finance_payments**
```sql
- id (UUID, PK)
- applicationId (UUID, FK -> applications)
- outletId (UUID, FK -> outlets)
- dealerId (UUID, FK -> users)
- paymentType (ENUM: Security Deposit, License Fee, Setup Fee, Other)
- amount (DECIMAL)
- dueDate (DATE)
- paidDate (DATE)
- status (ENUM: Pending, Paid, Overdue, Waived)
- transactionId (STRING)
- paymentMode (STRING)
- remarks (TEXT)
- createdAt, updatedAt
```
#### 11. **fnf_settlements**
```sql
- id (UUID, PK)
- fnfId (STRING, UNIQUE) - e.g., FNF-001
- resignationId (UUID, FK -> resignations)
- outletId (UUID, FK -> outlets)
- dealerId (UUID, FK -> users)
- totalDues (DECIMAL)
- securityDepositRefund (DECIMAL)
- otherCharges (DECIMAL)
- netSettlement (DECIMAL)
- status (ENUM: Initiated, DD Clearance, Legal Clearance, Finance Approval, Completed)
- settledDate (DATE)
- progressPercentage (INTEGER)
- createdAt, updatedAt
```
#### 12. **regions**
```sql
- id (UUID, PK)
- name (STRING, UNIQUE) - East, West, North, South, Central
- code (STRING)
- headName (STRING)
- headEmail (STRING)
- isActive (BOOLEAN)
- createdAt, updatedAt
```
#### 13. **zones**
```sql
- id (UUID, PK)
- name (STRING)
- code (STRING)
- regionId (UUID, FK -> regions)
- managerName (STRING)
- managerEmail (STRING)
- states (JSON) - Array of states covered
- isActive (BOOLEAN)
- createdAt, updatedAt
```
## 🔌 API Endpoints
### Authentication
#### `POST /api/auth/login`
```json
Request:
{
"email": "user@example.com",
"password": "password123"
}
Response:
{
"success": true,
"token": "jwt_token_here",
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "John Doe",
"role": "DD"
}
}
```
#### `POST /api/auth/logout`
```json
Headers: { Authorization: "Bearer jwt_token" }
Response:
{
"success": true,
"message": "Logged out successfully"
}
```
#### `GET /api/auth/me`
```json
Headers: { Authorization: "Bearer jwt_token" }
Response:
{
"success": true,
"user": {
"id": "uuid",
"email": "user@example.com",
"name": "John Doe",
"role": "DD",
"region": "West",
"zone": "Mumbai"
}
}
```
### Outlets
#### `GET /api/outlets/my-outlets`
Get all outlets for logged-in dealer
```json
Headers: { Authorization: "Bearer dealer_token" }
Response:
{
"success": true,
"outlets": [
{
"id": "uuid",
"code": "DL-MH-001",
"name": "Royal Enfield Mumbai",
"type": "Dealership",
"address": "Bandra West, Mumbai",
"status": "Active",
"hasActiveResignation": false
}
]
}
```
### Resignations
#### `POST /api/resignations/create`
Create resignation request (Dealer only)
```json
Headers: { Authorization: "Bearer dealer_token" }
Request:
{
"outletId": "uuid",
"resignationType": "Voluntary",
"lastOperationalDateSales": "2026-02-28",
"lastOperationalDateServices": "2026-02-28",
"reason": "Personal health issues",
"additionalInfo": "Optional details"
}
Response:
{
"success": true,
"resignationId": "RES-001",
"message": "Resignation request submitted successfully"
}
```
#### `GET /api/resignations/list`
Get resignations (role-based filtering)
```json
Headers: { Authorization: "Bearer jwt_token" }
Response:
{
"success": true,
"resignations": [
{
"resignationId": "RES-001",
"outlet": { "code": "DL-MH-001", "name": "..." },
"resignationType": "Voluntary",
"currentStage": "ASM Review",
"status": "Pending",
"progressPercentage": 15
}
]
}
```
#### `GET /api/resignations/:id`
Get resignation details
```json
Headers: { Authorization: "Bearer jwt_token" }
Response:
{
"success": true,
"resignation": {
"resignationId": "RES-001",
"outlet": {...},
"resignationType": "Voluntary",
"reason": "...",
"timeline": [...],
"worknotes": [...]
}
}
```
#### `POST /api/resignations/:id/approve`
Approve resignation at current stage
```json
Headers: { Authorization: "Bearer jwt_token" }
Request:
{
"remarks": "Approved by ASM"
}
Response:
{
"success": true,
"message": "Resignation approved and moved to next stage"
}
```
#### `POST /api/resignations/:id/reject`
Reject resignation
```json
Headers: { Authorization: "Bearer jwt_token" }
Request:
{
"reason": "Incomplete documentation"
}
Response:
{
"success": true,
"message": "Resignation rejected"
}
```
### Constitutional Changes
#### `POST /api/constitutional/create`
Create constitutional change request (Dealer only)
```json
Headers: { Authorization: "Bearer dealer_token" }
Request:
{
"outletId": "uuid",
"changeType": "Partnership Change",
"currentStructure": "Sole Proprietorship",
"proposedStructure": "Partnership Firm",
"reason": "Business expansion",
"effectiveDate": "2026-03-01"
}
Response:
{
"success": true,
"requestId": "CC-001"
}
```
#### `GET /api/constitutional/list`
Get constitutional change requests
```json
Headers: { Authorization: "Bearer jwt_token" }
Response:
{
"success": true,
"requests": [...]
}
```
### Relocation Requests
#### `POST /api/relocations/create`
Create relocation request (Dealer only)
```json
Headers: { Authorization: "Bearer dealer_token" }
Request:
{
"outletId": "uuid",
"relocationType": "Within City",
"proposedAddress": "New location address",
"proposedLatitude": 19.0760,
"proposedLongitude": 72.8777,
"proposedCity": "Mumbai",
"proposedState": "Maharashtra",
"proposedPincode": "400050",
"reason": "Better footfall location",
"effectiveDate": "2026-04-01"
}
Response:
{
"success": true,
"requestId": "REL-001"
}
```
#### `GET /api/relocations/calculate-distance`
Calculate distance between two locations
```json
Headers: { Authorization: "Bearer jwt_token" }
Query: ?fromLat=19.0760&fromLng=72.8777&toLat=19.1196&toLng=72.9046
Response:
{
"success": true,
"distance": 5.2,
"unit": "km"
}
```
### Worknotes
#### `POST /api/worknotes/create`
Add worknote to any request
```json
Headers: { Authorization: "Bearer jwt_token" }
Request:
{
"requestId": "uuid",
"requestType": "resignation",
"message": "Please provide updated documents"
}
Response:
{
"success": true,
"worknote": {...}
}
```
#### `GET /api/worknotes/:requestId/:requestType`
Get all worknotes for a request
```json
Headers: { Authorization: "Bearer jwt_token" }
Response:
{
"success": true,
"worknotes": [
{
"id": "uuid",
"userName": "John Doe",
"userRole": "DD Admin",
"message": "...",
"timestamp": "2026-01-13T10:30:00Z"
}
]
}
```
### Applications
#### `POST /api/applications/create`
Create new dealer application (public endpoint)
```json
Request:
{
"applicantName": "Rajesh Kumar",
"email": "rajesh@example.com",
"phone": "+91-9876543210",
"businessType": "Dealership",
"proposedLocation": "Full address",
"city": "Mumbai",
"state": "Maharashtra",
"pincode": "400001"
}
Response:
{
"success": true,
"applicationId": "APP-2026-001"
}
```
#### `GET /api/applications/list`
Get applications (role-based filtering)
```json
Headers: { Authorization: "Bearer jwt_token" }
Query: ?status=Pending&region=West&page=1&limit=10
Response:
{
"success": true,
"applications": [...],
"total": 50,
"page": 1,
"pages": 5
}
```
#### `POST /api/applications/:id/assign-ranking`
DD assigns ranking (1-5)
```json
Headers: { Authorization: "Bearer dd_token" }
Request:
{
"ranking": 4
}
Response:
{
"success": true,
"message": "Ranking assigned"
}
```
#### `POST /api/applications/:id/move-stage`
Move application to next stage
```json
Headers: { Authorization: "Bearer jwt_token" }
Request:
{
"action": "approve", // or "reject"
"remarks": "All documents verified"
}
Response:
{
"success": true,
"nextStage": "DD-ZM"
}
```
### Finance
#### `GET /api/finance/onboarding-payments`
Get all pending onboarding payments
```json
Headers: { Authorization: "Bearer finance_token" }
Response:
{
"success": true,
"payments": [...]
}
```
#### `POST /api/finance/payment/:id/mark-paid`
Mark payment as received
```json
Headers: { Authorization: "Bearer finance_token" }
Request:
{
"transactionId": "TXN123456",
"paidDate": "2026-01-13",
"paymentMode": "NEFT"
}
Response:
{
"success": true,
"message": "Payment marked as paid"
}
```
#### `GET /api/finance/fnf-list`
Get F&F settlement requests
```json
Headers: { Authorization: "Bearer finance_token" }
Response:
{
"success": true,
"fnfRequests": [...]
}
```
### Dashboard
#### `GET /api/dashboard/stats`
Get dashboard statistics (role-based)
```json
Headers: { Authorization: "Bearer jwt_token" }
Response:
{
"success": true,
"stats": {
"totalApplications": 150,
"pendingApplications": 45,
"approvedApplications": 95,
"rejectedApplications": 10,
"pendingResignations": 5,
"pendingRelocations": 3
}
}
```
### Master Configuration
#### `GET /api/master/regions`
Get all regions
```json
Headers: { Authorization: "Bearer jwt_token" }
Response:
{
"success": true,
"regions": [
{
"id": "uuid",
"name": "East",
"code": "EAST",
"zones": [...]
}
]
}
```
#### `POST /api/master/regions/create`
Create region (Super Admin only)
```json
Headers: { Authorization: "Bearer admin_token" }
Request:
{
"name": "East",
"code": "EAST",
"headName": "Amit Kumar",
"headEmail": "amit@example.com"
}
Response:
{
"success": true,
"region": {...}
}
```
### File Upload
#### `POST /api/upload/document`
Upload document
```json
Headers: {
Authorization: "Bearer jwt_token",
Content-Type: "multipart/form-data"
}
FormData:
- file: (binary)
- relatedTo: "resignation"
- relatedId: "uuid"
- documentType: "GST Certificate"
Response:
{
"success": true,
"document": {
"id": "uuid",
"filename": "unique-filename.pdf",
"originalName": "gst-certificate.pdf",
"url": "/uploads/documents/unique-filename.pdf"
}
}
```
## 🔐 Authentication & Authorization
### JWT Authentication Flow:
1. **Login:** User sends credentials → Server validates → Returns JWT token
2. **Protected Routes:** Client sends token in Authorization header
3. **Token Verification:** Middleware validates token before processing request
4. **Token Expiry:** 24 hours (configurable)
### Role-Based Access Control (RBAC):
Middleware checks user role against route permissions:
```javascript
// Example: Only DD Lead can access opportunity requests
router.get('/opportunity-requests',
auth,
roleCheck(['DD Lead']),
getOpportunityRequests
);
// Example: Multiple roles can approve resignations
router.post('/resignations/:id/approve',
auth,
roleCheck(['DD Admin', 'RBM', 'ZBH', 'NBH', 'Legal Admin']),
approveResignation
);
```
### Permission Matrix:
| Feature | DD | DD-ZM | RBM | ZBH | DD Lead | DD Head | NBH | DD Admin | Legal | Finance | Dealer |
|---------|----|----|-----|-----|---------|---------|-----|----------|-------|---------|--------|
| Create Application | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| View All Applications | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Approve Application Stage | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | ❌ | ✅ | ✅ | ❌ |
| Create Resignation | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ |
| Approve Resignation | ❌ | ❌ | ✅ | ✅ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ❌ |
| Constitutional Change | ❌ | ❌ | ❌ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Relocation Request | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ | ✅ | ✅ | ✅ | ❌ | ✅ |
| Master Configuration | ❌ | ❌ | ❌ | ❌ | ✅ | ❌ | ❌ | ✅ | ❌ | ❌ | ❌ |
## 📧 Email Notifications
### Email Triggers:
1. **Application Submitted** → Notify assigned DD
2. **Application Approved/Rejected** → Notify applicant
3. **Stage Changed** → Notify next approver
4. **Deadline Approaching** → Reminder email (3 days, 1 day before)
5. **Resignation Submitted** → Notify DD Admin
6. **Constitutional Change** → Notify Legal team
7. **Relocation Request** → Notify RBM
8. **Payment Due** → Notify dealer
9. **F&F Initiated** → Notify Finance team
### Email Templates:
Located in `utils/emailTemplates.js`:
- Application confirmation
- Approval notification
- Rejection notification
- Stage progression
- Deadline reminder
- Password reset
## 🚀 Setup Instructions
### 1. Prerequisites
Install the following on your system:
- Node.js v18+ (https://nodejs.org)
- PostgreSQL 14+ (https://www.postgresql.org)
- Git (optional)
### 2. Install Dependencies
```bash
cd backend
npm install
```
### 3. Database Setup
Create PostgreSQL database:
```sql
CREATE DATABASE royal_enfield_onboarding;
CREATE USER re_admin WITH PASSWORD 'your_password';
GRANT ALL PRIVILEGES ON DATABASE royal_enfield_onboarding TO re_admin;
```
### 4. Environment Configuration
Copy `.env.example` to `.env` and configure:
```env
# Server
NODE_ENV=development
PORT=5000
# Database
DB_HOST=localhost
DB_PORT=5432
DB_NAME=royal_enfield_onboarding
DB_USER=re_admin
DB_PASSWORD=your_password
# JWT
JWT_SECRET=your_super_secret_jwt_key_here_make_it_long_and_random
JWT_EXPIRES_IN=24h
# Email (Gmail example)
EMAIL_HOST=smtp.gmail.com
EMAIL_PORT=587
EMAIL_USER=your-email@gmail.com
EMAIL_PASSWORD=your-app-specific-password
EMAIL_FROM=Royal Enfield <noreply@royalenfield.com>
# File Upload
UPLOAD_PATH=./uploads
MAX_FILE_SIZE=10485760
# Frontend URL (for CORS)
FRONTEND_URL=http://localhost:5173
# Admin Default Password (for initial setup)
ADMIN_DEFAULT_PASSWORD=Admin@123
```
### 5. Run Migrations
```bash
npm run migrate
```
This creates all tables and seeds initial data:
- Super Admin user
- 5 Regions (East, West, North, South, Central)
- Sample zones
- Sample users for each role
### 6. Start Server
**Development:**
```bash
npm run dev
```
**Production:**
```bash
npm start
```
Server runs on: `http://localhost:5000`
### 7. Test API
Use Postman/Thunder Client:
```bash
# Login as Super Admin
POST http://localhost:5000/api/auth/login
Body: {
"email": "admin@royalenfield.com",
"password": "Admin@123"
}
# Get dashboard stats
GET http://localhost:5000/api/dashboard/stats
Headers: Authorization: Bearer <token_from_login>
```
## 🔗 Frontend Integration
### Update Frontend API Calls
In your frontend, update API base URL:
**Create `/src/lib/api.ts`:**
```typescript
const API_BASE_URL = process.env.NODE_ENV === 'production'
? 'https://your-backend-domain.com/api'
: 'http://localhost:5000/api';
export const api = {
async login(email: string, password: string) {
const response = await fetch(`${API_BASE_URL}/auth/login`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email, password })
});
return response.json();
},
async getMyOutlets(token: string) {
const response = await fetch(`${API_BASE_URL}/outlets/my-outlets`, {
headers: { 'Authorization': `Bearer ${token}` }
});
return response.json();
},
async createResignation(token: string, data: any) {
const response = await fetch(`${API_BASE_URL}/resignations/create`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${token}`
},
body: JSON.stringify(data)
});
return response.json();
}
};
```
### Replace Mock Data
**Before (Mock):**
```typescript
const mockOutlets = [...]; // Hardcoded data
```
**After (Real API):**
```typescript
useEffect(() => {
const fetchOutlets = async () => {
const token = localStorage.getItem('token');
const result = await api.getMyOutlets(token);
setOutlets(result.outlets);
};
fetchOutlets();
}, []);
```
## 📊 Workflow State Machines
### Application Workflow:
```
Initial → DD Review → DD-ZM Review → RBM Review → ZBH Review
→ DD Lead Review → DD Head Review → NBH Approval → Legal Clearance
→ Finance Payment → Approved ✅
```
### Resignation Workflow:
```
Submitted → ASM Review → RBM Review → ZBH Review → NBH Approval
→ DD Admin Clearance → Legal Clearance → F&F Initiation
→ Finance Settlement → Completed ✅
```
### Constitutional Change Workflow:
```
Submitted → DD Admin Review → Legal Verification → NBH Approval
→ Finance Clearance → Completed ✅
```
### Relocation Workflow:
```
Submitted → DD Admin Review → RBM Assessment → NBH Approval
→ Legal Clearance → Completed ✅
```
## 🛡️ Security Features
1. **Password Hashing:** bcryptjs with salt rounds
2. **JWT Tokens:** Secure token-based authentication
3. **CORS:** Configured for frontend domain only
4. **Helmet:** Security headers
5. **Rate Limiting:** Prevent brute force attacks
6. **Input Validation:** express-validator on all inputs
7. **SQL Injection Prevention:** Sequelize ORM parameterized queries
8. **File Upload Validation:** Type and size restrictions
9. **Audit Logging:** All actions logged with user/timestamp
## 📝 Logging
Winston logger with multiple transports:
- **Console:** Development logging
- **File:** `logs/error.log` - Error logs
- **File:** `logs/combined.log` - All logs
## 🧪 Testing
```bash
# Run tests
npm test
# Run with coverage
npm run test:coverage
```
## 🚢 Deployment
### Option 1: Railway (Recommended)
1. Create account on railway.app
2. Connect GitHub repository
3. Add PostgreSQL plugin
4. Set environment variables
5. Deploy automatically
### Option 2: Render
1. Create account on render.com
2. Create Web Service
3. Connect repository
4. Add PostgreSQL database
5. Set environment variables
6. Deploy
### Option 3: AWS/DigitalOcean
1. Set up EC2/Droplet
2. Install Node.js, PostgreSQL
3. Clone repository
4. Configure environment
5. Use PM2 for process management
6. Set up Nginx reverse proxy
### Environment Variables for Production:
```env
NODE_ENV=production
DB_HOST=<production-db-host>
DB_NAME=<production-db-name>
DB_USER=<production-db-user>
DB_PASSWORD=<production-db-password>
JWT_SECRET=<strong-random-secret>
EMAIL_HOST=<smtp-host>
EMAIL_USER=<email>
EMAIL_PASSWORD=<password>
FRONTEND_URL=https://your-frontend-domain.com
```
## 📦 Dependencies
**Core:**
- express: Web framework
- sequelize: ORM
- pg, pg-hstore: PostgreSQL driver
- jsonwebtoken: JWT authentication
- bcryptjs: Password hashing
**Middleware:**
- cors: Cross-origin resource sharing
- helmet: Security headers
- express-validator: Input validation
- multer: File uploads
**Utilities:**
- nodemailer: Email sending
- winston: Logging
- dotenv: Environment variables
- uuid: Unique IDs
**Dev Dependencies:**
- nodemon: Auto-restart on changes
- jest: Testing framework
## 🔧 Maintenance
### Database Backup:
```bash
pg_dump -U re_admin royal_enfield_onboarding > backup.sql
```
### Restore Database:
```bash
psql -U re_admin royal_enfield_onboarding < backup.sql
```
### Clear Logs:
```bash
npm run clear-logs
```
## 📞 Support & Troubleshooting
### Common Issues:
**1. Database Connection Error:**
- Check PostgreSQL is running: `sudo service postgresql status`
- Verify credentials in `.env`
- Check database exists: `psql -l`
**2. Port Already in Use:**
- Change PORT in `.env`
- Kill process: `lsof -ti:5000 | xargs kill`
**3. JWT Token Invalid:**
- Check JWT_SECRET is same across restarts
- Verify token expiry time
- Clear old tokens from frontend
**4. File Upload Failing:**
- Check UPLOAD_PATH directory exists and is writable
- Verify MAX_FILE_SIZE setting
- Check disk space
**5. Email Not Sending:**
- Verify SMTP credentials
- Check firewall/port 587 access
- Enable "Less secure apps" for Gmail or use App Password
## 🎯 Next Steps for AI Assistant (Cursor/Windsurf/etc)
When you provide this backend to your AI IDE, it will understand:
1. ✅ Complete architecture and file structure
2. ✅ Database schema and relationships
3. ✅ All API endpoints and their contracts
4. ✅ Authentication and authorization flow
5. ✅ Environment setup requirements
6. ✅ Deployment options
7. ✅ Integration points with frontend
**The AI can then:**
- Help you set up the database
- Debug any issues
- Add new features
- Optimize queries
- Handle deployment
- Write tests
- Generate documentation
## 📄 License
Proprietary - Royal Enfield Dealership Onboarding System
---
**Created:** January 2026
**Version:** 1.0.0
**Last Updated:** January 13, 2026
For questions or support, refer to this documentation first, then consult with your development team.