834 lines
18 KiB
Markdown
834 lines
18 KiB
Markdown
# Elysia API Documentation
|
|
|
|
## Overview
|
|
|
|
This project uses ElysiaJS integrated with Next.js App Router to create high-performance, type-safe APIs. The codebase follows a **Feature-based MVC pattern** for maintainability and scalability.
|
|
|
|
## Base URL
|
|
|
|
```
|
|
http://localhost:3000
|
|
```
|
|
|
|
## Endpoints
|
|
|
|
### Customers API
|
|
|
|
#### Get All Customers by Branch
|
|
|
|
```
|
|
GET /api/customers/:branch
|
|
```
|
|
|
|
**Parameters:**
|
|
|
|
- `branch` (path parameter, required): Branch identifier
|
|
- Examples: `branch-01`, `branch-02`, `head-office`
|
|
- `status` (query parameter, optional): Filter by customer status
|
|
- Values: `active`, `inactive`, `pending`
|
|
|
|
**Examples:**
|
|
|
|
1. Get all customers from branch-01:
|
|
|
|
```bash
|
|
curl http://localhost:3000/api/customers/branch-01
|
|
```
|
|
|
|
2. Get active customers from branch-02:
|
|
|
|
```bash
|
|
curl "http://localhost:3000/api/customers/branch-02?status=active"
|
|
```
|
|
|
|
3. Get pending customers from head-office:
|
|
|
|
```bash
|
|
curl "http://localhost:3000/api/customers/head-office?status=pending"
|
|
```
|
|
|
|
**Response Format:**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"id": "cust-001",
|
|
"branch": "branch-01",
|
|
"name": "สมชาย ใจดี",
|
|
"email": "somchai@example.com",
|
|
"phone": "081-234-5678",
|
|
"company": "บริษัท ไทยธุรกิจ จำกัด",
|
|
"address": "123 ถนนสุขุมวิท แขวงคลองตัน เขตคลองเตย กรุงเทพฯ 10110",
|
|
"status": "active",
|
|
"createdAt": "2024-01-15T09:00:00Z",
|
|
"updatedAt": "2024-01-15T09:00:00Z"
|
|
}
|
|
],
|
|
"count": 1,
|
|
"message": "Found 1 customer(s) for branch: branch-01"
|
|
}
|
|
```
|
|
|
|
#### Get Single Customer by ID
|
|
|
|
```
|
|
GET /api/customers/:branch/:id
|
|
```
|
|
|
|
#### Create Customer
|
|
|
|
```
|
|
POST /api/customers
|
|
```
|
|
|
|
#### Update Customer
|
|
|
|
```
|
|
PUT /api/customers/:branch/:id
|
|
```
|
|
|
|
#### Delete Customer
|
|
|
|
```
|
|
DELETE /api/customers/:branch/:id
|
|
```
|
|
|
|
---
|
|
|
|
### Quotations API
|
|
|
|
#### Get All Quotations by Branch
|
|
|
|
```
|
|
GET /api/quotations/:branch
|
|
```
|
|
|
|
**Parameters:**
|
|
|
|
- `branch` (path parameter, required): Branch identifier
|
|
- Examples: `branch-01`, `branch-02`, `head-office`
|
|
- `status` (query parameter, optional): Filter by quotation status
|
|
- Values: `draft`, `sent`, `accepted`, `rejected`, `expired`
|
|
|
|
**Examples:**
|
|
|
|
1. Get all quotations from branch-01:
|
|
|
|
```bash
|
|
curl http://localhost:3000/api/quotations/branch-01
|
|
```
|
|
|
|
2. Get sent quotations from head-office:
|
|
|
|
```bash
|
|
curl "http://localhost:3000/api/quotations/head-office?status=sent"
|
|
```
|
|
|
|
**Response Format:**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"id": "quot-001",
|
|
"quotationNumber": "QT-2024-001",
|
|
"branch": "branch-01",
|
|
"customerId": "cust-001",
|
|
"customerName": "สมชาย ใจดี",
|
|
"date": "2024-01-20T00:00:00Z",
|
|
"validUntil": "2024-02-20T00:00:00Z",
|
|
"subtotal": 50000,
|
|
"taxRate": 0.07,
|
|
"taxAmount": 3500,
|
|
"totalAmount": 53500,
|
|
"status": "sent",
|
|
"notes": "Quotation for office supplies",
|
|
"createdAt": "2024-01-20T09:00:00Z",
|
|
"updatedAt": "2024-01-20T09:00:00Z"
|
|
}
|
|
],
|
|
"count": 2,
|
|
"message": "Found 2 quotation(s) for branch: branch-01"
|
|
}
|
|
```
|
|
|
|
#### Get Single Quotation by ID
|
|
|
|
```
|
|
GET /api/quotations/:branch/:id
|
|
```
|
|
|
|
#### Create Quotation
|
|
|
|
```
|
|
POST /api/quotations
|
|
```
|
|
|
|
#### Update Quotation
|
|
|
|
```
|
|
PUT /api/quotations/:branch/:id
|
|
```
|
|
|
|
#### Delete Quotation
|
|
|
|
```
|
|
DELETE /api/quotations/:branch/:id
|
|
```
|
|
|
|
---
|
|
|
|
### Master Options API
|
|
|
|
#### Get All Master Options
|
|
|
|
```
|
|
GET /api/master-options
|
|
```
|
|
|
|
**Query Parameters:**
|
|
|
|
- `category` (optional): Filter by category (e.g., `customer_type`, `payment_method`, `industry`)
|
|
- `isActive` (optional): Filter by active status (`true` or `false`)
|
|
- `search` (optional): Search in code, nameTh, or nameEn
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl "http://localhost:3000/api/master-options?category=customer_type&isActive=true"
|
|
```
|
|
|
|
**Response Format:**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"id": "opt-001",
|
|
"branchId": "branch-01",
|
|
"category": "customer_type",
|
|
"code": "CORPORATE",
|
|
"nameTh": "องค์กร/บริษัท",
|
|
"nameEn": "Corporate",
|
|
"descriptionTh": "ลูกค้าประเภทองค์กร",
|
|
"descriptionEn": "Corporate customers",
|
|
"isActive": true,
|
|
"createdAt": "2024-01-15T09:00:00Z",
|
|
"updatedAt": "2024-01-15T09:00:00Z"
|
|
}
|
|
],
|
|
"count": 1,
|
|
"message": "Found 1 master option(s)"
|
|
}
|
|
```
|
|
|
|
#### Get Single Master Option
|
|
|
|
```
|
|
GET /api/master-options/:id
|
|
```
|
|
|
|
#### Create Master Option
|
|
|
|
```
|
|
POST /api/master-options
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{
|
|
"category": "customer_type",
|
|
"code": "INDIVIDUAL",
|
|
"nameTh": "บุคคลธรรมดา",
|
|
"nameEn": "Individual",
|
|
"descriptionTh": "ลูกค้ารายบุคคล",
|
|
"descriptionEn": "Individual customers"
|
|
}
|
|
```
|
|
|
|
#### Update Master Option
|
|
|
|
```
|
|
PUT /api/master-options/:id
|
|
```
|
|
|
|
#### Delete Master Option
|
|
|
|
```
|
|
DELETE /api/master-options/:id
|
|
```
|
|
|
|
#### Toggle Active Status
|
|
|
|
```
|
|
PATCH /api/master-options/:id/toggle
|
|
```
|
|
|
|
---
|
|
|
|
### Locations API
|
|
|
|
#### Get All Locations
|
|
|
|
```
|
|
GET /api/locations
|
|
```
|
|
|
|
**Query Parameters:**
|
|
|
|
- `type` (optional): Filter by location type (`country`, `province`, `district`, `subdistrict`)
|
|
- `parentId` (optional): Filter by parent location ID
|
|
- `search` (optional): Search in code, nameTh, or nameEn
|
|
- `isActive` (optional): Filter by active status
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl "http://localhost:3000/api/locations?type=province&search=กรุงเทพ"
|
|
```
|
|
|
|
**Response Format:**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"id": "loc-001",
|
|
"branchId": "head-office",
|
|
"code": "TH-10",
|
|
"nameTh": "กรุงเทพมหานคร",
|
|
"nameEn": "Bangkok",
|
|
"type": "province",
|
|
"parentId": "country-th-id",
|
|
"isActive": true,
|
|
"createdAt": "2024-01-15T09:00:00Z",
|
|
"updatedAt": "2024-01-15T09:00:00Z"
|
|
}
|
|
],
|
|
"count": 1,
|
|
"message": "Found 1 location(s)"
|
|
}
|
|
```
|
|
|
|
#### Get Locations by Type
|
|
|
|
```
|
|
GET /api/locations/type/:type
|
|
```
|
|
|
|
**Parameters:**
|
|
|
|
- `type` (path parameter): `country`, `province`, `district`, or `subdistrict`
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl http://localhost:3000/api/locations/type/province
|
|
```
|
|
|
|
#### Get Single Location
|
|
|
|
```
|
|
GET /api/locations/:id
|
|
```
|
|
|
|
#### Create Location
|
|
|
|
```
|
|
POST /api/locations
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{
|
|
"code": "TH-10",
|
|
"nameTh": "กรุงเทพมหานคร",
|
|
"nameEn": "Bangkok",
|
|
"type": "province",
|
|
"parentId": "country-th-id"
|
|
}
|
|
```
|
|
|
|
#### Update Location
|
|
|
|
```
|
|
PUT /api/locations/:id
|
|
```
|
|
|
|
#### Delete Location
|
|
|
|
```
|
|
DELETE /api/locations/:id
|
|
```
|
|
|
|
#### Toggle Active Status
|
|
|
|
```
|
|
PATCH /api/locations/:id/toggle
|
|
```
|
|
|
|
---
|
|
|
|
### Industrial Estates API
|
|
|
|
#### Get All Industrial Estates
|
|
|
|
```
|
|
GET /api/industrial-estates
|
|
```
|
|
|
|
**Query Parameters:**
|
|
|
|
- `locationId` (optional): Filter by location ID
|
|
- `isActive` (optional): Filter by active status
|
|
- `search` (optional): Search in code, nameTh, or nameEn
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl "http://localhost:3000/api/industrial-estates?locationId=th-10&isActive=true"
|
|
```
|
|
|
|
**Response Format:**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"id": "ie-001",
|
|
"branchId": "head-office",
|
|
"code": "BPL",
|
|
"nameTh": "นิคมอุตสาหกรรมบางพลี",
|
|
"nameEn": "Bangpoo Industrial Estate",
|
|
"locationId": "th-10",
|
|
"latitude": 13.5991,
|
|
"longitude": 100.7015,
|
|
"isActive": true,
|
|
"createdAt": "2024-01-15T09:00:00Z",
|
|
"updatedAt": "2024-01-15T09:00:00Z"
|
|
}
|
|
],
|
|
"count": 1,
|
|
"message": "Found 1 industrial estate(s)"
|
|
}
|
|
```
|
|
|
|
#### Get Industrial Estates by Location
|
|
|
|
```
|
|
GET /api/industrial-estates/location/:locationId
|
|
```
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl http://localhost:3000/api/industrial-estates/location/th-10
|
|
```
|
|
|
|
#### Get Single Industrial Estate
|
|
|
|
```
|
|
GET /api/industrial-estates/:id
|
|
```
|
|
|
|
#### Create Industrial Estate
|
|
|
|
```
|
|
POST /api/industrial-estates
|
|
```
|
|
|
|
**Request Body:**
|
|
|
|
```json
|
|
{
|
|
"code": "BPL",
|
|
"nameTh": "นิคมอุตสาหกรรมบางพลี",
|
|
"nameEn": "Bangpoo Industrial Estate",
|
|
"locationId": "th-10",
|
|
"latitude": 13.5991,
|
|
"longitude": 100.7015
|
|
}
|
|
```
|
|
|
|
#### Update Industrial Estate
|
|
|
|
```
|
|
PUT /api/industrial-estates/:id
|
|
```
|
|
|
|
#### Delete Industrial Estate
|
|
|
|
```
|
|
DELETE /api/industrial-estates/:id
|
|
```
|
|
|
|
#### Toggle Active Status
|
|
|
|
```
|
|
PATCH /api/industrial-estates/:id/toggle
|
|
```
|
|
|
|
---
|
|
|
|
### Audit Logs API
|
|
|
|
**Note:** This API requires Admin/Superadmin/Auditor access level.
|
|
|
|
#### Get All Audit Logs
|
|
|
|
```
|
|
GET /api/audit-logs
|
|
```
|
|
|
|
**Query Parameters:**
|
|
|
|
- `startDate` (optional): Filter logs from this date (ISO 8601 format)
|
|
- `endDate` (optional): Filter logs until this date (ISO 8601 format)
|
|
- `action` (optional): Filter by action type (`CREATE`, `UPDATE`, `DELETE`, `READ`)
|
|
- `entityType` (optional): Filter by entity type (`customer`, `quotation`, `location`, etc.)
|
|
- `limit` (optional): Number of results to return (default: 50)
|
|
- `offset` (optional): Number of results to skip (for pagination)
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl "http://localhost:3000/api/audit-logs?action=CREATE&limit=10"
|
|
```
|
|
|
|
**Response Format:**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": [
|
|
{
|
|
"id": "audit-001",
|
|
"branchId": "branch-01",
|
|
"userId": "user-123",
|
|
"actorId": "user-123",
|
|
"entityType": "customer",
|
|
"entityId": "cust-001",
|
|
"action": "CREATE",
|
|
"actionTh": "สร้าง",
|
|
"oldValues": null,
|
|
"newValues": {
|
|
"name": "สมชาย ใจดี",
|
|
"email": "somchai@example.com"
|
|
},
|
|
"ipAddress": "192.168.1.100",
|
|
"userAgent": "Mozilla/5.0...",
|
|
"createdAt": "2024-01-15T09:00:00Z"
|
|
}
|
|
],
|
|
"count": 1,
|
|
"message": "Found 1 audit log(s)"
|
|
}
|
|
```
|
|
|
|
#### Get Audit Log Statistics
|
|
|
|
```
|
|
GET /api/audit-logs/stats
|
|
```
|
|
|
|
**Response Format:**
|
|
|
|
```json
|
|
{
|
|
"success": true,
|
|
"data": {
|
|
"totalLogs": 1250,
|
|
"byAction": {
|
|
"CREATE": 350,
|
|
"UPDATE": 500,
|
|
"DELETE": 150,
|
|
"READ": 250
|
|
},
|
|
"byEntityType": {
|
|
"customer": 400,
|
|
"quotation": 300,
|
|
"location": 200,
|
|
"industrial_estate": 100,
|
|
"master_option": 250
|
|
},
|
|
"todayCount": 45,
|
|
"thisWeekCount": 320
|
|
}
|
|
}
|
|
```
|
|
|
|
#### Get Logs by Entity
|
|
|
|
```
|
|
GET /api/audit-logs/entity/:entityType/:entityId
|
|
```
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl http://localhost:3000/api/audit-logs/entity/customer/cust-001
|
|
```
|
|
|
|
#### Get Logs by User
|
|
|
|
```
|
|
GET /api/audit-logs/user/:userId
|
|
```
|
|
|
|
**Example:**
|
|
|
|
```bash
|
|
curl http://localhost:3000/api/audit-logs/user/user-123
|
|
```
|
|
|
|
#### Get Single Audit Log
|
|
|
|
```
|
|
GET /api/audit-logs/:id
|
|
```
|
|
|
|
---
|
|
|
|
## Available Data
|
|
|
|
### Customers
|
|
|
|
- `branch-01`: 4 customers (3 active, 1 pending)
|
|
- `branch-02`: 3 customers (1 active, 1 inactive, 1 pending)
|
|
- `head-office`: 3 customers (all active)
|
|
|
|
### Quotations
|
|
|
|
- `branch-01`: 2 quotations (1 sent, 1 accepted)
|
|
- `branch-02`: 1 quotation (draft)
|
|
- `head-office`: 1 quotation (sent)
|
|
|
|
### Master Options
|
|
|
|
- Categories: `customer_type`, `payment_method`, `industry`, `lead_source`
|
|
- Each category has multiple options with Thai/English names
|
|
|
|
### Locations
|
|
|
|
- Countries: Thailand, etc.
|
|
- Provinces: All Thai provinces
|
|
- Districts/Subdistricts: Hierarchical data structure
|
|
|
|
### Industrial Estates
|
|
|
|
- Multiple industrial estates across Thailand
|
|
- Linked to locations with GPS coordinates
|
|
|
|
### Audit Logs
|
|
|
|
- Complete audit trail for all operations
|
|
- Admin-only access
|
|
|
|
## Testing with Browser
|
|
|
|
Simply open these URLs in your browser:
|
|
|
|
### Customers
|
|
|
|
- http://localhost:3000/api/customers/branch-01
|
|
- http://localhost:3000/api/customers/branch-02?status=active
|
|
- http://localhost:3000/api/customers/head-office
|
|
|
|
### Quotations
|
|
|
|
- http://localhost:3000/api/quotations/branch-01
|
|
- http://localhost:3000/api/quotations/head-office?status=sent
|
|
|
|
### Master Options
|
|
|
|
- http://localhost:3000/api/master-options
|
|
- http://localhost:3000/api/master-options?category=customer_type
|
|
|
|
### Locations
|
|
|
|
- http://localhost:3000/api/locations
|
|
- http://localhost:3000/api/locations/type/province
|
|
- http://localhost:3000/api/locations?search=กรุงเทพ
|
|
|
|
### Industrial Estates
|
|
|
|
- http://localhost:3000/api/industrial-estates
|
|
- http://localhost:3000/api/industrial-estates?isActive=true
|
|
|
|
### Audit Logs (Admin only)
|
|
|
|
- http://localhost:3000/api/audit-logs
|
|
- http://localhost:3000/api/audit-logs/stats
|
|
|
|
## Project Structure
|
|
|
|
This project follows the **Feature-based MVC pattern** as recommended by ElysiaJS:
|
|
|
|
```
|
|
src/
|
|
├── app/
|
|
│ └── api/
|
|
│ └── [[...slugs]]/
|
|
│ └── route.ts # Main API entry point
|
|
├── modules/
|
|
│ ├── customers/
|
|
│ │ ├── controller.ts # HTTP handlers & routing
|
|
│ │ ├── service.ts # Business logic
|
|
│ │ └── model.ts # Schemas & validation
|
|
│ ├── quotations/
|
|
│ │ ├── controller.ts # HTTP handlers & routing
|
|
│ │ ├── service.ts # Business logic
|
|
│ │ └── model.ts # Schemas & validation
|
|
│ ├── master-options/
|
|
│ │ ├── controller.ts # HTTP handlers & routing
|
|
│ │ ├── service.ts # Business logic
|
|
│ │ └── model.ts # Schemas & validation
|
|
│ ├── locations/
|
|
│ │ ├── controller.ts # HTTP handlers & routing
|
|
│ │ ├── service.ts # Business logic
|
|
│ │ └── model.ts # Schemas & validation
|
|
│ ├── industrial-estates/
|
|
│ │ ├── controller.ts # HTTP handlers & routing
|
|
│ │ ├── service.ts # Business logic
|
|
│ │ └── model.ts # Schemas & validation
|
|
│ └── audit-logs/
|
|
│ ├── controller.ts # HTTP handlers & routing
|
|
│ ├── service.ts # Business logic
|
|
│ └── model.ts # Schemas & validation
|
|
├── types/
|
|
│ └── customer.ts # Shared types
|
|
├── lib/
|
|
│ └── mock-data.ts # Mock data
|
|
└── database/
|
|
└── schema.ts # Drizzle ORM schema
|
|
```
|
|
|
|
### File Responsibilities
|
|
|
|
#### Model (`model.ts`)
|
|
|
|
- Define TypeBox schemas for validation
|
|
- Export TypeScript types from schemas
|
|
- All data structure definitions
|
|
|
|
#### Service (`service.ts`)
|
|
|
|
- Business logic and data operations
|
|
- Pure functions (no Elysia dependencies)
|
|
- CRUD operations
|
|
- Data transformation
|
|
|
|
#### Controller (`controller.ts`)
|
|
|
|
- Elysia instance for the module
|
|
- Route definitions and handlers
|
|
- Request/response validation
|
|
- Calls service functions
|
|
- HTTP-specific concerns
|
|
|
|
#### Main Route (`app/api/[[...slugs]]/route.ts`)
|
|
|
|
- Import all controllers
|
|
- Combine with `.use()`
|
|
- Export handlers for Next.js
|
|
|
|
### Important Implementation Notes
|
|
|
|
This project follows the **correct ElysiaJS + Next.js integration pattern**:
|
|
|
|
- ✅ Single route file `[[...slugs]]/route.ts` with Elysia internal routing
|
|
- ✅ Uses `export const GET = app.fetch` (not `.handle`)
|
|
- ✅ Elysia instance has `prefix: '/api'`
|
|
- ✅ All routes defined within Elysia instances using `.get()`, `.post()`, etc.
|
|
- ✅ WinterCG compliant - works as normal Next.js API route
|
|
- ✅ Feature-based MVC pattern for maintainability
|
|
- ✅ Clear separation of concerns between Model, View, and Controller
|
|
- ✅ Branch-level data scoping for multi-tenant architecture
|
|
- ✅ Audit logging for all operations
|
|
- ✅ Soft delete with `deletedAt` field
|
|
- ✅ Multi-language support (Thai/English)
|
|
|
|
## Technologies Used
|
|
|
|
- **ElysiaJS**: Type-safe, high-performance web framework
|
|
- **Next.js 16**: React framework with App Router
|
|
- **TypeScript**: Type safety throughout
|
|
- **TypeBox**: Schema validation (via `@elysiajs/schema`)
|
|
- **Drizzle ORM**: Type-safe SQL ORM
|
|
- **PostgreSQL**: Primary database
|
|
|
|
## Features
|
|
|
|
✅ Feature-based MVC architecture
|
|
✅ Dynamic branch parameter support
|
|
✅ Type-safe request/response validation
|
|
✅ Optional query parameter filtering
|
|
✅ Mock data for customers and quotations
|
|
✅ Full TypeScript support
|
|
✅ Auto-generated API documentation (Swagger/OpenAPI ready)
|
|
✅ Correct ElysiaJS + Next.js integration pattern
|
|
✅ Scalable and maintainable code structure
|
|
✅ Clear separation of concerns
|
|
✅ Multi-tenant architecture with branch scoping
|
|
✅ Complete audit logging system
|
|
✅ Soft delete for data integrity
|
|
✅ Multi-language support (Thai/English)
|
|
✅ Hierarchical data structures (locations)
|
|
✅ GPS coordinate support (industrial estates)
|
|
✅ Admin-only access control (audit logs)
|
|
|
|
## Adding New Modules
|
|
|
|
To add a new module (e.g., `products`):
|
|
|
|
1. Create folder: `src/modules/products/`
|
|
2. Create `model.ts` - Define schemas
|
|
3. Create `service.ts` - Business logic
|
|
4. Create `controller.ts` - Routes and handlers
|
|
5. Create `index.ts` - Module exports
|
|
6. Update `src/app/api/[[...slugs]]/route.ts`:
|
|
|
|
```typescript
|
|
import { products } from "@/modules/products/controller";
|
|
|
|
const app = new Elysia({ prefix: "/api" })
|
|
.use(customers)
|
|
.use(quotations)
|
|
.use(masterOptions)
|
|
.use(locations)
|
|
.use(industrialEstates)
|
|
.use(auditLogs)
|
|
.use(products); // Add new module
|
|
```
|
|
|
|
## Security & Access Control
|
|
|
|
### Branch Middleware
|
|
|
|
All routes use `branchMiddleware` which injects:
|
|
|
|
- `currentBranchId` - Current user's branch
|
|
- `userId` - Current user ID
|
|
- `userGroups` - User groups/roles
|
|
- `accessibleBranches` - Branches user can access
|
|
|
|
### Permission Levels
|
|
|
|
- **Standard Users**: Access to branch-scoped data
|
|
- **Admin/Superadmin**: Full access + audit logs
|
|
- **Auditor**: Read-only access to audit logs
|
|
|
|
### Data Isolation
|
|
|
|
- All queries are automatically filtered by `branchId`
|
|
- Cross-branch access is prevented
|
|
- Soft delete ensures data integrity
|