PHP 8.2.30
Preview: README.md Size: 37.08 KB
/home/byroehnu/easepaybiz.easetack.com/README.md

# 💰 EasePay Backend API# 🔐 EasePay Advanced Authentication System



A comprehensive PERN stack backend for EasePay - a modern business expense and sales tracking application.A comprehensive, enterprise-grade authentication system inspired by OPay, featuring multiple authentication methods, session management, and enhanced security.



## 🚀 **Quick Start**## 🌟 Features



### **Development Setup**### 🔑 Authentication Methods

```bash- **📞 OTP Authentication** - Phone-based verification with SMS

# Clone the repository- **🔢 PIN Authentication** - Quick 4-6 digit PIN login

git clone https://github.com/Emperooid/easepay-backend.git- **👆 Biometric Authentication** - Fingerprint/Face ID support

cd easepay-backend- **🔄 Auto-Login** - Session-based automatic login (30 days)

- **� Secure Logout** - Device-specific session management

# Install dependencies

npm install### 🛡️ Security Features

- **Account Lockout** - 5 failed attempts = 30-minute lockout

# Setup environment variables- **PIN Protection** - Hashed and salted PIN storage

cp .env.production.template .env- **Device Registration** - Multi-device support and management

# Edit .env with your actual values- **Session Tokens** - Long-lived session management

- **Transaction PIN** - Additional security for sensitive operations

# Run database migrations- **Rate Limiting** - API endpoint protection

npm run db:migrate**API Version:** v1  

**Authentication:** JWT Bearer Token

# Start development server

npm run dev---

```

## 📋 Table of Contents

### **Production Deployment**

```bash- [Authentication](#authentication)

# Build and start production server- [Business Management](#business-management)

npm start- [Sales Management](#sales-management)

- [Expense Management](#expense-management)

# Database operations- [Dashboard & Analytics](#dashboard--analytics)

npm run db:push        # Push schema to database- [Reports](#reports)

npm run db:studio      # Open Prisma Studio- [Tax Management](#tax-management)

```- [Credit Score](#credit-score)

- [Subscription Management](#subscription-management)

## 📊 **Project Structure**- [Error Handling](#error-handling)

- [Frontend Integration](#frontend-integration)

```

easepay-backend/---

├── config/           # Database and API configurations

├── controllers/      # Route handlers and business logic## 🔐 Authentication

├── frontend-examples/# Frontend integration examples

├── middleware/       # Express middleware (auth, validation)### Base Route: `/api/auth`

├── prisma/          # Database schema and migrations

├── routes/          # API route definitions#### Public Endpoints

├── scripts/         # Database initialization scripts

├── services/        # External service integrations| Method | Endpoint | Description |

└── utils/           # Utility functions|--------|----------|-------------|

```| `POST` | `/api/auth/register` | Register new user |

| `POST` | `/api/auth/login` | Login user |

## 🔧 **Core Features**| `POST` | `/api/auth/send-otp` | Send OTP to phone number |

| `POST` | `/api/auth/verify-otp` | Verify OTP and get JWT token |

### **🔐 Authentication System**| `POST` | `/api/auth/phone-login` | Send OTP for existing user login |

- **OTP.dev Integration** - Real SMS/WhatsApp verification| `GET` | `/api/auth/staff/invite/:token` | Get staff invitation details |

- **Multiple Login Methods** - Phone OTP, Password, PIN, Biometric

- **Smart Auth Flow** - Automatic user state detection#### Protected Endpoints

- **JWT Tokens** - Secure session management

| Method | Endpoint | Description |

### **💼 Business Management**|--------|----------|-------------|

- **Sales Tracking** - Record and manage sales transactions| `GET` | `/api/auth/me` | Get current user profile |

- **Expense Management** - Track business expenses with categories| `POST` | `/api/auth/staff/accept-invite` | Accept staff invitation |

- **Dashboard Analytics** - Real-time business insights

- **Staff Management** - Multi-user business access### Request Examples



### **📊 Advanced Features**#### Register User

- **Credit Score System** - Business creditworthiness tracking```javascript

- **Tax Reporting** - Quarterly and annual tax calculationsPOST /api/auth/register

- **Invoice Generation** - PDF invoice creationContent-Type: application/json

- **Subscription Management** - Flutterwave payment integration

{

## 🌐 **API Documentation**  "phone": "+1234567890",

  "role": "OWNER"  // Optional: OWNER, STAFF, ADMIN

### **Base URLs**}

- **Development**: `http://localhost:5004````

- **Production**: `https://easepay-backend.onrender.com`

- **API Docs**: `/api-docs` (Swagger UI)#### Login User

```javascript

### **Key Endpoints**POST /api/auth/login

Content-Type: application/json

#### **Authentication**

| Method | Endpoint | Description |{

|--------|----------|-------------|  "phone": "+1234567890"

| `POST` | `/api/auth/check-user-status` | Check user authentication state |}

| `POST` | `/api/auth/send-otp` | Send SMS/WhatsApp OTP |```

| `POST` | `/api/auth/verify-otp` | Verify OTP code |

| `POST` | `/api/auth/setup-password` | Setup account password |#### Send OTP

| `POST` | `/api/auth/signin` | Sign in with password |```javascript

POST /api/auth/send-otp

#### **Business Operations**Content-Type: application/json

| Method | Endpoint | Description |

|--------|----------|-------------|{

| `GET/POST` | `/api/sales` | Manage sales records |  "phone": "+1234567890"

| `GET/POST` | `/api/expenses` | Manage expense records |}

| `GET` | `/api/dashboard/overview` | Get business analytics |```

| `GET` | `/api/reports/profit-loss` | Generate P&L reports |

#### Verify OTP

## 🔑 **Environment Variables**```javascript

POST /api/auth/verify-otp

### **Required Variables**Content-Type: application/json

```bash

DATABASE_URL=postgresql://...          # PostgreSQL connection string{

JWT_SECRET=your_jwt_secret             # JWT signing secret (32+ chars)  "phone": "+1234567890",

OTP_API_KEY=your_otp_dev_key          # OTP.dev API key  "otp": "123456"

OTP_SENDER_ID=your_sender_id          # OTP.dev sender ID}

OTP_TEMPLATE_ID=your_template_id      # OTP.dev message template```

```

#### Phone Login (Existing Users)

### **Optional Variables**```javascript

```bashPOST /api/auth/phone-login

NODE_ENV=development                   # Environment modeContent-Type: application/json

PORT=5004                             # Server port

FRONTEND_URL=http://localhost:8081    # CORS frontend URL{

FLW_SECRET_KEY=flw_secret             # Flutterwave secret key  "phone": "+1234567890"

EMAIL_USER=your_email@gmail.com       # SMTP email settings}

``````



## 🛠 **Available Scripts**#### Response Format

```javascript

```bash// Login/Register Response

npm start              # Start production server{

npm run dev           # Start development server with nodemon  "success": true,

npm run db:migrate    # Run database migrations  "message": "Login successful",

npm run db:studio     # Open Prisma Studio  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",

npm run db:generate   # Generate Prisma client  "user": {

npm run test:otp      # Test OTP integration    "id": "uuid",

```    "phone": "+1234567890",

    "role": "OWNER"

## 📱 **Frontend Integration**  }

}

### **React Native Example**

```javascript// Send OTP Response

import { SmartAuthProvider, useSmartAuth } from './AuthContext';{

  "success": true,

// Wrap your app  "message": "OTP sent successfully",

<SmartAuthProvider>  "phone": "+1234567890",

  <App />  "otp": "123456"  // Only in development mode

</SmartAuthProvider>}



// Use in components// Verify OTP Response

const { handlePhoneInput, currentState } = useSmartAuth();{

```  "success": true,

  "message": "Phone verified successfully",

### **Authentication Flow**  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",

```javascript  "user": {

// 1. Check user status    "id": "uuid",

const status = await checkUserStatus(phone);    "phone": "+1234567890",

    "firstName": "User",

// 2. Route based on status    "lastName": "Temp",

switch(status.userStatus) {    "email": "1234567890@temp.com",

  case 'new': sendOTP(phone); break;    "role": "OWNER",

  case 'complete': showPasswordLogin(); break;    "phoneVerified": true

}  }

```}

```

## 🔒 **Security Features**

---

- **Rate Limiting** - 100 requests per 15 minutes

- **CORS Protection** - Configured for your frontend domain## 🏢 Business Management

- **Helmet Security** - HTTP headers protection

- **JWT Authentication** - Secure token-based auth### Base Route: `/api/business`

- **Phone Validation** - International format support**Authentication:** Required  

- **Password Hashing** - bcrypt with 12 rounds**Subscription:** Required



## 📚 **Documentation Files**| Method | Endpoint | Description |

|--------|----------|-------------|

- **`FRONTEND_API_ENDPOINTS.md`** - Complete API reference| `GET` | `/api/business/profile` | Get business profile |

- **`OTP_DEV_INTEGRATION_GUIDE.md`** - OTP service setup guide| `POST` | `/api/business/profile` | Create business profile |

- **`frontend-examples/`** - React/React Native integration examples| `PUT` | `/api/business/profile` | Update business profile |

| `DELETE` | `/api/business/profile` | Delete business profile |

## 🚀 **Deployment**| `POST` | `/api/business/staff` | Add staff member |

| `POST` | `/api/business/staff/invite` | Invite staff member |

### **Render Deployment**| `GET` | `/api/business/staff/:businessId` | Get staff list |

1. Connect GitHub repository| `DELETE` | `/api/business/staff` | Remove staff member |

2. Set environment variables from `.env.production.template`

3. Deploy automatically on push to main### Request Examples



### **Database Setup**#### Create Business

```bash```javascript

# Using Neon PostgreSQL (recommended)POST /api/business/profile

# 1. Create database at neon.techAuthorization: Bearer <token>

# 2. Copy connection string to DATABASE_URLContent-Type: application/json

# 3. Run migrations: npm run db:migrate

```{

  "name": "My Business",

## 🤝 **Contributing**  "type": "RETAIL",  // RETAIL, SERVICE, MANUFACTURING, etc.

  "vatRegistered": false,

1. Fork the repository  "hasStaff": true

2. Create feature branch (`git checkout -b feature/amazing-feature`)}

3. Commit changes (`git commit -m 'Add amazing feature'`)```

4. Push to branch (`git push origin feature/amazing-feature`)

5. Open Pull Request#### Invite Staff

```javascript

## 📄 **License**POST /api/business/staff/invite

Authorization: Bearer <token>

This project is licensed under the ISC License.Content-Type: application/json



## 👨‍💻 **Author**{

  "email": "staff@example.com",

**Emmanuel Awosika**  "role": "STAFF",

- GitHub: [@Emperooid](https://github.com/Emperooid)  "businessId": "business-uuid"

}

---```



## 🆘 **Support**---



For issues and questions:## 💰 Sales Management

1. Check API documentation at `/api-docs`

2. Review integration examples in `frontend-examples/`### Base Route: `/api/sales`

3. Test OTP service with `npm run test:otp`**Authentication:** Required

4. Open GitHub issue for bugs

| Method | Endpoint | Description |

**Built with ❤️ for modern business management**|--------|----------|-------------|
| `GET` | `/api/sales` | Get all sales (paginated) |
| `POST` | `/api/sales` | Create new sale |
| `GET` | `/api/sales/:id` | Get specific sale |
| `PUT` | `/api/sales/:id` | Update specific sale |
| `DELETE` | `/api/sales/:id` | Delete specific sale |

### Query Parameters for GET `/api/sales`

| Parameter | Type | Description |
|-----------|------|-------------|
| `page` | number | Page number (default: 1) |
| `limit` | number | Items per page (default: 10) |
| `startDate` | string | Filter from date (ISO format) |
| `endDate` | string | Filter to date (ISO format) |
| `category` | string | Filter by category |

### Request Examples

#### Create Sale
```javascript
POST /api/sales
Authorization: Bearer <token>
Content-Type: application/json

{
  "amount": "150.00",
  "description": "Product sale",
  "date": "2026-02-09T10:00:00Z",
  "businessId": "business-uuid"  // Optional
}
```

#### Get Sales with Filters
```javascript
GET /api/sales?page=1&limit=20&startDate=2026-02-01&endDate=2026-02-09
Authorization: Bearer <token>
```

### Response Format
```javascript
{
  "success": true,
  "sales": [
    {
      "id": "sale-uuid",
      "amount": "150.00",
      "description": "Product sale",
      "date": "2026-02-09T10:00:00Z",
      "userId": "user-uuid",
      "businessId": "business-uuid",
      "createdAt": "2026-02-09T10:00:00Z"
    }
  ],
  "pagination": {
    "page": 1,
    "limit": 20,
    "total": 50,
    "totalPages": 3
  }
}
```

---

## 💸 Expense Management

### Base Route: `/api/expenses`
**Authentication:** Required

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/expenses` | Get all expenses (paginated) |
| `POST` | `/api/expenses` | Create new expense |
| `GET` | `/api/expenses/:id` | Get specific expense |
| `PUT` | `/api/expenses/:id` | Update specific expense |
| `DELETE` | `/api/expenses/:id` | Delete specific expense |
| `GET` | `/api/expenses/analytics` | Get expense analytics |

### Request Examples

#### Create Expense
```javascript
POST /api/expenses
Authorization: Bearer <token>
Content-Type: application/json

{
  "amount": "50.00",
  "description": "Office supplies",
  "category": "office",
  "date": "2026-02-09T10:00:00Z",
  "businessId": "business-uuid"  // Optional
}
```

#### Get Expense Analytics
```javascript
GET /api/expenses/analytics
Authorization: Bearer <token>
```

---

## 📊 Dashboard & Analytics

### Base Route: `/api/dashboard`
**Authentication:** Required

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/dashboard/overview` | Get dashboard overview |
| `GET` | `/api/dashboard/sales-analytics` | Get sales analytics |
| `GET` | `/api/dashboard/expense-analytics` | Get expense analytics |

### Query Parameters

| Parameter | Type | Options | Description |
|-----------|------|---------|-------------|
| `timeframe` | string | week, month, year | For overview endpoint |
| `period` | string | week, month, year | For analytics endpoints |

### Request Examples

#### Get Dashboard Overview
```javascript
GET /api/dashboard/overview?timeframe=month
Authorization: Bearer <token>
```

### Response Format
```javascript
{
  "success": true,
  "data": {
    "revenue": {
      "current": 5000.00,
      "previous": 4500.00,
      "change": 11.11,
      "count": 25
    },
    "expenses": {
      "current": 1500.00,
      "previous": 1800.00,
      "change": -16.67,
      "count": 15
    },
    "profit": {
      "current": 3500.00,
      "previous": 2700.00,
      "change": 29.63
    },
    "recentTransactions": [...],
    "timeframe": "month"
  }
}
```

---

## 📈 Reports

### Base Route: `/api/reports`
**Authentication:** Required

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/reports/sales` | Get sales report |
| `GET` | `/api/reports/expenses` | Get expense report |
| `GET` | `/api/reports/profit-loss` | Get profit & loss report |

### Query Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `startDate` | string | Report start date (ISO format) |
| `endDate` | string | Report end date (ISO format) |
| `groupBy` | string | Group by: day, week, month |
| `category` | string | Filter by category |
| `format` | string | Response format: json, csv |

### Request Examples

#### Get Sales Report
```javascript
GET /api/reports/sales?startDate=2026-01-01&endDate=2026-02-09&groupBy=month
Authorization: Bearer <token>
```

---

## 🧮 Tax Management

### Base Route: `/api/tax`
**Authentication:** Required

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/tax/summary` | Get tax summary |
| `GET` | `/api/tax/quarterly/:year/:quarter` | Get quarterly tax report |
| `GET` | `/api/tax/annual/:year` | Get annual tax report |

### Request Examples

#### Get Quarterly Tax Report
```javascript
GET /api/tax/quarterly/2026/1
Authorization: Bearer <token>
```

#### Get Annual Tax Report
```javascript
GET /api/tax/annual/2026
Authorization: Bearer <token>
```

---

## 📊 Credit Score

### Base Route: `/api/credit-score`
**Authentication:** Required

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/credit-score` | Get current credit score |
| `GET` | `/api/credit-score/history` | Get credit score history |
| `POST` | `/api/credit-score/recalculate` | Force recalculate credit score |
| `GET` | `/api/credit-score/factors` | Get credit score factors |

### Query Parameters

| Parameter | Type | Description |
|-----------|------|-------------|
| `limit` | number | History items limit (default: 12) |

### Request Examples

#### Get Credit Score History
```javascript
GET /api/credit-score/history?limit=6
Authorization: Bearer <token>
```

### Response Format
```javascript
{
  "success": true,
  "creditScore": {
    "score": 750,
    "factors": {...},
    "recommendations": [...],
    "breakdown": {
      "paymentHistory": 85,
      "revenueStability": 78,
      "businessAge": 65,
      "expenseManagement": 82
    },
    "lastUpdated": "2026-02-09T10:00:00Z"
  }
}
```

---

## 💳 Subscription Management

### Base Route: `/api/subscription`

#### Public Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `GET` | `/api/subscription/plans` | Get available plans |

#### Protected Endpoints

| Method | Endpoint | Description |
|--------|----------|-------------|
| `POST` | `/api/subscription/subscribe` | Subscribe to a plan |
| `GET` | `/api/subscription/my-subscription` | Get current subscription |

### Request Examples

#### Subscribe to Plan
```javascript
POST /api/subscription/subscribe
Authorization: Bearer <token>
Content-Type: application/json

{
  "planId": "premium-plan",
  "paymentMethod": "card"
}
```

---

## ⚠️ Error Handling

### Error Response Format
```javascript
{
  "success": false,
  "message": "Error description",
  "errors": [
    {
      "field": "email",
      "message": "Email is required"
    }
  ]
}
```

### Common HTTP Status Codes

| Code | Meaning |
|------|---------|
| `200` | Success |
| `201` | Created |
| `400` | Bad Request |
| `401` | Unauthorized |
| `403` | Forbidden |
| `404` | Not Found |
| `429` | Too Many Requests |
| `500` | Internal Server Error |

---

## 🛠️ Frontend Integration

### Complete API Service Class

```javascript
class EasePayAPI {
  constructor() {
    this.baseURL = 'http://localhost:5004/api';
    this.token = localStorage.getItem('authToken');
  }

  // Helper Methods
  getHeaders() {
    const headers = { 'Content-Type': 'application/json' };
    if (this.token) {
      headers['Authorization'] = `Bearer ${this.token}`;
    }
    return headers;
  }

  setToken(token) {
    this.token = token;
    localStorage.setItem('authToken', token);
  }

  // Authentication
  async register(userData) {
    const response = await fetch(`${this.baseURL}/auth/register`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(userData)
    });
    return response.json();
  }

  async login(credentials) {
    const response = await fetch(`${this.baseURL}/auth/login`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(credentials)
    });
    const data = await response.json();
    if (data.success && data.token) {
      this.setToken(data.token);
    }
    return data;
  }

  // OTP Authentication
  async sendOTP(phone) {
    const response = await fetch(`${this.baseURL}/auth/send-otp`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone })
    });
    return response.json();
  }

  async verifyOTP(phone, otp) {
    const response = await fetch(`${this.baseURL}/auth/verify-otp`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone, otp })
    });
    const data = await response.json();
    if (data.success && data.token) {
      this.setToken(data.token);
    }
    return data;
  }

  async phoneLogin(phone) {
    const response = await fetch(`${this.baseURL}/auth/phone-login`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ phone })
    });
    return response.json();
  }

  async getCurrentUser() {
    const response = await fetch(`${this.baseURL}/auth/me`, {
      headers: this.getHeaders()
    });
    return response.json();
  }

  // Business Management
  async getBusinessProfile() {
    const response = await fetch(`${this.baseURL}/business/profile`, {
      headers: this.getHeaders()
    });
    return response.json();
  }

  async createBusiness(businessData) {
    const response = await fetch(`${this.baseURL}/business/profile`, {
      method: 'POST',
      headers: this.getHeaders(),
      body: JSON.stringify(businessData)
    });
    return response.json();
  }

  // Sales Management
  async getSales(params = {}) {
    const queryString = new URLSearchParams(params).toString();
    const response = await fetch(`${this.baseURL}/sales?${queryString}`, {
      headers: this.getHeaders()
    });
    return response.json();
  }

  async createSale(saleData) {
    const response = await fetch(`${this.baseURL}/sales`, {
      method: 'POST',
      headers: this.getHeaders(),
      body: JSON.stringify(saleData)
    });
    return response.json();
  }

  // Expense Management
  async getExpenses(params = {}) {
    const queryString = new URLSearchParams(params).toString();
    const response = await fetch(`${this.baseURL}/expenses?${queryString}`, {
      headers: this.getHeaders()
    });
    return response.json();
  }

  async createExpense(expenseData) {
    const response = await fetch(`${this.baseURL}/expenses`, {
      method: 'POST',
      headers: this.getHeaders(),
      body: JSON.stringify(expenseData)
    });
    return response.json();
  }

  // Dashboard
  async getDashboardOverview(timeframe = 'month') {
    const response = await fetch(`${this.baseURL}/dashboard/overview?timeframe=${timeframe}`, {
      headers: this.getHeaders()
    });
    return response.json();
  }

  // Reports
  async getSalesReport(params = {}) {
    const queryString = new URLSearchParams(params).toString();
    const response = await fetch(`${this.baseURL}/reports/sales?${queryString}`, {
      headers: this.getHeaders()
    });
    return response.json();
  }

  // Credit Score
  async getCreditScore() {
    const response = await fetch(`${this.baseURL}/credit-score`, {
      headers: this.getHeaders()
    });
    return response.json();
  }

  // Subscription
  async getSubscriptionPlans() {
    const response = await fetch(`${this.baseURL}/subscription/plans`);
    return response.json();
  }

  async subscribe(planData) {
    const response = await fetch(`${this.baseURL}/subscription/subscribe`, {
      method: 'POST',
      headers: this.getHeaders(),
      body: JSON.stringify(planData)
    });
    return response.json();
  }

  // Utility
  logout() {
    this.token = null;
    localStorage.removeItem('authToken');
  }

  isAuthenticated() {
    return !!this.token;
  }
}

// Export for use
const api = new EasePayAPI();
export default api;
```

### React Hook Example

```javascript
// useAPI.js
import { useState, useEffect } from 'react';
import api from './api';

export function useAuth() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const checkAuth = async () => {
      try {
        if (api.isAuthenticated()) {
          const result = await api.getCurrentUser();
          if (result.success) {
            setUser(result.user);
          }
        }
      } catch (error) {
        console.error('Auth check failed:', error);
      } finally {
        setLoading(false);
      }
    };

    checkAuth();
  }, []);

  const login = async (credentials) => {
    const result = await api.login(credentials);
    if (result.success) {
      setUser(result.user);
    }
    return result;
  };

  const logout = () => {
    api.logout();
    setUser(null);
  };

  return { user, loading, login, logout };
}

export function useDashboard() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const loadDashboard = async () => {
      try {
        const result = await api.getDashboardOverview();
        if (result.success) {
          setData(result.data);
        }
      } catch (error) {
        console.error('Dashboard load failed:', error);
      } finally {
        setLoading(false);
      }
    };

    loadDashboard();
  }, []);

  return { data, loading, refresh: () => loadDashboard() };
}
```

### Usage Examples

```javascript
// Login
const handleLogin = async (phone) => {
  const result = await api.login({ phone });
  if (result.success) {
    console.log('Logged in:', result.user);
  }
};

// OTP Authentication Flow
const handleOTPAuth = async (phone) => {
  try {
    // Step 1: Send OTP
    const otpResult = await api.sendOTP(phone);
    if (otpResult.success) {
      console.log('OTP sent to:', otpResult.phone);
      console.log('OTP (dev mode):', otpResult.otp);
      
      // Step 2: User enters OTP, then verify
      const userOTP = prompt('Enter OTP:'); // In real app, get from form
      const verifyResult = await api.verifyOTP(phone, userOTP);
      
      if (verifyResult.success) {
        console.log('Phone verified! User:', verifyResult.user);
        console.log('Token:', verifyResult.token);
        // Redirect to dashboard or next step
      }
    }
  } catch (error) {
    console.error('OTP authentication failed:', error);
  }
};

// Phone Login for Existing Users
const handlePhoneLogin = async (phone) => {
  const result = await api.phoneLogin(phone);
  if (result.success) {
    console.log('Login OTP sent to:', phone);
    // Then use verifyOTP to complete login
  }
};

// Create Sale
const createSale = async () => {
  const result = await api.createSale({
    amount: "150.00",
    description: "Product sale"
  });
  if (result.success) {
    console.log('Sale created:', result.sale);
  }
};

// Get Dashboard
const loadDashboard = async () => {
  const result = await api.getDashboardOverview('month');
  if (result.success) {
    console.log('Dashboard data:', result.data);
  }
};
```

---

## 🔒 Security & Authentication

### JWT Token
- Include in `Authorization` header as `Bearer <token>`
- Store securely in localStorage or httpOnly cookies
- Token expires after 7 days
- Refresh by re-logging in

### Rate Limiting
- 100 requests per 15 minutes per IP
- Applies to all `/api/*` routes

### CORS Policy
- Frontend URL: `http://localhost:3000` (configurable)
- Credentials allowed
- Methods: GET, POST, PUT, DELETE, PATCH, OPTIONS

---

## 📞 Support

For API questions or issues:
- Check server logs for detailed error messages
- Ensure proper authentication headers
- Verify request body format matches examples
- Check network connectivity to `http://localhost:5004`

---

## 📝 License

This API documentation is part of the EasePay project.

---

**Last Updated:** February 9, 2026  
**API Version:** v1.0.0
- **Backend**: Node.js with Express.js
- **Authentication**: JWT (JSON Web Tokens)
- **Security**: Helmet, CORS, Rate Limiting
- **Environment**: dotenv for configuration
- **Password Hashing**: bcryptjs
- **Development**: Nodemon for hot reloading

## Project Structure

```
backend/
├── config/
│   └── db.js                    # Database configuration
├── controllers/
│   ├── authController.js        # Authentication logic
│   ├── businessController.js    # Business management
│   ├── saleController.js        # Sales management
│   ├── expenseController.js     # Expense management
│   ├── dashboardController.js   # Dashboard analytics
│   ├── reportController.js      # Report generation
│   ├── taxController.js         # Tax calculations
│   └── creditScoreController.js # Credit score management
├── models/
│   ├── User.js                  # User model & schema
│   ├── Business.js              # Business model & schema
│   ├── Sale.js                  # Sales model & schema
│   ├── Expense.js               # Expense model & schema
│   └── CreditScore.js           # Credit score model & schema
├── routes/
│   ├── authRoutes.js            # Authentication routes
│   ├── businessRoutes.js        # Business routes
│   ├── saleRoutes.js            # Sales routes
│   ├── expenseRoutes.js         # Expense routes
│   ├── dashboardRoutes.js       # Dashboard routes
│   ├── reportRoutes.js          # Report routes
│   ├── taxRoutes.js             # Tax routes
│   └── creditScoreRoutes.js     # Credit score routes
├── middleware/
│   └── auth.js                  # Authentication middleware
├── utils/
│   └── creditScoreCalculator.js # Credit score calculation logic
├── scripts/
│   └── initDb.js                # Database initialization script
├── .env                         # Environment variables
├── package.json
├── server.js                    # Main server file
└── README.md
```

## Quick Start

### Prerequisites

- Node.js (v14 or higher)
- PostgreSQL (v12 or higher)
- npm or yarn

### Installation

1. **Clone and navigate to the project**:
   ```bash
   cd easepayBackend
   ```

2. **Install dependencies**:
   ```bash
   npm install
   ```

3. **Set up environment variables**:
   Update the `.env` file with your configuration:
   ```env
   # Database Configuration
   DB_HOST=localhost
   DB_PORT=5432
   DB_NAME=easepay_db
   DB_USER=your_username
   DB_PASSWORD=your_password

   # JWT Configuration
   JWT_SECRET=your-super-secret-jwt-key-change-this-in-production
   JWT_EXPIRE=7d

   # Server Configuration
   PORT=5000
   NODE_ENV=development

   # CORS Configuration
   FRONTEND_URL=http://localhost:3000
   ```

4. **Create PostgreSQL database**:
   ```sql
   CREATE DATABASE easepay_db;
   ```

5. **Initialize database tables**:
   ```bash
   npm run init-db
   ```

6. **Start the development server**:
   ```bash
   npm run dev
   ```

The server will start on `http://localhost:5000`

## API Endpoints

### Authentication
- `POST /api/auth/register` - Register new user
- `POST /api/auth/login` - User login
- `GET /api/auth/me` - Get current user (protected)

### Business Management
- `GET /api/business/profile` - Get business profile
- `POST /api/business/profile` - Create business profile
- `PUT /api/business/profile` - Update business profile
- `DELETE /api/business/profile` - Delete business profile

### Sales Management
- `GET /api/sales` - Get all sales (with pagination & filters)
- `POST /api/sales` - Create new sale
- `GET /api/sales/:id` - Get sale by ID
- `PUT /api/sales/:id` - Update sale
- `DELETE /api/sales/:id` - Delete sale

### Expense Management
- `GET /api/expenses` - Get all expenses (with pagination & filters)
- `POST /api/expenses` - Create new expense
- `GET /api/expenses/:id` - Get expense by ID
- `PUT /api/expenses/:id` - Update expense
- `DELETE /api/expenses/:id` - Delete expense
- `GET /api/expenses/categories` - Get expense categories

### Dashboard
- `GET /api/dashboard/overview` - Get dashboard overview
- `GET /api/dashboard/sales-chart` - Get sales chart data
- `GET /api/dashboard/expense-breakdown` - Get expense breakdown

### Reports
- `GET /api/reports/sales` - Generate sales report
- `GET /api/reports/expenses` - Generate expense report
- `GET /api/reports/profit-loss` - Generate profit/loss report

### Tax Management
- `GET /api/tax/summary` - Get tax summary
- `GET /api/tax/quarterly/:year/:quarter` - Get quarterly tax report
- `GET /api/tax/annual/:year` - Get annual tax report

### Credit Score
- `GET /api/credit-score` - Get current credit score
- `GET /api/credit-score/history` - Get credit score history
- `POST /api/credit-score/recalculate` - Force recalculate score
- `GET /api/credit-score/factors` - Get score factors explanation

## Database Schema

### Users Table
- `id` - Primary key
- `email` - Unique user email
- `password` - Hashed password
- `first_name` - User's first name
- `last_name` - User's last name
- `phone` - Phone number
- `business_name` - Business name
- `is_active` - Account status
- `email_verified` - Email verification status
- `created_at` - Creation timestamp
- `updated_at` - Last update timestamp

### Businesses Table
- `id` - Primary key
- `user_id` - Foreign key to users
- `business_name` - Business name
- `business_type` - Type of business
- `business_address` - Business address
- `tax_id` - Tax identification number
- `phone_number` - Business phone
- `email` - Business email
- `website` - Business website
- `description` - Business description
- Additional metadata fields

### Sales Table
- `id` - Primary key
- `user_id` - Foreign key to users
- `customer_name` - Customer name
- `customer_email` - Customer email
- `customer_phone` - Customer phone
- `items` - JSON array of sale items
- `subtotal` - Subtotal amount
- `tax` - Tax amount
- `total` - Total amount
- `payment_method` - Payment method
- `sale_date` - Sale date
- `notes` - Additional notes
- `category` - Sale category
- Additional metadata fields

### Expenses Table
- `id` - Primary key
- `user_id` - Foreign key to users
- `description` - Expense description
- `amount` - Expense amount
- `category` - Expense category
- `vendor` - Vendor/supplier
- `payment_method` - Payment method
- `expense_date` - Expense date
- `receipt_url` - Receipt image URL
- `notes` - Additional notes
- `is_deductible` - Tax deductible flag
- Additional metadata fields

### Credit Scores Table
- `id` - Primary key
- `user_id` - Foreign key to users
- `score` - Credit score (300-850)
- `factors` - JSON object of score factors
- `recommendations` - JSON array of recommendations
- `payment_history_score` - Payment history component score
- `revenue_stability_score` - Revenue stability component score
- `business_age_score` - Business age component score
- `expense_management_score` - Expense management component score
- Additional metadata fields

## Security Features

- **JWT Authentication** - Secure token-based authentication
- **Password Hashing** - bcrypt with salt rounds
- **Rate Limiting** - Protect against brute force attacks
- **CORS Protection** - Cross-origin resource sharing control
- **Helmet Security** - Various HTTP security headers
- **Input Validation** - Comprehensive data validation
- **SQL Injection Protection** - Parameterized queries

## Development

### Available Scripts

- `npm start` - Start production server
- `npm run dev` - Start development server with nodemon
- `npm run init-db` - Initialize database tables
- `npm test` - Run tests (to be implemented)

### Environment Variables

Make sure to set up all required environment variables in your `.env` file. See `.env.example` for reference.

### Database Setup

1. Install PostgreSQL
2. Create a new database
3. Update connection settings in `.env`
4. Run `npm run init-db` to create tables

## Credit Score Algorithm

The credit score system evaluates businesses based on four key factors:

1. **Payment History (35%)** - Transaction consistency and frequency
2. **Revenue Stability (30%)** - Revenue patterns and growth trends
3. **Business Age (20%)** - Time in business and account history
4. **Expense Management (15%)** - Expense-to-revenue ratio and management

Scores range from 300-850, similar to personal credit scores.

## Contributing

1. Fork the repository
2. Create a feature branch
3. Make your changes
4. Add tests if applicable
5. Submit a pull request

## License

ISC License - see LICENSE file for details

## Support

For support, please open an issue in the repository or contact the development team.

---

**Built with ❤️ using the PERN Stack**

Directory Contents

Dirs: 14 × Files: 19

Name Size Perms Modified Actions
.adminjs DIR
- drwxr-xr-x 2026-03-14 01:49:04
Edit Download
config DIR
- drwxr-xr-x 2026-03-14 01:49:04
Edit Download
- drwxr-xr-x 2026-03-14 01:49:12
Edit Download
- drwxr-xr-x 2026-03-14 01:49:04
Edit Download
- drwxr-xr-x 2026-03-14 01:49:04
Edit Download
images DIR
- drwxr-xr-x 2026-03-21 09:47:23
Edit Download
- drwxr-xr-x 2026-03-22 12:37:17
Edit Download
- drwxr-xr-x 2026-03-14 01:49:04
Edit Download
prisma DIR
- drwxr-xr-x 2026-03-14 01:49:04
Edit Download
routes DIR
- drwxr-xr-x 2026-03-20 23:25:48
Edit Download
scripts DIR
- drwxr-xr-x 2026-03-20 00:05:44
Edit Download
services DIR
- drwxr-xr-x 2026-03-20 11:35:27
Edit Download
tmp DIR
- drwxr-xr-x 2026-03-22 07:35:33
Edit Download
utils DIR
- drwxr-xr-x 2026-03-14 01:49:04
Edit Download
1.87 KB lrw-r--r-- 2026-03-02 07:23:00
Edit Download
3.02 KB lrw-r--r-- 2026-02-26 16:27:46
Edit Download
54 B lrw-r--r-- 2026-03-03 05:21:52
Edit Download
1.99 KB lrw-r--r-- 2026-03-02 04:00:46
Edit Download
1.99 KB lr--r--r-- 2026-03-14 01:40:10
Edit Download
21.77 KB lrw-r--r-- 2026-03-04 23:41:22
Edit Download
95.99 MB lrw-r--r-- 2026-03-04 23:40:43
Edit Download
23.32 KB lr--r--r-- 2026-03-14 00:49:43
Edit Download
5.12 KB lrw-r--r-- 2026-03-02 08:04:38
Edit Download
360.34 KB lrw-r--r-- 2026-02-28 13:42:20
Edit Download
1.94 KB lrw-r--r-- 2026-03-05 15:13:41
Edit Download
33.05 KB lrw-r--r-- 2026-02-28 12:52:54
Edit Download
374 B lrw-r--r-- 2026-01-26 22:49:38
Edit Download
37.08 KB lrw-r--r-- 2026-02-26 16:27:46
Edit Download
88 B lrw-r--r-- 2026-03-14 00:49:44
Edit Download
7.04 KB lrw-r--r-- 2026-03-04 23:57:24
Edit Download
331.20 KB lrw-r--r-- 2026-03-12 06:51:30
Edit Download
6.32 KB lrw-r--r-- 2026-02-26 16:27:46
Edit Download
6.11 KB lr--r--r-- 2026-03-14 01:40:10
Edit Download

If ZipArchive is unavailable, a .tar will be created (no compression).