# 📋 Document Numbering System Summary

> **Version:** v1.7.0
> **Last Updated:** 2025-12-24
> **Status:** Implemented (with known build issues)

---

## 📊 Architecture Overview

ระบบ Document Numbering ใช้สำหรับสร้างเลขที่เอกสารอัตโนมัติ โดยมี **Reserve-Confirm Pattern** และ **Two-Phase Locking** (Redis + DB Optimistic Lock) เพื่อป้องกัน Race Conditions

```mermaid
flowchart TB
    subgraph Frontend["Frontend (Next.js)"]
        A[lib/api/numbering.ts]
        B[components/numbering/*]
        C[types/dto/numbering.dto.ts]
    end

    subgraph Backend["Backend (NestJS)"]
        D[Controllers]
        E[DocumentNumberingService]
        F[Sub-Services]
        G[Entities]
    end

    A --> D
    B --> A
    E --> F
    E --> G
```

---

## 📁 Backend Structure

### Module Location
`backend/src/modules/document-numbering/`

| Directory      | Files | Description                                                                         |
| -------------- | ----- | ----------------------------------------------------------------------------------- |
| `controllers/` | 3     | Public, Admin, Metrics Controllers                                                  |
| `services/`    | 8     | Main + Counter, Reservation, Format, Lock, Template, Audit, Metrics, ManualOverride |
| `entities/`    | 5     | Format, Counter, Reservation, Audit, Error                                          |
| `dto/`         | 5     | Preview, Reserve, ConfirmReservation, CounterKey, ManualOverride                    |
| `interfaces/`  | 1     | GenerateNumberContext                                                               |

### Key Services

| Service                        | Responsibility                                                       |
| ------------------------------ | -------------------------------------------------------------------- |
| `DocumentNumberingService`     | Main orchestrator (generateNextNumber, reserveNumber, previewNumber) |
| `CounterService`               | Increment counter with Optimistic Lock                               |
| `ReservationService`           | Reserve-Confirm pattern handling                                     |
| `FormatService`                | Token replacement & format resolution                                |
| `DocumentNumberingLockService` | Redis distributed lock (Redlock)                                     |
| `ManualOverrideService`        | Admin counter override                                               |
| `AuditService`                 | Audit logging                                                        |
| `MetricsService`               | Prometheus metrics                                                   |

---

## 📁 Frontend Structure

### Files

| Path                                         | Description                    |
| -------------------------------------------- | ------------------------------ |
| `lib/api/numbering.ts`                       | API client + Types (335 lines) |
| `lib/services/document-numbering.service.ts` | Service wrapper                |
| `types/dto/numbering.dto.ts`                 | DTOs for forms                 |
| `types/numbering.ts`                         | Type re-exports                |

### Components (`components/numbering/`)

| Component                  | Description                 |
| -------------------------- | --------------------------- |
| `template-editor.tsx`      | Editor for format templates |
| `template-tester.tsx`      | Test number generation      |
| `sequence-viewer.tsx`      | View counter sequences      |
| `metrics-dashboard.tsx`    | Audit/Error logs dashboard  |
| `manual-override-form.tsx` | Admin counter override      |
| `void-replace-form.tsx`    | Void & Replace number       |
| `cancel-number-form.tsx`   | Cancel/Skip a number        |
| `bulk-import-form.tsx`     | Bulk import counters        |
| `audit-logs-table.tsx`     | Audit logs table            |

### Admin Pages
- `app/(admin)/admin/numbering/` - Template management
- `app/(admin)/admin/system-logs/numbering/` - System logs

---

## 💾 Database Schema (v1.7.0)

### 5 Tables

| Table                          | Purpose                   | Key Feature                                 |
| ------------------------------ | ------------------------- | ------------------------------------------- |
| `document_number_formats`      | Template รูปแบบเลขที่เอกสาร  | Unique per (project, correspondence_type)   |
| `document_number_counters`     | Running Number Counter    | **8-Column Composite PK** + Optimistic Lock |
| `document_number_audit`        | Audit Trail สำหรับทุกการสร้าง | เก็บ ≥ 7 ปี                                   |
| `document_number_errors`       | Error Log                 | 5 Error Types                               |
| `document_number_reservations` | **Two-Phase Commit**      | Reserve → Confirm Pattern                   |

---

## 🔑 Counter Composite Primary Key (8 Columns)

```sql
PRIMARY KEY (
  project_id,
  originator_organization_id,
  recipient_organization_id,    -- 0 = no recipient (RFA)
  correspondence_type_id,
  sub_type_id,                  -- 0 = ไม่ระบุ (for TRANSMITTAL)
  rfa_type_id,                  -- 0 = ไม่ใช่ RFA
  discipline_id,                -- 0 = ไม่ระบุ
  reset_scope                   -- 'YEAR_2024', 'NONE', etc.
)
```

### Reset Scope Values

| Value           | Description                      |
| --------------- | -------------------------------- |
| `YEAR_XXXX`     | Reset ทุกปี เช่น `YEAR_2024`        |
| `MONTH_XXXX_XX` | Reset ทุกเดือน เช่น `MONTH_2024_01` |
| `CONTRACT_XXXX` | Reset ต่อสัญญา                     |
| `NONE`          | ไม่ Reset                         |

### Constraints

```sql
CONSTRAINT chk_last_number_positive CHECK (last_number >= 0)
CONSTRAINT chk_reset_scope_format CHECK (
  reset_scope IN ('NONE')
  OR reset_scope LIKE 'YEAR_%'
  OR reset_scope LIKE 'MONTH_%'
  OR reset_scope LIKE 'CONTRACT_%'
)
```

---

## 📜 Business Rules

### 1️⃣ Number Generation Rules

| Rule                          | Description                                          |
| ----------------------------- | ---------------------------------------------------- |
| **Uniqueness**                | เลขที่เอกสารห้ามซ้ำกันภายใน Project                        |
| **Sequence Reset**            | Reset ตาม `reset_scope` (ปกติ Reset ต่อปี)              |
| **Idempotency**               | ใช้ `Idempotency-Key` header ป้องกันการสร้างซ้ำ            |
| **Race Condition Prevention** | Redis Lock (Primary) + DB Optimistic Lock (Fallback) |
| **Format Fallback**           | ใช้ Default Format ถ้าไม่มี Specific Format              |

### 2️⃣ Two-Phase Commit (Reserve → Confirm)

```mermaid
stateDiagram-v2
    [*] --> RESERVED: Reserve Number
    RESERVED --> CONFIRMED: Confirm (Save Document)
    RESERVED --> CANCELLED: Cancel / Timeout (15 min)
    CONFIRMED --> VOID: Admin Void
    VOID --> [*]
    CANCELLED --> [*]
```

| Status      | Description                         |
| ----------- | ----------------------------------- |
| `RESERVED`  | จองแล้ว รอ Confirm (หมดอายุใน 15 นาที) |
| `CONFIRMED` | ยืนยันแล้ว ใช้งานจริง                    |
| `CANCELLED` | ยกเลิก (User/System/Timeout)         |
| `VOID`      | Admin Void (ยกเลิกเลขที่หลัง Confirm)   |

### 3️⃣ Format Template Tokens

| Token          | Example Value | Description                  |
| -------------- | ------------- | ---------------------------- |
| `{PROJECT}`    | `LCBP3`       | Project Code                 |
| `{ORG}`        | `NAP`         | Originator Organization Code |
| `{RECIPIENT}`  | `PAT`         | Recipient Organization Code  |
| `{TYPE}`       | `LET`         | Correspondence Type Code     |
| `{DISCIPLINE}` | `STR`         | Discipline Code              |
| `{SEQ:N}`      | `0001`        | Sequence padded to N digits  |
| `{YEAR}`       | `2025`        | 4-digit CE Year              |
| `{YEAR:BE}`    | `2568`        | 4-digit Buddhist Era Year    |
| `{REV}`        | `0`           | Revision Number              |

### Example Format

```
Template: {ORG}-{RECIPIENT}-{TYPE}-{YEAR:BE}-{SEQ:4}
Result:   NAP-PAT-LET-67-0001
```

### 4️⃣ Format Resolution Priority

1. **Specific Format**: project_id + correspondence_type_id
2. **Default Format**: project_id + correspondence_type_id = NULL
3. **Fallback**: `{ORG}-{RECIPIENT}-{SEQ:4}-{YEAR:BE}`

---

## 🛡️ Concurrency Control Strategy

```mermaid
sequenceDiagram
    participant API
    participant Redis
    participant DB

    API->>Redis: Acquire Lock (TTL: 5s)
    alt Redis Lock Success
        API->>DB: SELECT counter + UPDATE (increment)
        API->>Redis: Release Lock
    else Redis Lock Failed/Timeout
        Note over API,DB: Fallback to DB Optimistic Lock
        API->>DB: SELECT FOR UPDATE + INCREMENT
        API->>DB: Check version (Optimistic Lock)
    end
```

| Strategy               | Use Case                                    |
| ---------------------- | ------------------------------------------- |
| **Redis Redlock**      | Primary - Distributed Lock across instances |
| **DB Optimistic Lock** | Fallback - When Redis down/timeout          |
| **Version Column**     | Prevent concurrent updates                  |

---

## 🔄 Generation Flow

```mermaid
sequenceDiagram
    participant Client
    participant Controller
    participant Service
    participant RedisLock
    participant CounterService
    participant FormatService
    participant DB

    Client->>Controller: POST /preview or Reserve
    Controller->>Service: generateNextNumber(ctx)
    Service->>RedisLock: acquireLock(counterKey)
    Service->>CounterService: incrementCounter(key)
    CounterService->>DB: SELECT FOR UPDATE + INCREMENT
    DB-->>CounterService: sequence
    CounterService-->>Service: sequence
    Service->>FormatService: format(options)
    FormatService->>DB: Lookup (Project, Type, Org, Discipline)
    FormatService-->>Service: formattedNumber
    Service->>DB: save AuditLog
    Service->>RedisLock: releaseLock()
    Service-->>Controller: { number, auditId }
    Controller-->>Client: Response
```

---

## 🔌 API Endpoints

### Public (`/document-numbering`)

| Method | Endpoint        | Permission               | Description                 |
| ------ | --------------- | ------------------------ | --------------------------- |
| POST   | `/preview`      | `correspondence.read`    | Preview เลขที่ (ไม่ increment) |
| GET    | `/sequences`    | `correspondence.read`    | ดู Counter ทั้งหมด             |
| GET    | `/logs/audit`   | `system.view_logs`       | Audit Logs                  |
| GET    | `/logs/errors`  | `system.view_logs`       | Error Logs                  |
| PATCH  | `/counters/:id` | `system.manage_settings` | Update Counter (Deprecated) |

### Admin (`/admin/document-numbering`)

| Method | Endpoint                 | Description                 |
| ------ | ------------------------ | --------------------------- |
| GET    | `/templates`             | ดู Templates ทั้งหมด           |
| GET    | `/templates?projectId=X` | ดู Templates ตาม Project     |
| POST   | `/templates`             | สร้าง/แก้ไข Template          |
| DELETE | `/templates/:id`         | ลบ Template                 |
| GET    | `/metrics`               | Audit + Error Logs combined |
| POST   | `/manual-override`       | Override Counter Value      |
| POST   | `/void-and-replace`      | Void + สร้างเลขใหม่           |
| POST   | `/cancel`                | ยกเลิกเลขที่                   |
| POST   | `/bulk-import`           | Import Counters จาก Legacy  |

---

## 📈 Audit & Monitoring

### Audit Log Operations

| Operation         | Description        |
| ----------------- | ------------------ |
| `RESERVE`         | จองเลขที่            |
| `CONFIRM`         | ยืนยันการใช้เลขที่      |
| `MANUAL_OVERRIDE` | Admin แก้ไข Counter |
| `VOID_REPLACE`    | Void และสร้างใหม่    |
| `CANCEL`          | ยกเลิกเลขที่          |

### Audit Log Fields

| Field               | Description                   |
| ------------------- | ----------------------------- |
| `counter_key`       | JSON 8 fields (Composite Key) |
| `reservation_token` | UUID v4 สำหรับ Reserve-Confirm  |
| `idempotency_key`   | Request Idempotency Key       |
| `template_used`     | Format Template ที่ใช้           |
| `retry_count`       | จำนวนครั้งที่ retry                |
| `lock_wait_ms`      | เวลารอ Redis lock (ms)        |
| `total_duration_ms` | เวลารวมทั้งหมด (ms)             |
| `fallback_used`     | NONE / DB_LOCK / RETRY        |

### Error Types

| Type               | Description                     |
| ------------------ | ------------------------------- |
| `LOCK_TIMEOUT`     | Redis lock หมดเวลา              |
| `VERSION_CONFLICT` | Optimistic lock fail            |
| `DB_ERROR`         | Database error                  |
| `REDIS_ERROR`      | Redis connection error          |
| `VALIDATION_ERROR` | Template/Input validation error |

### Prometheus Metrics

| Metric                           | Type      | Description                   |
| -------------------------------- | --------- | ----------------------------- |
| `numbering_sequences_total`      | Counter   | Total sequences generated     |
| `numbering_sequence_utilization` | Gauge     | Utilization of sequence space |
| `numbering_lock_wait_seconds`    | Histogram | Time waiting for locks        |
| `numbering_lock_failures_total`  | Counter   | Lock acquisition failures     |

---

## 🔐 Permissions

| Permission               | Description                                   |
| ------------------------ | --------------------------------------------- |
| `correspondence.read`    | Preview, View Sequences                       |
| `system.view_logs`       | View Audit/Error Logs                         |
| `system.manage_settings` | Template CRUD, Override, Void, Cancel, Import |

---

## ⚠️ Known Issues (Current Build)

### TypeScript Errors

1. **DTO Field Mismatch**
   - `PreviewNumberDto.originatorId` vs Service expects `originatorOrganizationId`

2. **Missing Properties in PreviewNumberDto**
   - `correspondenceTypeId` (used as `typeId`)
   - `customTokens`

3. **TypeScript Initializers**
   - DTOs need `!` or default values for strict mode

### Files Needing Fix

- `dto/preview-number.dto.ts`
- `dto/reserve-number.dto.ts`
- `dto/confirm-reservation.dto.ts`
- `dto/counter-key.dto.ts`
- `entities/document-number-format.entity.ts`
- `entities/document-number-error.entity.ts`
- `services/document-numbering.service.ts`

---

## 📚 Related Documentation

- [specs/01-requirements/03.11-document-numbering.md](../specs/01-requirements/03.11-document-numbering.md)
- [specs/03-implementation/document-numbering.md](../specs/03-implementation/document-numbering.md)
- [specs/07-database/data-dictionary-v1.7.0.md](../specs/07-database/data-dictionary-v1.7.0.md)
- [specs/07-database/lcbp3-v1.7.0-schema.sql](../specs/07-database/lcbp3-v1.7.0-schema.sql)

---

## 📝 Changelog

### v1.7.0
- Changed `document_number_counters` PK from 5 to **8 columns**
- Added `document_number_reservations` table for Two-Phase Commit
- Added `reset_scope` field (replaces `current_year`)
- Enhanced `document_number_audit` with operation tracking
- Added `idempotency_key` support

### v1.5.1
- Initial implementation
- Basic format templating
- Counter management

---

**End of Document**
