# Backend Architecture Overview

## Table of Contents
1. [System Overview](#system-overview)
2. [Architecture Pattern](#architecture-pattern)
3. [Technology Stack](#technology-stack)
4. [Project Structure](#project-structure)
5. [Design Patterns Used](#design-patterns-used)
6. [Pattern Evaluation](#pattern-evaluation)
7. [Recommendations](#recommendations)
8. [Local-Only POS Considerations](#local-only-pos-considerations)
9. [Data Flow](#data-flow)
10. [Database Schema](#database-schema)

---

## System Overview

This is a **local-only Point of Sale (POS) system** built with Node.js/Express and MongoDB. It runs on a single computer and does not connect to the internet or external services (except for local network).

### Key Capabilities
- 💳 **Sales Processing**: Bills and Invoices management
- 📦 **Inventory**: Product tracking with stock levels and expiry dates
- 💰 **Accounting**: Loan management, accounts payable/receivable, expense tracking
- 👥 **Payroll**: Employee salary management
- 📊 **Analytics**: Bilingual (Dari/English) PDF reports with currency support
- 🔐 **Security**: JWT-based authentication with role-based access control
- 🖨️ **Printing**: Receipt printing via ESPOs drivers
- 📝 **Audit**: Comprehensive audit logging for compliance
- 📱 **Multi-platform**: REST API supports desktop and mobile frontends

---

## Architecture Pattern

### **Current Pattern: API-Centric MVC (Model-Controller-Router)**

```
HTTP Request
    ↓
Router (RESTful endpoints)
    ↓
Middleware (Auth, Validation, Error Handling)
    ↓
Controller (Business Logic)
    ↓
Model (Data Persistence via Mongoose)
    ↓
MongoDB (Local Database)
    ↓
HTTP Response (JSON)
```

### Why MVC for a Local POS?
- **Separation of Concerns**: Easy to debug and maintain
- **Testability**: Isolated layers are testable
- **Scalability**: If business needs expand, pattern supports evolution
- **Team Collaboration**: Clear role division between data, logic, and routing

---

## Technology Stack

### Core Framework
| Component | Technology | Version | Purpose |
|-----------|-----------|---------|---------|
| **Runtime** | Node.js | Latest | JavaScript execution |
| **Web Server** | Express.js | ^4.21.2 | HTTP server and routing |
| **Database** | MongoDB | Local instance | Data persistence |
| **ODM** | Mongoose | ^8.0.0 | Schema-based MongoDB interaction |

### Authentication & Security
| Package | Purpose |
|---------|---------|
| `bcryptjs` | Password hashing and verification |
| `jsonwebtoken` | JWT token generation and validation |
| `helmet` | HTTP header security |
| `xss-clean` | XSS attack prevention |
| `hpp` | HTTP Parameter Pollution protection |
| `express-rate-limit` | Rate limiting for API endpoints |

### Data Validation & Processing
| Package | Purpose |
|---------|---------|
| `zod` | Runtime schema validation |
| `multer` | File upload handling |
| `sharp` | Image optimization and resizing |

### Business-Specific Features
| Package | Purpose |
|---------|---------|
| `pdf-lib` + `@pdf-lib/fontkit` | PDF generation with Unicode (Dari) support |
| `escpos` + drivers | Receipt printer integration |
| `nodemailer` | Email notifications |
| `redis` | Caching and session management |

### Development & Quality
| Package | Purpose |
|---------|---------|
| `nodemon` | Auto-restart during development |
| `jest` | Unit and integration testing |
| `eslint` | Code linting |
| `morgan` | HTTP request logging |
| `compression` | gzip response compression |

---

## Project Structure

```
POS-Backend/
├── Controllers/              # Business logic layer (22 controllers)
│   ├── authController.js     # Authentication & user management
│   ├── billsController.js    # Bill processing
│   ├── invoicesController.js # Invoice management
│   ├── loansController.js    # Loan operations
│   ├── reportsController.js  # Analytics & PDF generation
│   ├── analyticsController.js# Data aggregation
│   └── [17 more...]          # Domain-specific controllers
│
├── Modles/                   # Mongoose schemas (18 models)
│   ├── BillsModel.js
│   ├── InvoiceModel.js
│   ├── ProductModle.js
│   ├── UserDetailsModel.js
│   └── [14 more...]
│
├── Routers/                  # RESTful route definitions
│   ├── billsRouter.js
│   ├── invoicesRouter.js
│   └── [19 more...]
│
├── Valadation/               # Zod schema validation
│   ├── billvalidation.schema.js
│   ├── uservalidation.schema.js
│   └── [3 more...]
│
├── utils/                    # Utilities and helpers
│   ├── reports/              # Report generation modules (modularized)
│   │   ├── reportShared.js          # Shared constants & i18n
│   │   ├── collectAnalyticsReportData.js  # Data aggregation
│   │   └── renderAnalyticsReportPdf.js    # PDF rendering with Dari support
│   ├── CatchAsync.js         # Async error wrapper
│   ├── AppError.js           # Custom error class
│   ├── upload.js             # Multer file upload config
│   ├── imageproccessor.js    # Image optimization middleware
│   └── [3 more...]
│
├── __tests__/                # Test suites
│   ├── billvalidation.schema.test.js
│   └── [4 more...]
│
├── app.js                    # Express app configuration
├── server.js                 # Server startup
├── config.env                # Environment configuration
├── package.json              # Dependencies
├── jest.config.js            # Test configuration
└── fonts/                    # Vazirmatn-Regular.ttf for Dari text in PDFs
```

### Folder Naming Notes
- **Modles/** (typo: should be `Models/`) - Contains Mongoose schemas
- **Valadation/** (typo: should be `Validation/`) - Contains Zod validation schemas
- **Controllers/** - Named well; domain-centric organization
- **utils/reports/** - Recently refactored into modular components (recommended pattern)

---

## Design Patterns Used

### 1. **Factory Pattern** ✅ GOOD
**Location**: `Controllers/FactoryHundlers.js`

```javascript
// Generic CRUD handlers
exports.getAll = Model => catchAsync(async (req, res, next) => {
  const docs = await Model.find().lean();
  res.status(200).json({ status: 'success', data: { data: docs } });
});

exports.findOne = (Model, modelName) => catchAsync(async (req, res, next) => {
  const doc = await Model.findById(req.params.id).lean();
  if (!doc) return next(new AppError(`No ${modelName} found`, 404));
  res.status(200).json({ status: 'success', data: { doc } });
});
```

**Evaluation**: ✅ **EXCELLENT for local POS**
- Reduces code duplication for standard CRUD operations
- Easy to maintain and extend
- Suitable for a single-machine system with modest complexity

---

### 2. **Async Error Handling (Higher-Order Function)** ✅ EXCELLENT
**Location**: `utils/CatchAsync.js`

```javascript
module.exports = fn => {
  return (req, res, next) => {
    fn(req, res, next).catch(next);
  };
};
```

**Evaluation**: ✅ **OPTIMAL**
- Eliminates try-catch boilerplate in every route handler
- Centralizes error handling via middleware
- Prevents unhandled promise rejections
- Perfect for a local system with predictable error scenarios

---

### 3. **Custom Error Class** ✅ GOOD
**Location**: `utils/AppError.js`

```javascript
class AppError extends Error {
  constructor(message, statusCode) {
    super(message);
    this.statusCode = statusCode;
    this.status = `${statusCode}`.startsWith('4') ? 'fail' : 'error';
    this.isOperational = true;
    Error.captureStackTrace(this, this.constructor);
  }
}
```

**Evaluation**: ✅ **GOOD**
- Consistent error response format
- Distinguishes operational errors from programming errors
- Enables precise HTTP status code mapping
- **Note**: `isOperational` flag is set but not used in global error handler (minor issue)

---

### 4. **Middleware Chain Pattern** ✅ GOOD
**Location**: `Routers/productsRouter.js`

```javascript
router
  .route("/:id")
  .put(
    authController.protect,        // Authentication
    upload.single("image"),        // File upload
    optimizeImage,                 // Image processing
    productController.updateProduct // Business logic
  );
```

**Evaluation**: ✅ **GOOD**
- Clear, composable middleware order
- Reusable across multiple routes
- Prevents unauthorized access early
- **Local POS benefit**: No need for complex permission layers

---

### 5. **Domain-Centric Organization** ✅ GOOD
**Location**: `Controllers/`, `Routers/`, `Modles/`

Organizations:
- `billsController.js` + `billsRouter.js` + `BillsModel.js`
- `invoicesController.js` + `invoicesRouter.js` + `InvoiceModel.js`
- `loansController.js` + `loansRouter.js` + `LoanModel.js`

**Evaluation**: ✅ **GOOD**
- Easy to locate related code
- Supports team development (each engineer owns a domain)
- Straightforward dependency tracking
- **For local POS**: Perfect scale—no need for further modularization yet

---

### 6. **Modular Report Generation** ✅ EXCELLENT (Recently Refactored)
**Location**: `utils/reports/`

Three focused modules:
- `reportShared.js` - Shared constants, i18n, helpers
- `collectAnalyticsReportData.js` - Data aggregation logic
- `renderAnalyticsReportPdf.js` - PDF rendering with Dari/English support

**Evaluation**: ✅ **EXCELLENT**
- Follows separation of concerns
- Easy to test individual components
- Unicode font support for Dari text with proper bidirectional text handling
- Demonstrates how to break down large controllers
- **Recommendation**: Apply this pattern to other large controllers

---

### 7. **Input Validation (Zod)** ✅ VERY GOOD
**Location**: `Valadation/*.schema.js`, used in controllers

```javascript
const parsedData = createUserSchema.parse(req.body);
// or
const parsedData = createBillSchema.parse(req.body);
```

**Evaluation**: ✅ **VERY GOOD**
- Runtime schema validation (catches errors early)
- Type-safe data extraction
- Automatic error response formatting via global error handler
- **Better than alternatives**: More lightweight than TypeScript, better than manual validation

---

### 8. **Local File Storage (Multer)** ✅ APPROPRIATE
**Location**: `utils/upload.js`

```javascript
const storage = multer.diskStorage({
  destination: (req, file, cb) => cb(null, 'uploads/product/'),
  filename: (req, file, cb) => {
    const uniqueSuffix = Date.now() + '-' + Math.random();
    cb(null, `${file.fieldname}-${uniqueSuffix}${ext}`);
  }
});
```

**Evaluation**: ✅ **APPROPRIATE for local POS**
- No cloud dependencies (S3, Cloudinary)
- Direct file access for fast retrieval
- Backups are simpler (just backup the folder)
- **Perfect for local system**: Reduced complexity, zero latency

---

## Pattern Evaluation

### Summary Table

| Pattern | Used | Rating | Suitable for Local POS? | Notes |
|---------|------|--------|------------------------|-------|
| MVC/MCA | ✅ | ⭐⭐⭐⭐⭐ | Yes | Clear separation of concerns |
| Factory Pattern | ✅ | ⭐⭐⭐⭐⭐ | Yes | Reduces CRUD boilerplate |
| Async Error Handling | ✅ | ⭐⭐⭐⭐⭐ | Yes | Prevents unhandled rejections |
| Custom Error Class | ✅ | ⭐⭐⭐⭐ | Yes | Good but under-utilized |
| Middleware Chain | ✅ | ⭐⭐⭐⭐⭐ | Yes | Composable and reusable |
| Domain Organization | ✅ | ⭐⭐⭐⭐ | Yes | Easy to navigate |
| Modular Reports | ✅ | ⭐⭐⭐⭐⭐ | Yes | Best practice demonstrated |
| Zod Validation | ✅ | ⭐⭐⭐⭐⭐ | Yes | Runtime type safety |
| Local File Storage | ✅ | ⭐⭐⭐⭐ | Yes | Zero cloud overhead |
| Service Layer | ❌ | N/A | Maybe | See recommendations |
| Dependency Injection | ❌ | N/A | No | Unnecessary complexity |
| Microservices | ❌ | N/A | No | Overkill for local system |

---

## Recommendations

### 1. **Fix Folder Naming (Quick Win)** 🔧
```
Modles/  → Models/
Valadation/ → Validation/
FactoryHundlers.js → FactoryHandlers.js (typo)
CatchAsync.js → catchAsync.js (naming convention)
```
**Why**: Improves professionalism and follows JavaScript conventions.

---

### 2. **Create a Service Layer (Medium Priority)** 📋

**Current Structure**:
```
Controller (23 files)
  ↓
Database Model
```

**Recommended Structure**:
```
Controller
  ↓
Service Layer (Business Logic)
  ↓
Database Model
```

**Example**:
```javascript
// services/billService.js
class BillService {
  async createBill(billData) {
    // Validate stock availability
    // Calculate gross profit
    // Create related loan entries
    // Handle payment status
    return bill;
  }
  
  async getBillAnalytics(dateRange) {
    // Aggregate bill data
    // Calculate KPIs
    return analytics;
  }
}

// Then use in controller:
// const bill = await billService.createBill(req.body);
```

**Benefits**:
- Business logic isolated from HTTP concerns
- Easier to reuse logic (e.g., bill creation for API and scheduled jobs)
- Simpler controller testing
- Better for future mobile app backend reuse

---

### 3. **Apply Report Modularization Pattern Everywhere** 📦

**Current state**: `utils/reports/` is modular (good!)
**Apply to**: Large controllers like `billsController.js`, `invoicesController.js`

**Example**:
```
utils/
├── bills/
│   ├── billShared.js (constants, helpers)
│   ├── billService.js (business logic)
│   └── billValidators.js (complex validations)
├── invoices/
│   ├── invoiceShared.js
│   └── invoiceService.js
└── reports/
    ├── reportShared.js ✅ Already done
    ├── collectAnalyticsReportData.js ✅ Already done
    └── renderAnalyticsReportPdf.js ✅ Already done
```

---

### 4. **Enhance Error Handling** 🛡️

**Current issue**: `AppError.isOperational` not used:
```javascript
// In globalErrorHandler.js, add:
if (err.isOperational) {
  res.status(err.statusCode).json({
    status: err.status,
    message: err.message
  });
} else {
  // Log to file, don't expose details
  console.error('Programming error:', err);
  res.status(500).json({
    status: 'error',
    message: 'Something went wrong'
  });
}
```

---

### 5. **Add Caching Layer (Optional)** 💾

**Current**: Redis dependency installed but not used.

**Use cases for local POS**:
```javascript
// Cache product list (changes rarely)
const productCache = new Map();

exports.getAllProducts = catchAsync(async (req, res, next) => {
  if (productCache.has('all')) {
    return res.json(productCache.get('all'));
  }
  
  const products = await Product.find().lean();
  productCache.set('all', products);
  res.json(products);
});
```

**Why useful**: Frequent product lookups during bill/invoice creation.

---

### 6. **Implement Repository Pattern (Optional)** 🏗️

**For even cleaner separation**:
```
// repos/billRepository.js
class BillRepository {
  async query(filter) { return Bill.find(filter).lean(); }
  async create(data) { return Bill.create(data); }
  async update(id, data) { return Bill.findByIdAndUpdate(id, data); }
}

// Then in service:
const bill = await billRepository.create(billData);
```

**When to use**: If controllers grow beyond 500 lines.

---

## Local-Only POS Considerations

### Advantages of Current Architecture
1. ✅ **No network overhead**: Everything runs locally
2. ✅ **Direct filesystem access**: Can optimize for local storage
3. ✅ **Single-machine predictability**: No distributed system complexity
4. ✅ **Zero external dependencies**: More reliable (works offline)
5. ✅ **Simple backups**: Just copy the database and uploads folder

### Optimizations for Local POS
1. **Connection pooling**: MongoDB connection is always local (minimal benefit)
2. **Rate limiting**: Can be disabled (single trusted user)
3. **CORS**: Only needed for frontend on same machine (could be simpler)
4. **File uploads**: Local storage is optimal (keep current approach)
5. **Session management**: JWT works fine (no centralized session store needed)

### Features That Make Sense Locally
| Feature | Benefit | Priority |
|---------|---------|----------|
| Comprehensive Audit Logging | Compliance, accountability | ⭐⭐⭐ |
| PDF Bilingual Reports | Business reporting (Dari/English) | ⭐⭐⭐⭐⭐ |
| Receipt Printing | Daily operations | ⭐⭐⭐⭐⭐ |
| Offline-first caching | N/A (not needed) | ❌ |
| API rate limiting | N/A (single user) | ⚠️ |
| CDN for static files | N/A | ❌ |

---

## Data Flow

### Example: Creating a Bill (Complete Flow)

```
1. Frontend → POST /api/v1/bills
   └─ JSON payload with bill items
   
2. Middleware Chain
   ├─ authController.protect → Verify JWT token
   ├─ zod validation → Parse & validate request body
   └─ Next middleware or error
   
3. billsController.createBill (CatchAsync wrapper)
   ├─ Validate product availability via ProductModel
   ├─ Check stock levels
   ├─ Calculate gross profit
   ├─ Create bill record via BillsModel
   ├─ (Future) Call billService.createBill() for logic
   └─ Handle errors via AppError
   
4. Database Operations (Mongoose/MongoDB)
   ├─ Save bill document
   ├─ Update product stock
   ├─ Create loan entry (if required)
   └─ Return result
   
5. Controller Response
   ├─ Format response as JSON
   └─ res.status(201).json({ status: 'success', data: bill })
   
6. Global Error Handler (if error occurred)
   └─ globalErrorHandler.js formats error response

7. Frontend receives response
   └─ UI updates with bill confirmation
```

---

## Database Schema

### Core Collections (18 Models)

| Collection | Purpose | Key Fields | Relationships |
|-----------|---------|-----------|---|
| **users** | User accounts | name, email, password, role | N:1 company |
| **products** | Inventory | firstname, barcode, stock, mainprice, sellingprice, expirydate | N:1 category |
| **bills** | POS transactions | billNumber, items[], total, paymentStatus | N:1 account |
| **invoices** | Customer invoices | invoiceNumber, items[], paymentStatus, totalAmount | N:1 account |
| **categories** | Product categories | name | 1:N products |
| **loans** | Loan records | loanNumber, amount, status | N:1 account |
| **loanaccounts** | Customer/vendor accounts | name, accountCode, accountType | 1:N loans/invoices |
| **expenses** | Business expenses | title, category, amount, status | Standalone |
| **payroll** | Employee salaries | userId, amount, date, status | N:1 user |
| **cashincashout** | Cash transactions | amount, category, type, timestamp | Standalone |
| **orders** | Purchase/sales orders | orderNumber, items[], status | Standalone |
| **invoiceitems** | Line items (embedded in invoice) | productId, quantity, unitprice | N:1 invoice |
| **auditlogs** | Compliance logs | action, entity, before, after, user, timestamp | N:1 user |
| **accountpayable** | AP tracking | vendorId, amount, dueDate | N:1 vendor |
| **expenses** | Expense records | title, category, amount, date | Standalone |
| **userdetails** | Advanced user info | userId, bankAccount, address | 1:1 user |
| **companydetails** | Company info | name, address, phone, tax_id | Standalone |
| **expensecategory** | Expense categories | name, description | 1:N expenses |

### Key Indexes (Performance Optimization)
```javascript
// productSchema has indexes on:
// - firstname (search by name)
// - category (filter by category)
// - status (filter active/inactive)
// - expirydate (find expired products)
// - companyname (multi-company support)

// Good practice: Add similar indexes to high-query models
// (bills, invoices, loans, users)
```

---

## Conclusion

### Overall Assessment: ⭐⭐⭐⭐ (4/5)

**Strengths**:
- ✅ Clean MVC separation
- ✅ Excellent error handling patterns
- ✅ Proper validation layer
- ✅ Domain-organized code
- ✅ Recent modularization of reports (best practice)
- ✅ Local-first design (appropriate for standalone POS)

**Areas for Improvement**:
- ⚠️ Add service layer for complex business logic
- ⚠️ Fix folder naming conventions
- ⚠️ Inconsistent controller sizes (some are very large)
- ⚠️ Under-utilized Redis (optional)

**Recommendation**: 
This architecture is **well-suited for a local-only POS system**. The patterns chosen are pragmatic and maintainable. Before scaling (if needed), implement the service layer pattern and continue the modularization trend.

The system is ready for **production deployment on a single machine** with the caveat that offline-first caching, microservices, or horizontal scaling are not necessary or beneficial in this context.

---

## Quick Reference: What to Do Next

1. **Immediate** (1-2 hours):
   - Rename folders: `Modles/` → `Models/`, `Valadation/` → `Validation/`
   - Fix typos in filenames

2. **Short-term** (1-2 weeks):
   - Create `services/` directory
   - Extract bill/invoice business logic into services
   - Add proper error distinction in global handler

3. **Medium-term** (1-2 months):
   - Apply modularization to large controllers
   - Add more integration tests
   - Implement data caching for performance

4. **Long-term** (Ongoing):
   - Monitor performance, optimize queries
   - Gather user feedback for feature prioritization
   - Regular security audits

---

**Document Version**: 1.0  
**Last Updated**: April 2026  
**Architecture Owner**: Backend Team  
**Status**: Current & Actively Maintained
