251202:1300
This commit is contained in:
@@ -1,69 +1,296 @@
|
||||
# 3.11 Document Numbering Management (การจัดการเลขที่เอกสาร)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: Document Numbering Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
last_updated: 2025-12-02
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
- specs/04-data-dictionary/4_Data_Dictionary_V1_4_4.md
|
||||
---
|
||||
|
||||
## 3.11.1. วัตถุประสงค์
|
||||
|
||||
- ระบบต้องสามารถสร้างเลขที่เอกสาร (Running Number) ได้โดยอัตโนมัติและยืดหยุ่นสูง
|
||||
- ระบต้องสามารถกำหนด รูปแบบ(template) เลขที่เอกสารได้ สำหรับแต่ละโครงการ, ชนิดเอกสาร, ประเภทเอกสาร
|
||||
- ระบบต้องสามารถกำหนดรูปแบบ (template) เลขที่เอกสารได้ สำหรับแต่ละโครงการ, ชนิดเอกสาร, ประเภทเอกสาร
|
||||
- ระบบต้องรับประกัน Uniqueness ของเลขที่เอกสารในทุกสถานการณ์
|
||||
- ระบบต้องรองรับการทำงานแบบ concurrent ได้อย่างปลอดภัย
|
||||
|
||||
## 3.11.2. Logic การนับเลข (Counter Logic)
|
||||
|
||||
- การนับเลขจะต้องรองรับการแยกตาม Key ที่ซับซ้อนขึ้น ตามแต่ละ รูปแบบ(template) ได้
|
||||
การนับเลขจะแยกตาม **Counter Key** ที่ประกอบด้วย:
|
||||
|
||||
## 3.11.3. Format Template
|
||||
- `project_id` - รหัสโครงการ
|
||||
- `doc_type_id` - ชนิดเอกสาร (Correspondence, RFA, Transmittal, Drawing)
|
||||
- `sub_type_id` - ประเภทย่อยของเอกสาร (nullable)
|
||||
- `discipline_id` - สาขาวิชา/งาน (nullable)
|
||||
- `year` - ปี พ.ศ. หรือ ค.ศ. ตามที่กำหนดใน template
|
||||
|
||||
- รองรับการกำหนดรูปแบบด้วย Token Replacement
|
||||
- transmittal to owner:
|
||||
- {ORG}-{ORG}-{TYPE}-{SEQ:4}-{YEAR B.D.} -> คคง.-สคฉ.3-03-21-0117-2568
|
||||
- other transmittal:
|
||||
- {ORG}-{ORG}-{TYPE}-{SEQ:4}-{YEAR B.D.} -> ผรม.2-คคง.-0117-2568
|
||||
- RFA:
|
||||
- {PROJECT}-{ORG}-{TYPE}-{DISCIPLINE}-{SEQ:4}-{REV} -> LCBP3-C2-RFI-ROW-0029-A
|
||||
- Correspondence type LETTER:
|
||||
- {ORG}-{ORG}-{TYPE}-{SEQ:4}-{YEAR B.D.} -> คคง.-สคฉ.3-0985-2568
|
||||
- Correspondence รองรับ Token: {ORG}-{ORG}-{TYPE}-{SEQ:4}-{YEAR B.D.} -> คคง.-สคฉ.3-STR-0001-2568
|
||||
- RFA รองรับ Token: {PROJECT}-{ORG}-{TYPE}-{DISCIPLINE}-{SEQ:4}-{REV} -> TEAM-RFA-STR-0001-A
|
||||
- Transmittal รองรับ Token: {PROJECT}-{ORG}-{TYPE}-{DISCIPLINE}-{SEQ:4}-{REV} -> TEAM-TR-STR-0001-A
|
||||
### ตัวอย่าง Counter Key
|
||||
|
||||
## 3.11.4. Transmittal Logic
|
||||
```text
|
||||
Correspondence: project_id + doc_type_id + sub_type_id + year
|
||||
RFA: project_id + doc_type_id + discipline_id + year
|
||||
Transmittal: project_id + doc_type_id + recipient_type + year
|
||||
Drawing: project_id + doc_type_id + discipline_id + year
|
||||
```
|
||||
|
||||
- รองรับเงื่อนไขพิเศษสำหรับ Transmittal ที่เลขอาจเปลี่ยนตามผู้รับ (To Owner vs To Contractor)
|
||||
### Fallback สำหรับค่า NULL
|
||||
|
||||
## 3.11.5. กลไกความปลอดภัย
|
||||
- กรณีที่ `discipline_id` หรือ `sub_type_id` เป็น NULL ให้ใช้ค่า Default `0` ในการจัดกลุ่ม Counter
|
||||
- ป้องกัน Error และรับประกันความถูกต้องของ Running Number (Uniqueness Guarantee)
|
||||
|
||||
- ยังคงใช้ Redis Distributed Lock และ Optimistic Locking เพื่อป้องกันเลขซ้ำหรือข้าม
|
||||
## 3.11.3. Format Templates by Document Type
|
||||
|
||||
## 3.11.6. ต้องมี retry mechanism และ fallback strategy เมื่อการ generate เลขที่เอกสารล้มเหลว
|
||||
ระบบรองรับการกำหนดรูปแบบด้วย **Token Replacement**
|
||||
|
||||
## 3.11.7. Fallback Logic (เพิ่ม)
|
||||
### 3.11.3.1. Correspondence (หนังสือราชการ)
|
||||
|
||||
- กรณีที่เอกสารประเภทนั้นไม่มี discipline_id หรือ sub_type_id (เป็นค่า NULL หรือไม่ระบุ) ให้ระบบใช้ค่า Default (เช่น 0) ในการจัดกลุ่ม Counter เพื่อป้องกัน Error และรับประกันความถูกต้องของ Running Number (Uniqueness Guarantee)
|
||||
- Scenario 1: Redis Unavailable
|
||||
- Fallback เป็น database-only locking (pessimistic lock)
|
||||
- Log warning และแจ้ง ops team
|
||||
#### Letter Type (TYPE = 03)
|
||||
|
||||
- **Template**: `{ORG}-{ORG}-{TYPE}-{SEQ:4}-{YEAR:B.E.}`
|
||||
- **Example**: `คคง.-สคฉ.3-0985-2568`
|
||||
- **Counter Key**: `project_id + doc_type_id + sub_type_id + year`
|
||||
|
||||
#### Other Correspondence Types
|
||||
|
||||
- **Template**: `{ORG}-{ORG}-{TYPE}-{SEQ:4}-{YEAR:B.E.}`
|
||||
- **Example**: `คคง.-สคฉ.3-STR-0001-2568`
|
||||
- **Counter Key**: `project_id + doc_type_id + sub_type_id + year`
|
||||
|
||||
### 3.11.3.2. Transmittal
|
||||
|
||||
#### Transmittal to Owner
|
||||
|
||||
- **Template**: `{ORG}-{ORG}-{TYPE}-{SUB_TYPE}-{SEQ:4}-{YEAR:B.E.}`
|
||||
- **Example**: `คคง.-สคฉ.3-03-21-0117-2568`
|
||||
- **Counter Key**: `project_id + doc_type_id + recipient_type + year`
|
||||
- **Note**: `recipient_type = 'OWNER'`
|
||||
|
||||
#### Transmittal to Contractor/Others
|
||||
|
||||
- **Template**: `{ORG}-{ORG}-{TYPE}-{SEQ:4}-{YEAR:B.E.}`
|
||||
- **Example**: `ผรม.2-คคง.-0117-2568`
|
||||
- **Counter Key**: `project_id + doc_type_id + recipient_type + year`
|
||||
- **Note**: `recipient_type = 'CONTRACTOR' | 'CONSULTANT' | 'OTHER'`
|
||||
|
||||
#### Alternative Project-based Format
|
||||
|
||||
- **Template**: `{PROJECT}-{ORG}-{TYPE}-{DISCIPLINE}-{SEQ:4}-{REV}`
|
||||
- **Example**: `LCBP3-TR-STR-0001-A`
|
||||
- **Counter Key**: `project_id + doc_type_id + discipline_id + year`
|
||||
|
||||
### 3.11.3.3. RFA (Request for Approval)
|
||||
|
||||
- **Template**: `{PROJECT}-{ORG}-{TYPE}-{DISCIPLINE}-{SEQ:4}-{REV}`
|
||||
- **Example**: `LCBP3-C2-RFI-ROW-0029-A`
|
||||
- **Counter Key**: `project_id + doc_type_id + discipline_id + year`
|
||||
- **Note**: `{REV}` คือ revision code (A, B, C, ..., AA, AB, ...)
|
||||
|
||||
### 3.11.3.4. Drawing
|
||||
|
||||
- **Template**: `{PROJECT}-{DISCIPLINE}-{CATEGORY}-{SEQ:4}-{REV}`
|
||||
- **Example**: `LCBP3-STR-DRW-0001-A`
|
||||
- **Counter Key**: `project_id + doc_type_id + discipline_id + category + year`
|
||||
|
||||
## 3.11.4. Supported Token Types
|
||||
|
||||
| Token | Description | Example |
|
||||
|-------|-------------|---------|
|
||||
| `{PROJECT}` | รหัสโครงการ | `LCBP3` |
|
||||
| `{ORG}` | รหัสหน่วยงาน | `คคง.`, `สคฉ.3` |
|
||||
| `{TYPE}` | รหัสชนิดเอกสาร | `RFI`, `03` |
|
||||
| `{SUB_TYPE}` | รหัสประเภทย่อย | `21` |
|
||||
| `{DISCIPLINE}` | รหัสสาขาวิชา | `STR`, `ROW` |
|
||||
| `{CATEGORY}` | หมวดหมู่ | `DRW` |
|
||||
| `{SEQ:n}` | Running number (n = จำนวนหลัก) | `0001`, `0029` |
|
||||
| `{YEAR:B.E.}` | ปี พ.ศ. | `2568` |
|
||||
| `{YEAR:A.D.}` | ปี ค.ศ. | `2025` |
|
||||
| `{REV}` | Revision Code | `A`, `B`, `AA` |
|
||||
|
||||
## 3.11.5. Transmittal Special Logic
|
||||
|
||||
- Transmittal มีเงื่อนไขพิเศษที่เลขอาจเปลี่ยนตามผู้รับ:
|
||||
- **To Owner**: ใช้ format พิเศษที่มี sub_type รหัสโครงการ
|
||||
- **To Contractor/Others**: ใช้ format ทั่วไป
|
||||
- Counter Key จะแยกตาม `recipient_type` เพื่อให้แต่ละประเภทมี running number อิสระ
|
||||
|
||||
## 3.11.6. กลไกความปลอดภัย (Concurrency Control)
|
||||
|
||||
### 3.11.6.1. Redis Distributed Lock
|
||||
|
||||
- ใช้ Redis Distributed Lock เพื่อป้องกัน race condition
|
||||
- Lock key format: `lock:docnum:{project_id}:{doc_type_id}:{...counter_key_parts}`
|
||||
- Lock TTL: 5 วินาที (auto-release เมื่อ timeout)
|
||||
- Lock acquisition timeout: 10 วินาที
|
||||
|
||||
### 3.11.6.2. Optimistic Locking
|
||||
|
||||
- ใช้ `version` column ในตาราง `document_number_configs`
|
||||
- ตรวจสอบ version ก่อน update counter
|
||||
- หาก version conflict เกิดขึ้น → retry transaction
|
||||
|
||||
### 3.11.6.3. Database Constraints
|
||||
|
||||
- Unique constraint บน `document_number` column
|
||||
- Foreign key constraints เพื่อความสัมพันธ์ข้อมูล
|
||||
- Check constraints สำหรับ business rules
|
||||
|
||||
## 3.11.7. Retry Mechanism & Error Handling
|
||||
|
||||
### 3.11.7.1. Scenario 1: Redis Unavailable
|
||||
|
||||
- **Fallback**: ใช้ database-only locking (pessimistic lock)
|
||||
- **Action**:
|
||||
- ใช้ `SELECT ... FOR UPDATE` แทน Redis lock
|
||||
- Log warning พร้อม alert ops team
|
||||
- ระบบยังใช้งานได้แต่ performance ลดลง
|
||||
- Scenario 2: Lock Acquisition Timeout
|
||||
- Retry 5 ครั้งด้วย exponential backoff (1s, 2s, 4s, 8s, 16s)
|
||||
- หลัง 5 ครั้ง: Return error 503 "Service Temporarily Unavailable"
|
||||
- Frontend แสดง user-friendly message: "ระบบกำลังยุ่ง กรุณาลองใหม่ภายหลัง"
|
||||
- Scenario 3: Version Conflict After Lock
|
||||
- Retry transaction อีก 2 ครั้ง
|
||||
- หากยังล้มเหลว: Log error พร้อม context และ return 409 Conflict
|
||||
- Frontend แสดง user-friendly message: "เลขที่เอกสารถูกเปลี่ยน กรุณาลองใหม่"
|
||||
- Monitoring:
|
||||
- Alert ถ้า lock acquisition failures > 5% ใน 5 นาที
|
||||
- Dashboard แสดง lock wait time percentiles
|
||||
|
||||
### 3.11.7.2. Scenario 2: Lock Acquisition Timeout
|
||||
|
||||
- **Retry**: 5 ครั้งด้วย exponential backoff
|
||||
- Attempt 1: wait 1s
|
||||
- Attempt 2: wait 2s
|
||||
- Attempt 3: wait 4s
|
||||
- Attempt 4: wait 8s
|
||||
- Attempt 5: wait 16s (รวม ~31 วินาที)
|
||||
- **Failure**: Return HTTP 503 "Service Temporarily Unavailable"
|
||||
- **Frontend**: แสดงข้อความ "ระบบกำลังยุ่ง กรุณาลองใหม่ภายหลัง"
|
||||
|
||||
### 3.11.7.3. Scenario 3: Version Conflict After Lock
|
||||
|
||||
- **Retry**: 2 ครั้ง (reload counter + retry transaction)
|
||||
- **Failure**: Log error พร้อม context และ return HTTP 409 Conflict
|
||||
- **Frontend**: แสดงข้อความ "เลขที่เอกสารถูกเปลี่ยน กรุณาลองใหม่"
|
||||
|
||||
### 3.11.7.4. Scenario 4: Database Connection Error
|
||||
|
||||
- **Retry**: 3 ครั้งด้วย exponential backoff (1s, 2s, 4s)
|
||||
- **Failure**: Return HTTP 500 "Internal Server Error"
|
||||
- **Frontend**: แสดงข้อความ "เกิดข้อผิดพลาดในระบบ กรุณาติดต่อผู้ดูแลระบบ"
|
||||
|
||||
## 3.11.8. Configuration Management
|
||||
|
||||
### 3.11.8.1. Admin Panel Configuration
|
||||
|
||||
- Project Admin สามารถกำหนด/แก้ไข template ผ่าน Admin Panel
|
||||
- การเปลี่ยนแปลง template จะไม่ส่งผลต่อเอกสารที่สร้างไว้แล้ว
|
||||
- ต้องมีการ validate template ก่อนบันทึก (ตรวจสอบ token ที่ใช้ถูกต้อง)
|
||||
|
||||
### 3.11.8.2. Template Versioning
|
||||
|
||||
- เก็บ history ของ template changes
|
||||
- บันทึก user, timestamp, และเหตุผลในการเปลี่ยนแปลง
|
||||
- สามารถ rollback ไปเวอร์ชันก่อนหน้าได้
|
||||
|
||||
### 3.11.8.3. Counter Reset Policy
|
||||
|
||||
- Counter reset ตามปี (yearly reset)
|
||||
- Counter reset ตาม project phase (optional)
|
||||
- Admin สามารถ manual reset counter ได้ (require approval + audit log)
|
||||
|
||||
## 3.11.9. Audit Trail
|
||||
|
||||
### 3.11.9.1. การบันทึก Audit Log
|
||||
|
||||
บันทึกทุกการ generate เลขที่เอกสารใน `document_number_audit` table:
|
||||
|
||||
- `document_id` - เอกสารที่ถูกสร้าง
|
||||
- `generated_number` - เลขที่ถูกสร้าง
|
||||
- `counter_key` - key ที่ใช้ในการนับ
|
||||
- `template_used` - template ที่ใช้
|
||||
- `user_id` - ผู้ที่ request
|
||||
- `ip_address` - IP address ของผู้ request
|
||||
- `timestamp` - เวลาที่สร้าง
|
||||
- `retry_count` - จำนวนครั้งที่ retry (ถ้ามี)
|
||||
|
||||
### 3.11.9.2. Conflict & Error Logging
|
||||
|
||||
- บันทึก version conflicts และ กลไก retry ที่ใช้
|
||||
- บันทึก lock timeouts และ failure reasons
|
||||
- บันทึก fallback scenarios (เช่น Redis unavailable)
|
||||
|
||||
## 3.11.10. Performance Requirements
|
||||
|
||||
### 3.11.10.1. Response Time
|
||||
|
||||
- Document number generation ต้องเสร็จภายใน **2 วินาที** (95th percentile)
|
||||
- Document number generation ต้องเสร็จภายใน **5 วินาที** (99th percentile)
|
||||
- ในกรณี normal operation (ไม่มี retry) ควรเสร็จภายใน **500ms**
|
||||
|
||||
### 3.11.10.2. Throughput
|
||||
|
||||
- ระบบรองรับ concurrent requests อย่างน้อย **50 requests/second**
|
||||
- Peak load รองรับได้ถึง **100 requests/second** (ช่วงเวลาเร่งงาน)
|
||||
|
||||
### 3.11.10.3. Availability
|
||||
|
||||
- Uptime ≥ 99.5% (exclude planned maintenance)
|
||||
- Maximum downtime ต่อเดือน ≤ 3.6 ชั่วโมง
|
||||
|
||||
## 3.11.11. Monitoring & Alerting
|
||||
|
||||
### 3.11.11.1. Metrics to Monitor
|
||||
|
||||
- Lock acquisition time (p50, p95, p99)
|
||||
- Lock acquisition failure rate
|
||||
- Counter generation latency
|
||||
- Retry count distribution
|
||||
- Redis connection status
|
||||
- Database connection pool usage
|
||||
|
||||
### 3.11.11.2. Alert Conditions
|
||||
|
||||
- 🔴 **Critical**: Redis unavailable > 1 minute
|
||||
- 🔴 **Critical**: Lock acquisition failures > 10% in 5 minutes
|
||||
- 🟡 **Warning**: Lock acquisition failures > 5% in 5 minutes
|
||||
- 🟡 **Warning**: Average lock wait time > 1 second
|
||||
- 🟡 **Warning**: Retry count > 100 per hour
|
||||
|
||||
### 3.11.11.3. Dashboard
|
||||
|
||||
- Real-time lock acquisition success rate
|
||||
- Lock wait time percentiles (p50, p95, p99)
|
||||
- Counter generation rate (per minute)
|
||||
- Error rate breakdown (by error type)
|
||||
- Redis/Database health status
|
||||
|
||||
## 3.11.12. API Reference
|
||||
|
||||
เอกสารนี้อ้างอิงถึง API endpoints ต่อไปนี้ (รายละเอียดใน `specs/02-architecture/api-design.md`):
|
||||
|
||||
- `POST /api/v1/documents/{documentId}/generate-number` - สร้างเลขที่เอกสาร
|
||||
- `GET /api/v1/document-numbering/configs` - ดูการตั้งค่า template
|
||||
- `PUT /api/v1/document-numbering/configs/{configId}` - แก้ไข template (Admin only)
|
||||
- `POST /api/v1/document-numbering/configs/{configId}/reset-counter` - Reset counter (Admin only)
|
||||
|
||||
## 3.11.13. Database Schema Reference
|
||||
|
||||
เอกสารนี้อ้างอิงถึง tables ต่อไปนี้ (รายละเอียดใน `specs/04-data-dictionary/4_Data_Dictionary_V1_4_4.md`):
|
||||
|
||||
- `document_number_configs` - เก็บ template และ counter configuration
|
||||
- `document_number_counters` - เก็บ current counter value
|
||||
- `document_number_audit` - เก็บ audit trail
|
||||
- `documents` - เก็บ document number ที่ถูกสร้าง
|
||||
|
||||
## 3.11.14. Security Considerations
|
||||
|
||||
### 3.11.14.1. Authorization
|
||||
|
||||
- เฉพาะ authenticated users เท่านั้นที่สามารถ request document number
|
||||
- เฉพาะ Project Admin เท่านั้นที่แก้ไข template ได้
|
||||
- เฉพาะ Super Admin เท่านั้นที่ reset counter ได้
|
||||
|
||||
### 3.11.14.2. Rate Limiting
|
||||
|
||||
- Limit ต่อ user: **10 requests/minute** (prevent abuse)
|
||||
- Limit ต่อ IP: **50 requests/minute**
|
||||
|
||||
### 3.11.14.3. Audit & Compliance
|
||||
|
||||
- บันทึกทุก API call ที่เกี่ยวข้องกับ document numbering
|
||||
- เก็บ audit log อย่างน้อย **7 ปี** (ตาม พ.ร.บ. ข้อมูลอิเล็กทรอนิกส์)
|
||||
|
||||
Reference in New Issue
Block a user