Files
lcbp3/docs/20251224-document-numbering-summary.md
admin cd73cc1549
Some checks failed
Spec Validation / validate-markdown (push) Has been cancelled
Spec Validation / validate-diagrams (push) Has been cancelled
Spec Validation / check-todos (push) Has been cancelled
251225:1703 On going update to 1.7.0: Refoctory drawing Module not finish
2025-12-25 17:03:33 +07:00

16 KiB
Raw Blame History

📋 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

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)

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

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)

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

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

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


📝 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