251218:1701 On going update to 1.7.0: Documnet Number rebuild
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
# **ตารางฐานข้อมูล (Data Dictionary) - LCBP3-DMS (V1.6.0)**
|
||||
# **ตารางฐานข้อมูล (Data Dictionary) - LCBP3-DMS (V1.7.0)**
|
||||
|
||||
เอกสารนี้สรุปโครงสร้างตาราง,
|
||||
FOREIGN KEYS (FK),
|
||||
และ Constraints ที่สำคัญทั้งหมดในฐานข้อมูล LCBP3 - DMS (v1.6.0) เพื่อใช้เป็นเอกสารอ้างอิงสำหรับทีมพัฒนา Backend (NestJS) และ Frontend (Next.js) โดยอิงจาก Requirements และ SQL Script ล่าสุด ** สถานะ: ** FINAL GUIDELINE ** วันที่: ** 2025 -12 -13 ** อ้างอิง: ** Requirements v1.6.0 & FullStackJS Guidelines v1.6.0 ** Classification: ** Internal Technical Documentation ## 📝 สรุปรายการปรับปรุง (Summary of Changes in v1.6.0)
|
||||
1.** Schema Refactoring **: ปรับโครงสร้างตาราง `correspondences`, `correspondence_revisions`, `rfas`, `rfa_revisions` ให้เป็นมาตรฐานเดียวกัน
|
||||
2.** Shared PK Pattern **: ตาราง `rfas` ใช้ ID ร่วมกับ `correspondences` (FK Reference แทน AUTO_INCREMENT)
|
||||
3.** Column Rename **: เปลี่ยน `title` เป็น `subject` ในตาราง revision และเพิ่ม `body`, `remarks`
|
||||
4.** Virtual Columns **: เพิ่ม Virtual Columns สำหรับ Index ข้อมูลจาก JSON details
|
||||
5.** FK Updates **: `correspondence_recipients` FK ชี้ไป `correspondences(id)` แทน `correspondence_revisions` ---
|
||||
และ Constraints ที่สำคัญทั้งหมดในฐานข้อมูล LCBP3 - DMS (v1.7.0) เพื่อใช้เป็นเอกสารอ้างอิงสำหรับทีมพัฒนา Backend (NestJS) และ Frontend (Next.js) โดยอิงจาก Requirements และ SQL Script ล่าสุด ** สถานะ: ** FINAL GUIDELINE ** วันที่: ** 2025 -12 -18 ** อ้างอิง: ** Requirements v1.7.0 & FullStackJS Guidelines v1.7.0 ** Classification: ** Internal Technical Documentation ## 📝 สรุปรายการปรับปรุง (Summary of Changes in v1.7.0)
|
||||
1. **Document Numbering Overhaul**: ปรับปรุงโครงสร้าง `document_number_counters` เปลี่ยน PK เป็น Composite 8 columns และใช้ `reset_scope` แทน `current_year`
|
||||
2. **Audit & Error Logging**: ปรับปรุงตาราง `document_number_audit`, `document_number_errors` และเพิ่ม `document_number_reservations`
|
||||
3. **JSON Schemas**: เพิ่ม columns `version`, `table_name`, `ui_schema`, `virtual_columns`, `migration_script` ในตาราง `json_schemas`
|
||||
4. **Schema Cleanup**: ลบ `correspondence_id` ออกจาก `rfa_revisions` และปรับปรุง Virtual Columns ใน `correspondence_revisions` ---
|
||||
|
||||
## **1. 🏢 Core & Master Data Tables (องค์กร, โครงการ, สัญญา)**
|
||||
|
||||
@@ -252,7 +251,7 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
|
||||
---
|
||||
|
||||
### 3.3 correspondences (UPDATE v1.5.1)
|
||||
### 3.3 correspondences (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: Master table for correspondence documents (non-revisioned data)
|
||||
|
||||
@@ -289,7 +288,7 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
|
||||
---
|
||||
|
||||
### 3.4 correspondence_revisions (UPDATE v1.5.1)
|
||||
### 3.4 correspondence_revisions (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: Child table storing revision history of correspondences (1:N)
|
||||
|
||||
@@ -312,7 +311,7 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
| created_by | INT | NULL, FK | User who created revision |
|
||||
| updated_by | INT | NULL, FK | User who last updated |
|
||||
| v_ref_project_id | INT | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column ดึง Project ID จาก JSON details เพื่อทำ Index |
|
||||
| v_ref_type | VARCHAR(50) | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column ดึง Type จาก JSON details |
|
||||
|
||||
| v_doc_subtype | VARCHAR(50) | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column ดึง Type จาก JSON details |
|
||||
| schema_version | INT | DEFAULT 1 | Version of the schema used with this details |
|
||||
|
||||
@@ -330,7 +329,6 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
* INDEX (document_date)
|
||||
* INDEX (issued_date)
|
||||
* INDEX (v_ref_project_id)
|
||||
* INDEX (v_ref_type)
|
||||
* INDEX (v_doc_subtype)
|
||||
|
||||
---
|
||||
@@ -429,25 +427,26 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
|
||||
## **4. 📐 approval: RFA Tables (เอกสารขออนุมัติ, Workflows)**
|
||||
|
||||
### 4.1 rfa_types
|
||||
### 4.1 rfa_types (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: Master table for RFA (Request for Approval) types
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ----------- | ------------ | --------------------------- | ------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
|
||||
| type_code | VARCHAR(20) | NOT NULL, UNIQUE | Type code (DWG, DOC, MAT, etc.) |
|
||||
| type_name | VARCHAR(100) | NOT NULL | Full type name |
|
||||
| description | TEXT | NULL | Type description |
|
||||
| sort_order | INT | DEFAULT 0 | Display order |
|
||||
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :----------- | :----------- | :-------------------------- | :------------------------------ |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
|
||||
| contract_id | INT | NOT NULL, FK | Contract reference |
|
||||
| type_code | VARCHAR(20) | NOT NULL | Type code (DWG, DOC, MAT, etc.) |
|
||||
| type_name_th | VARCHAR(100) | NOT NULL | Full type name (TH) |
|
||||
| type_name_en | VARCHAR(100) | NOT NULL | Full type name (EN) |
|
||||
| remark | TEXT | NULL | Remark |
|
||||
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id)
|
||||
* UNIQUE (type_code)
|
||||
* UNIQUE (contract_id, type_code)
|
||||
* FOREIGN KEY (contract_id) REFERENCES contracts(id) ON DELETE CASCADE
|
||||
* INDEX (is_active)
|
||||
* INDEX (sort_order)
|
||||
|
||||
**Relationships**:
|
||||
|
||||
@@ -507,43 +506,42 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
|
||||
---
|
||||
|
||||
### 4.4 rfas (UPDATE v1.5.1)
|
||||
### 4.4 rfas (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: Master table for RFA documents (non-revisioned data)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ----------------- | --------- | --------------------------- | --------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Master RFA ID |
|
||||
| rfa_type_id | INT | NOT NULL, FK | Reference to rfa_types |
|
||||
| **discipline_id** | **INT** | **NULL, FK** | **[NEW] สาขางาน (ถ้ามี)** |
|
||||
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
|
||||
| created_by | INT | NULL, FK | User who created the record |
|
||||
| deleted_at | DATETIME | NULL | Soft delete timestamp |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :---------- | :-------- | :------------------------ | :------------------------------------------ |
|
||||
| id | INT | PK, FK | Master RFA ID (Shared with correspondences) |
|
||||
| rfa_type_id | INT | NOT NULL, FK | Reference to rfa_types |
|
||||
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
|
||||
| created_by | INT | NULL, FK | User who created the record |
|
||||
| deleted_at | DATETIME | NULL | Soft delete timestamp |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id)
|
||||
* FOREIGN KEY (id) REFERENCES correspondences(id) ON DELETE CASCADE
|
||||
* FOREIGN KEY (rfa_type_id) REFERENCES rfa_types(id)
|
||||
* **FOREIGN KEY (discipline_id) REFERENCES disciplines(id) ON DELETE SET NULL**
|
||||
* FOREIGN KEY (created_by) REFERENCES users(user_id) ON DELETE SET NULL
|
||||
* INDEX (rfa_type_id)
|
||||
* INDEX (deleted_at)
|
||||
|
||||
**Relationships**:
|
||||
|
||||
* Parent: rfa_types, **disciplines**, users
|
||||
* Parent: correspondences, rfa_types, users
|
||||
* Children: rfa_revisions
|
||||
|
||||
---
|
||||
|
||||
### 4.5 rfa_revisions (UPDATE v1.5.1)
|
||||
### 4.5 rfa_revisions (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: Child table storing revision history of RFAs (1:N)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------------- | ------------ | --------------------------------- | ----------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
|
||||
| correspondence_id | INT | NOT NULL, FK | Link to correspondence (RFA as correspondence) |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ----------- | --------- | --------------------------- | ------------------ |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
|
||||
|
||||
| rfa_id | INT | NOT NULL, FK | Master RFA ID |
|
||||
| revision_number | INT | NOT NULL | Revision sequence (0, 1, 2...) |
|
||||
| revision_label | VARCHAR(10) | NULL | Display revision (A, B, 1.1...) |
|
||||
@@ -566,7 +564,6 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id)
|
||||
* FOREIGN KEY (correspondence_id) REFERENCES correspondences(id) ON DELETE CASCADE
|
||||
* FOREIGN KEY (rfa_id) REFERENCES rfas(id) ON DELETE CASCADE
|
||||
* FOREIGN KEY (rfa_status_code_id) REFERENCES rfa_status_codes(id)
|
||||
* FOREIGN KEY (rfa_approve_code_id) REFERENCES rfa_approve_codes(id) ON DELETE SET NULL
|
||||
@@ -582,7 +579,7 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
**Relationships**:
|
||||
|
||||
* Parent: correspondences, rfas, rfa_status_codes, rfa_approve_codes, users
|
||||
* Children: rfa_items, rfa_workflows
|
||||
* Children: rfa_items
|
||||
|
||||
---
|
||||
|
||||
@@ -590,15 +587,15 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
|
||||
**Purpose**: Junction table linking RFA revisions to shop drawing revisions (M:N)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------------------ | --------- | --------------- | ------------------------------ |
|
||||
| rfarev_correspondence_id | INT | PRIMARY KEY, FK | RFA revision correspondence ID |
|
||||
| shop_drawing_revision_id | INT | PRIMARY KEY, FK | Shop drawing revision ID |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :----------------------- | :-------- | :-------------- | :----------------------- |
|
||||
| rfa_revision_id | INT | PRIMARY KEY, FK | RFA Revision ID |
|
||||
| shop_drawing_revision_id | INT | PRIMARY KEY, FK | Shop drawing revision ID |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (rfarev_correspondence_id, shop_drawing_revision_id)
|
||||
* FOREIGN KEY (rfarev_correspondence_id) REFERENCES rfa_revisions(correspondence_id) ON DELETE CASCADE
|
||||
* PRIMARY KEY (rfa_revision_id, shop_drawing_revision_id)
|
||||
* FOREIGN KEY (rfa_revision_id) REFERENCES rfa_revisions(id) ON DELETE CASCADE
|
||||
* FOREIGN KEY (shop_drawing_revision_id) REFERENCES shop_drawing_revisions(id) ON DELETE CASCADE
|
||||
* INDEX (shop_drawing_revision_id)
|
||||
|
||||
@@ -614,45 +611,6 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
|
||||
---
|
||||
|
||||
### 4.7 rfa_workflows
|
||||
|
||||
**Purpose**: Transaction log table tracking actual RFA approval workflow execution
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| --------------- | --------- | ----------------------------------- | ------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique workflow log ID |
|
||||
| rfa_revision_id | INT | NOT NULL, FK | Reference to RFA revision |
|
||||
| step_number | INT | NOT NULL | Current step number |
|
||||
| organization_id | INT | NOT NULL, FK | Organization responsible |
|
||||
| assigned_to | INT | NULL, FK | Assigned user ID |
|
||||
| action_type | ENUM | NULL | Action type: REVIEW, APPROVE, ACKNOWLEDGE |
|
||||
| status | ENUM | NULL | Status: PENDING, IN_PROGRESS, COMPLETED, REJECTED |
|
||||
| comments | TEXT | NULL | Comments/remarks |
|
||||
| completed_at | DATETIME | NULL | Completion timestamp |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
|
||||
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
|
||||
| state_context | JSON\* | NULL | เก็บข้อมูล Context ของ Workflow ณ ขณะนั้น (Snapshot) |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id)
|
||||
* FOREIGN KEY (rfa_revision_id) REFERENCES rfa_revisions(id) ON DELETE CASCADE
|
||||
* FOREIGN KEY (organization_id) REFERENCES organizations(id)
|
||||
* FOREIGN KEY (assigned_to) REFERENCES users(user_id)
|
||||
* INDEX (rfa_revision_id, step_number)
|
||||
* INDEX (assigned_to, status)
|
||||
* INDEX (status)
|
||||
|
||||
**Relationships**:
|
||||
|
||||
* Parent: rfa_revisions, organizations, users
|
||||
|
||||
**Business Rules**:
|
||||
|
||||
* Records actual workflow execution history
|
||||
* Tracks who did what and when
|
||||
* Multiple records per RFA revision (one per step)
|
||||
* Status changes tracked via updated_at
|
||||
|
||||
---
|
||||
|
||||
@@ -1344,85 +1302,154 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
|
||||
---
|
||||
|
||||
### 9.2 document_number_counters (UPDATE v1.5.1)
|
||||
### 9.2 document_number_counters (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: Transaction table tracking running numbers (High Concurrency)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------------- | --------- | ------------- | -------------------------------------------- |
|
||||
| project_id | INT | PK, NOT NULL | โครงการ |
|
||||
| originator_organization_id | INT | PK, NOT NULL | องค์กรผู้ส่ง |
|
||||
| recipient_organization_id | INT | PK, NOT NULL | [NEW] องค์กรผู้รับ (-1 = ทุกองค์กร) |
|
||||
| correspondence_type_id | INT | PK, NOT NULL | ประเภทเอกสาร |
|
||||
| sub_type_id | INT | PK, DEFAULT 0 | [NEW] ประเภทย่อย สำหรับ TRANSMITTAL (0 = ไม่ระบุ) |
|
||||
| rfa_type_id | INT | PK, DEFAULT 0 | [NEW] ประเภท RFA (0 = ไม่ใช่ RFA) |
|
||||
| discipline_id | INT | PK, DEFAULT 0 | [NEW] สาขางาน (0 = ไม่ระบุ) |
|
||||
| current_year | INT | PK, NOT NULL | ปี ค.ศ. ของตัวนับ (auto-reset ทุกปี) |
|
||||
| last_number | INT | DEFAULT 0 | เลขล่าสุดที่ถูกใช้งานไปแล้ว |
|
||||
| updated_at | TIMESTAMP | ON UPDATE | เวลาที่อัปเดตล่าสุด |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------------- | ----------- | ------------- | ----------------------------------------------- |
|
||||
| project_id | INT | PK, NOT NULL | โครงการ |
|
||||
| originator_organization_id | INT | PK, NOT NULL | องค์กรผู้ส่ง |
|
||||
| recipient_organization_id | INT | PK, NOT NULL | องค์กรผู้รับ (0 = no recipient / RFA) |
|
||||
| correspondence_type_id | INT | PK, NULL | ประเภทเอกสาร (NULL = default) |
|
||||
| sub_type_id | INT | PK, DEFAULT 0 | ประเภทย่อย สำหรับ TRANSMITTAL (0 = ไม่ระบุ) |
|
||||
| rfa_type_id | INT | PK, DEFAULT 0 | ประเภท RFA (0 = ไม่ใช่ RFA) |
|
||||
| discipline_id | INT | PK, DEFAULT 0 | สาขางาน (0 = ไม่ระบุ) |
|
||||
| reset_scope | VARCHAR(20) | PK, NOT NULL | Scope of reset (YEAR_2024, MONTH_2024_01, NONE) |
|
||||
| last_number | INT | DEFAULT 0 | เลขล่าสุดที่ถูกใช้งานไปแล้ว |
|
||||
| version | INT | DEFAULT 0 | Optimistic Lock Version |
|
||||
| updated_at | DATETIME(6) | ON UPDATE | เวลาที่อัปเดตล่าสุด |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* **PRIMARY KEY (project_id, originator_organization_id, recipient_organization_id, correspondence_type_id, sub_type_id, rfa_type_id, discipline_id, current_year)**
|
||||
* **PRIMARY KEY (project_id, originator_organization_id, recipient_organization_id, correspondence_type_id, sub_type_id, rfa_type_id, discipline_id, reset_scope)**
|
||||
* INDEX idx_counter_lookup (project_id, correspondence_type_id, reset_scope)
|
||||
* INDEX idx_counter_org (originator_organization_id, reset_scope)
|
||||
|
||||
**Business Rules**:
|
||||
|
||||
* **Composite Primary Key 8 Columns**: เพื่อรองรับการรันเลขที่ซับซ้อนตาม Req 6B
|
||||
* **Concurrency Control**: ใช้ Redis Lock หรือ Optimistic Locking ในการอัปเดต `last_number`
|
||||
* **Reset Rule**: `current_year` เปลี่ยน -> เริ่มนับ 1 ใหม่
|
||||
* **Composite Primary Key 8 Columns**: เพื่อรองรับการรันเลขที่ซับซ้อนและ Reset Scope ที่หลากหลาย
|
||||
* **Concurrency Control**: ใช้ Redis Lock หรือ Optimistic Locking (version)
|
||||
* **Reset Scope**: ใช้ Field `reset_scope` ควบคุมการ Reset แทน `current_year` แบบเดิม
|
||||
|
||||
---
|
||||
|
||||
### 9.3 document_number_audit (NEW v1.5.1)
|
||||
### 9.3 document_number_audit (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: Audit log for document number generation (Debugging & Tracking)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :---------------- | :----------- | :---------- | :---------------------------------- |
|
||||
| id | BIGINT | PK, AI | Unique ID |
|
||||
| transaction_id | VARCHAR(36) | NOT NULL | UUID ของ Transaction การขอเลข |
|
||||
| counter_key_json | JSON | NOT NULL | ค่า Key ที่ใช้ในการ Query (เก็บเป็น JSON) |
|
||||
| generated_number | VARCHAR(100) | NOT NULL | เลขที่ได้ |
|
||||
| requested_by | INT | FK | User ที่ขอเลข |
|
||||
| requested_at | TIMESTAMP | DEFAULT NOW | เวลาที่ขอ |
|
||||
| execution_time_ms | INT | NULL | เวลาที่ใช้ในการประมวลผล (ms) |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :------------------------- | :----------- | :----------------- | :-------------------------------------- |
|
||||
| id | INT | PK, AI | ID ของ audit record |
|
||||
| document_id | INT | NOT NULL, FK | ID ของเอกสารที่สร้างเลขที่ |
|
||||
| document_type | VARCHAR(50) | NULL | ประเภทเอกสาร |
|
||||
| document_number | VARCHAR(100) | NOT NULL | เลขที่เอกสารที่สร้าง (ผลลัพธ์) |
|
||||
| operation | ENUM | DEFAULT 'CONFIRM' | RESERVE, CONFIRM, MANUAL_OVERRIDE, etc. |
|
||||
| status | ENUM | DEFAULT 'RESERVED' | RESERVED, CONFIRMED, CANCELLED, VOID |
|
||||
| counter_key | JSON | NOT NULL | Counter key ที่ใช้ (JSON 8 fields) |
|
||||
| reservation_token | VARCHAR(36) | NULL | Token การจอง |
|
||||
| originator_organization_id | INT | NULL | องค์กรผู้ส่ง |
|
||||
| recipient_organization_id | INT | NULL | องค์กรผู้รับ |
|
||||
| template_used | VARCHAR(200) | NOT NULL | Template ที่ใช้ในการสร้าง |
|
||||
| user_id | INT | NOT NULL, FK | ผู้ขอสร้างเลขที่ |
|
||||
| is_success | BOOLEAN | DEFAULT TRUE | สถานะความสำเร็จ |
|
||||
| created_at | TIMESTAMP | DEFAULT NOW | วันที่/เวลาที่สร้าง |
|
||||
| total_duration_ms | INT | NULL | เวลารวมทั้งหมดในการสร้าง (ms) |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id)
|
||||
* FOREIGN KEY (document_id) REFERENCES correspondences(id) ON DELETE CASCADE
|
||||
* FOREIGN KEY (user_id) REFERENCES users(user_id)
|
||||
* INDEX (document_id)
|
||||
* INDEX (user_id)
|
||||
* INDEX (status)
|
||||
* INDEX (operation)
|
||||
* INDEX (document_number)
|
||||
* INDEX (reservation_token)
|
||||
* INDEX (created_at)
|
||||
|
||||
---
|
||||
|
||||
### 9.4 document_number_errors (NEW v1.5.1)
|
||||
### 9.4 document_number_errors (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: Error log for failed document number generation
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :--------------- | :---------- | :---------- | :------------------------------- |
|
||||
| id | BIGINT | PK, AI | Unique ID |
|
||||
| transaction_id | VARCHAR(36) | NOT NULL | UUID ของ Transaction |
|
||||
| error_code | VARCHAR(50) | NOT NULL | รหัส Error (เช่น ERR_LOCK_TIMEOUT) |
|
||||
| error_message | TEXT | NOT NULL | รายละเอียด Error |
|
||||
| counter_key_json | JSON | NULL | ค่า Key ที่พยายามใช้ |
|
||||
| occurred_at | TIMESTAMP | DEFAULT NOW | เวลาที่เกิด Error |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :------------ | :-------- | :---------- | :--------------------------------------------- |
|
||||
| id | INT | PK, AI | ID ของ error record |
|
||||
| error_type | ENUM | NOT NULL | LOCK_TIMEOUT, VERSION_CONFLICT, DB_ERROR, etc. |
|
||||
| error_message | TEXT | NULL | ข้อความ error |
|
||||
| stack_trace | TEXT | NULL | Stack trace สำหรับ debugging |
|
||||
| context_data | JSON | NULL | Context ของ request |
|
||||
| user_id | INT | NULL | ผู้ที่เกิด error |
|
||||
| created_at | TIMESTAMP | DEFAULT NOW | วันที่เกิด error |
|
||||
| resolved_at | TIMESTAMP | NULL | วันที่แก้ไขแล้ว |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id)
|
||||
* INDEX (error_type)
|
||||
* INDEX (created_at)
|
||||
* INDEX (user_id)
|
||||
* INDEX (resolved_at)
|
||||
|
||||
---
|
||||
|
||||
## **10. ⚙️ Unified Workflow Engine Tables (NEW v1.5.1)**
|
||||
### 9.5 document_number_reservations (NEW v1.7.0)
|
||||
|
||||
**Purpose**: Two-Phase Commit table for document number reservation
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :--------------------- | :----------- | :--------------- | :----------------------------------- |
|
||||
| id | INT | PK, AI | Unique ID |
|
||||
| token | VARCHAR(36) | UNIQUE, NOT NULL | UUID v4 Reservation Token |
|
||||
| document_number | VARCHAR(100) | UNIQUE, NOT NULL | เลขที่เอกสารที่จอง |
|
||||
| document_number_status | ENUM | DEFAULT RESERVED | RESERVED, CONFIRMED, CANCELLED, VOID |
|
||||
| document_id | INT | NULL, FK | ID ของเอกสาร (เมื่อ Confirm แล้ว) |
|
||||
| expires_at | DATETIME(6) | NOT NULL | เวลาหมดอายุการจอง |
|
||||
| project_id | INT | NOT NULL, FK | Project Context |
|
||||
| user_id | INT | NOT NULL, FK | User Context |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id)
|
||||
* FOREIGN KEY (document_id) REFERENCES correspondence_revisions(id) ON DELETE SET NULL
|
||||
* FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
|
||||
* FOREIGN KEY (correspondence_type_id) REFERENCES correspondence_types(id) ON DELETE CASCADE
|
||||
* FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
|
||||
* INDEX idx_token (token)
|
||||
* INDEX idx_status (document_number_status)
|
||||
* INDEX idx_status_expires (document_number_status, expires_at)
|
||||
* INDEX idx_document_id (document_id)
|
||||
* INDEX idx_user_id (user_id)
|
||||
* INDEX idx_reserved_at (reserved_at)
|
||||
|
||||
---
|
||||
|
||||
## **10. ⚙️ Unified Workflow Engine Tables (UPDATE v1.7.0)**
|
||||
|
||||
### 10.1 workflow_definitions
|
||||
|
||||
**Purpose**: เก็บแม่แบบ (Template) ของ Workflow (Req 3.6)
|
||||
**Purpose**: เก็บแม่แบบ (Template) ของ Workflow (Definition / DSL)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :------------ | :----------- | :----------- | :--------------------------------------------- |
|
||||
| id | INT | PK, AI | Unique ID |
|
||||
| workflow_code | VARCHAR(50) | UNIQUE | รหัส Workflow (เช่น WF-RFA-GENERIC) |
|
||||
| workflow_name | VARCHAR(255) | NOT NULL | ชื่อ Workflow |
|
||||
| description | TEXT | NULL | คำอธิบาย |
|
||||
| module | VARCHAR(50) | NOT NULL | ใช้กับ Module ไหน (RFA, CORRESPONDENCE) |
|
||||
| steps_config | JSON | NOT NULL | การตั้งค่า Step (Sequence, Approvers, Conditions) |
|
||||
| is_active | BOOLEAN | DEFAULT TRUE | สถานะการใช้งาน |
|
||||
| version | INT | DEFAULT 1 | เวอร์ชันของ Definition |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :------------ | :---------- | :----------- | :------------------------------------- |
|
||||
| id | CHAR(36) | PK, UUID | Unique Workflow Definition ID |
|
||||
| workflow_code | VARCHAR(50) | NOT NULL | รหัส Workflow (เช่น RFA_FLOW_V1) |
|
||||
| version | INT | DEFAULT 1 | หมายเลข Version |
|
||||
| description | TEXT | NULL | คำอธิบาย Workflow |
|
||||
| dsl | JSON | NOT NULL | นิยาม Workflow ต้นฉบับ (YAML/JSON Format) |
|
||||
| compiled | JSON | NOT NULL | โครงสร้าง Execution Tree ที่ Compile แล้ว |
|
||||
| is_active | BOOLEAN | DEFAULT TRUE | สถานะการใช้งาน |
|
||||
| created_at | TIMESTAMP | DEFAULT NOW | วันที่สร้าง |
|
||||
| updated_at | TIMESTAMP | ON UPDATE | วันที่แก้ไขล่าสุด |
|
||||
|
||||
**Business Rules**:
|
||||
* `steps_config` เก็บ Logic ของ Workflow ทั้งหมดในรูปแบบ JSON เพื่อความยืดหยุ่น
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id)
|
||||
* UNIQUE KEY (workflow_code, version)
|
||||
* INDEX (is_active)
|
||||
|
||||
---
|
||||
|
||||
@@ -1430,16 +1457,24 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
|
||||
**Purpose**: เก็บสถานะของ Workflow ที่กำลังรันอยู่จริง (Runtime)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :--------------------- | :----------- | :----------- | :----------------------------------------- |
|
||||
| id | BIGINT | PK, AI | Unique ID |
|
||||
| workflow_definition_id | INT | FK, NOT NULL | อ้างอิง Definition |
|
||||
| business_key | VARCHAR(100) | INDEX | ID ของเอกสารที่ผูกกับ Workflow นี้ (เช่น RFA-001) |
|
||||
| current_step_name | VARCHAR(100) | NOT NULL | ชื่อ Step ปัจจุบัน |
|
||||
| status | ENUM | NOT NULL | IN_PROGRESS, COMPLETED, TERMINATED |
|
||||
| context_data | JSON | NULL | ข้อมูลประกอบการตัดสินใจ (Variables) |
|
||||
| started_at | TIMESTAMP | DEFAULT NOW | เวลาที่เริ่ม |
|
||||
| completed_at | TIMESTAMP | NULL | เวลาที่จบ |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :------------ | :---------- | :--------------- | :--------------------------------------------- |
|
||||
| id | CHAR(36) | PK, UUID | Unique Instance ID |
|
||||
| definition_id | CHAR(36) | FK, NOT NULL | อ้างอิง Definition ที่ใช้ |
|
||||
| entity_type | VARCHAR(50) | NOT NULL | ประเภทเอกสาร (rfa_revision, correspondence...) |
|
||||
| entity_id | VARCHAR(50) | NOT NULL | ID ของเอกสาร |
|
||||
| current_state | VARCHAR(50) | NOT NULL | สถานะปัจจุบัน |
|
||||
| status | ENUM | DEFAULT 'ACTIVE' | ACTIVE, COMPLETED, CANCELLED, TERMINATED |
|
||||
| context | JSON | NULL | ตัวแปร Context สำหรับตัดสินใจ |
|
||||
| created_at | TIMESTAMP | DEFAULT NOW | เวลาที่สร้าง |
|
||||
| updated_at | TIMESTAMP | ON UPDATE | เวลาที่อัปเดตล่าสุด |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id)
|
||||
* FOREIGN KEY (definition_id) REFERENCES workflow_definitions(id) ON DELETE CASCADE
|
||||
* INDEX (entity_type, entity_id)
|
||||
* INDEX (current_state)
|
||||
|
||||
---
|
||||
|
||||
@@ -1447,86 +1482,102 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
|
||||
**Purpose**: เก็บประวัติการดำเนินการในแต่ละ Step (Audit Trail)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :------------------- | :----------- | :----------- | :--------------------------------- |
|
||||
| id | BIGINT | PK, AI | Unique ID |
|
||||
| workflow_instance_id | BIGINT | FK, NOT NULL | อ้างอิง Instance |
|
||||
| step_name | VARCHAR(100) | NOT NULL | ชื่อ Step |
|
||||
| action | VARCHAR(50) | NOT NULL | การกระทำ (APPROVE, REJECT, COMMENT) |
|
||||
| actor_id | INT | FK, NULL | User ที่กระทำ |
|
||||
| comments | TEXT | NULL | ความเห็นเพิ่มเติม |
|
||||
| performed_at | TIMESTAMP | DEFAULT NOW | เวลาที่กระทำ |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :---------------- | :---------- | :----------- | :-------------------- |
|
||||
| id | CHAR(36) | PK, UUID | Unique ID |
|
||||
| instance_id | CHAR(36) | FK, NOT NULL | อ้างอิง Instance |
|
||||
| from_state | VARCHAR(50) | NOT NULL | สถานะต้นทาง |
|
||||
| to_state | VARCHAR(50) | NOT NULL | สถานะปลายทาง |
|
||||
| action | VARCHAR(50) | NOT NULL | Action ที่กระทำ |
|
||||
| action_by_user_id | INT | FK, NULL | User ID ผู้กระทำ |
|
||||
| comment | TEXT | NULL | ความเห็น |
|
||||
| metadata | JSON | NULL | Snapshot ข้อมูล ณ ขณะนั้น |
|
||||
| created_at | TIMESTAMP | DEFAULT NOW | เวลาที่กระทำ |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id)
|
||||
* FOREIGN KEY (instance_id) REFERENCES workflow_instances(id) ON DELETE CASCADE
|
||||
* INDEX (instance_id)
|
||||
* INDEX (action_by_user_id)
|
||||
|
||||
---
|
||||
|
||||
## **11. 🖥️ System & Logs Tables (ระบบ, บันทึก)**
|
||||
|
||||
### 11.1 json_schemas (NEW v1.5.1)
|
||||
### 11.1 json_schemas (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: เก็บ Schema สำหรับ Validate JSON Columns (Req 3.12)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :---------- | :---------- | :----------- | :------------------------------------- |
|
||||
| id | INT | PK, AI | Unique ID |
|
||||
| schema_code | VARCHAR(50) | UNIQUE | รหัส Schema (เช่น RFA_DETAILS_V1) |
|
||||
| schema_body | JSON | NOT NULL | JSON Schema Draft 7/2020-12 definition |
|
||||
| description | TEXT | NULL | คำอธิบาย |
|
||||
| is_active | BOOLEAN | DEFAULT TRUE | สถานะ |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :---------------- | :----------- | :----------- | :------------------------------- |
|
||||
| id | INT | PK, AI | Unique ID |
|
||||
| schema_code | VARCHAR(100) | NOT NULL | รหัส Schema (เช่น RFA_DWG) |
|
||||
| version | INT | DEFAULT 1 | เวอร์ชันของ Schema |
|
||||
| table_name | VARCHAR(100) | NOT NULL | ชื่อตารางเป้าหมาย |
|
||||
| schema_definition | JSON | NOT NULL | JSON Schema Definition |
|
||||
| ui_schema | JSON | NULL | โครงสร้าง UI Schema สำหรับ Frontend |
|
||||
| virtual_columns | JSON | NULL | Config สำหรับสร้าง Virtual Columns |
|
||||
| migration_script | JSON | NULL | Script สำหรับแปลงข้อมูล |
|
||||
| is_active | BOOLEAN | DEFAULT TRUE | สถานะการใช้งาน |
|
||||
|
||||
|
||||
---
|
||||
|
||||
### 11.2 audit_logs (UPDATE v1.5.1)
|
||||
### 11.2 audit_logs (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: Centralized audit logging for all system actions
|
||||
**Purpose**: Centralized audit logging for all system actions (Req 6.1)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ----------- | ------------ | --------------------------- | ----------------------------------------- |
|
||||
| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | Unique log ID |
|
||||
| user_id | INT | NULL, FK | User who performed action |
|
||||
| action | VARCHAR(50) | NOT NULL | Action name (CREATE, UPDATE, DELETE, etc) |
|
||||
| module | VARCHAR(50) | NOT NULL | Module name (USERS, RFA, etc) |
|
||||
| entity_id | VARCHAR(50) | NULL | ID of affected entity |
|
||||
| old_values | JSON | NULL | Data before change |
|
||||
| new_values | JSON | NULL | Data after change |
|
||||
| ip_address | VARCHAR(45) | NULL | User IP address |
|
||||
| user_agent | VARCHAR(255) | NULL | User browser/client info |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Log timestamp |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :----------- | :----------- | :------------------------ | :------------------------------------------- |
|
||||
| audit_id | BIGINT | PK, AI | Unique log ID |
|
||||
| request_id | VARCHAR(100) | NULL | Trace ID linking to app logs |
|
||||
| user_id | INT | NULL, FK | User who performed action |
|
||||
| action | VARCHAR(100) | NOT NULL | Action name (e.g. rfa.create) |
|
||||
| severity | ENUM | DEFAULT 'INFO' | INFO, WARN, ERROR, CRITICAL |
|
||||
| entity_type | VARCHAR(50) | NULL | Module/Table name (e.g. rfa, correspondence) |
|
||||
| entity_id | VARCHAR(50) | NULL | ID of affected entity |
|
||||
| details_json | JSON | NULL | Context data / Old & New values |
|
||||
| ip_address | VARCHAR(45) | NULL | User IP address |
|
||||
| user_agent | VARCHAR(255) | NULL | User browser/client info |
|
||||
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Log timestamp |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id, created_at) -- **Partition Key**
|
||||
* INDEX (user_id)
|
||||
* INDEX (module)
|
||||
* INDEX (action)
|
||||
* INDEX (created_at)
|
||||
* INDEX (entity_id)
|
||||
* PRIMARY KEY (audit_id, created_at) -- **Partition Key**
|
||||
* INDEX idx_audit_user (user_id)
|
||||
* INDEX idx_audit_action (action)
|
||||
* INDEX idx_audit_entity (entity_type, entity_id)
|
||||
* INDEX idx_audit_created (created_at)
|
||||
|
||||
**Partitioning**:
|
||||
* **PARTITION BY RANGE (YEAR(created_at))**: แบ่ง Partition รายปี เพื่อประสิทธิภาพในการเก็บข้อมูลระยะยาว
|
||||
|
||||
---
|
||||
|
||||
### 11.3 notifications (UPDATE v1.5.1)
|
||||
### 11.3 notifications (UPDATE v1.7.0)
|
||||
|
||||
**Purpose**: System notifications for users
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ----------- | ------------ | --------------------------- | ----------------------------------- |
|
||||
| id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | Unique notification ID |
|
||||
| user_id | INT | NOT NULL, FK | Recipient user ID |
|
||||
| title | VARCHAR(255) | NOT NULL | Notification title |
|
||||
| message | TEXT | NOT NULL | Notification body |
|
||||
| link | VARCHAR(500) | NULL | Action link URL |
|
||||
| type | VARCHAR(50) | DEFAULT ' INFO ' | Type: INFO, WARNING, ERROR, SUCCESS |
|
||||
| is_read | BOOLEAN | DEFAULT FALSE | Read status |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Notification timestamp |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :---------------- | :----------- | :-------------------------- | :------------------------ |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique notification ID |
|
||||
| user_id | INT | NOT NULL, FK | Recipient user ID |
|
||||
| title | VARCHAR(255) | NOT NULL | Notification title |
|
||||
| message | TEXT | NOT NULL | Notification body |
|
||||
| notification_type | ENUM | NOT NULL | Type: EMAIL, LINE, SYSTEM |
|
||||
| is_read | BOOLEAN | DEFAULT FALSE | Read status |
|
||||
| entity_type | VARCHAR(50) | NULL | Related Entity Type |
|
||||
| entity_id | INT | NULL | Related Entity ID |
|
||||
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Notification timestamp |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
* PRIMARY KEY (id, created_at) -- **Partition Key**
|
||||
* FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
|
||||
* INDEX (user_id, is_read)
|
||||
* INDEX (created_at)
|
||||
* INDEX idx_notif_user (user_id)
|
||||
* INDEX idx_notif_type (notification_type)
|
||||
* INDEX idx_notif_read (is_read)
|
||||
* INDEX idx_notif_created (created_at)
|
||||
|
||||
**Partitioning**:
|
||||
* **PARTITION BY RANGE (YEAR(created_at))**: แบ่ง Partition รายปี
|
||||
@@ -1535,58 +1586,33 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
|
||||
|
||||
## **12. 🔍 Views (มุมมองข้อมูล)**
|
||||
|
||||
### 12.1 v_correspondence_details
|
||||
### 12.1 v_current_correspondences
|
||||
|
||||
**Purpose**: Denormalized view for correspondence listing and searching
|
||||
**Purpose**: แสดงข้อมูล Correspondence Revision ล่าสุด (is_current = TRUE)
|
||||
|
||||
```sql
|
||||
CREATE VIEW v_correspondence_details AS
|
||||
SELECT
|
||||
c.id,
|
||||
c.correspondence_number,
|
||||
c.correspondence_type_id,
|
||||
ct.type_name,
|
||||
c.project_id,
|
||||
p.project_code,
|
||||
c.originator_id,
|
||||
org.organization_code AS originator_code,
|
||||
cr.title,
|
||||
cr.revision_number,
|
||||
cr.correspondence_status_id,
|
||||
cs.status_name,
|
||||
cr.document_date,
|
||||
cr.created_at
|
||||
FROM correspondences c
|
||||
JOIN correspondence_revisions cr ON c.id = cr.correspondence_id AND cr.is_current = 1
|
||||
JOIN correspondence_types ct ON c.correspondence_type_id = ct.id
|
||||
JOIN projects p ON c.project_id = p.id
|
||||
LEFT JOIN organizations org ON c.originator_id = org.id
|
||||
LEFT JOIN correspondence_status cs ON cr.correspondence_status_id = cs.id;
|
||||
```
|
||||
### 12.2 v_current_rfas
|
||||
|
||||
### 12.2 v_rfa_details
|
||||
**Purpose**: แสดงข้อมูล RFA Revision ล่าสุด พร้อม Status และ Approve Code
|
||||
|
||||
**Purpose**: Denormalized view for RFA listing and searching
|
||||
### 12.3 v_user_tasks (Unified Workflow)
|
||||
|
||||
```sql
|
||||
CREATE VIEW v_rfa_details AS
|
||||
SELECT
|
||||
r.id,
|
||||
c.correspondence_number AS rfa_number,
|
||||
rt.type_code AS rfa_type,
|
||||
rr.title,
|
||||
rr.revision_number,
|
||||
rsc.status_name AS rfa_status,
|
||||
rac.approve_name AS approval_result,
|
||||
rr.document_date,
|
||||
rr.due_date
|
||||
FROM rfas r
|
||||
JOIN correspondences c ON r.id = c.id -- Assuming 1:1 mapping logic or shared ID
|
||||
JOIN rfa_revisions rr ON r.id = rr.rfa_id AND rr.is_current = 1
|
||||
JOIN rfa_types rt ON r.rfa_type_id = rt.id
|
||||
JOIN rfa_status_codes rsc ON rr.rfa_status_code_id = rsc.id
|
||||
LEFT JOIN rfa_approve_codes rac ON rr.rfa_approve_code_id = rac.id;
|
||||
```
|
||||
**Purpose**: รวมรายการงานที่ยังค้างอยู่ (Status = ACTIVE) จากทุกระบบ (RFA, Circulation, Correspondence) เพื่อนำไปแสดงใน Dashboard
|
||||
|
||||
### 12.4 v_audit_log_details
|
||||
|
||||
**Purpose**: แสดง audit_logs พร้อมข้อมูล username และ email ของผู้กระทำ
|
||||
|
||||
### 12.5 v_user_all_permissions
|
||||
|
||||
**Purpose**: รวมสิทธิ์ทั้งหมด (Global + Project + Organization) ของผู้ใช้ทุกคน
|
||||
|
||||
### 12.6 v_documents_with_attachments
|
||||
|
||||
**Purpose**: แสดงเอกสารทั้งหมดที่มีไฟล์แนบ (Correspondence, Circulation, Drawings)
|
||||
|
||||
### 12.7 v_document_statistics
|
||||
|
||||
**Purpose**: แสดงสถิติเอกสารตามประเภทและสถานะ
|
||||
|
||||
---
|
||||
|
||||
@@ -1594,21 +1620,21 @@ LEFT JOIN rfa_approve_codes rac ON rr.rfa_approve_code_id = rac.id;
|
||||
|
||||
### 13.1 Performance Indexes
|
||||
|
||||
| Table Name | Index Columns | Purpose |
|
||||
| :----------------------- | :------------------------------------------------- | :----------------------------- |
|
||||
| correspondences | (project_id, correspondence_number) | Fast lookup by document number |
|
||||
| correspondences | (correspondence_type_id) | Filter by type |
|
||||
| correspondence_revisions | (correspondence_id, is_current) | Get current revision |
|
||||
| rfas | (rfa_type_id) | Filter by RFA type |
|
||||
| rfa_revisions | (rfa_id, is_current) | Get current RFA revision |
|
||||
| rfa_revisions | (rfa_status_code_id) | Filter by status |
|
||||
| audit_logs | (created_at) | Date range queries |
|
||||
| audit_logs | (user_id) | User activity history |
|
||||
| audit_logs | (module, action) | Action type analysis |
|
||||
| notifications | (user_id, is_read) | Unread notifications query |
|
||||
| document_number_counters | (project_id, correspondence_type_id, current_year) | Running number generation |
|
||||
| workflow_instances | (business_key) | Workflow lookup by document ID |
|
||||
| workflow_instances | (status) | Monitor active workflows |
|
||||
| Table Name | Index Columns | Purpose |
|
||||
| :----------------------- | :------------------------------------------------ | :----------------------------- |
|
||||
| correspondences | (project_id, correspondence_number) | Fast lookup by document number |
|
||||
| correspondences | (correspondence_type_id) | Filter by type |
|
||||
| correspondence_revisions | (correspondence_id, is_current) | Get current revision |
|
||||
| rfas | (rfa_type_id) | Filter by RFA type |
|
||||
| rfa_revisions | (rfa_id, is_current) | Get current RFA revision |
|
||||
| rfa_revisions | (rfa_status_code_id) | Filter by status |
|
||||
| audit_logs | (created_at) | Date range queries |
|
||||
| audit_logs | (user_id) | User activity history |
|
||||
| audit_logs | (module, action) | Action type analysis |
|
||||
| notifications | (user_id, is_read) | Unread notifications query |
|
||||
| document_number_counters | (project_id, correspondence_type_id, reset_scope) | Running number generation |
|
||||
| workflow_instances | (entity_type, entity_id) | Workflow lookup by document ID |
|
||||
| workflow_instances | (current_state) | Monitor active workflows |
|
||||
|
||||
### 13.2 Unique Constraints
|
||||
|
||||
@@ -1620,9 +1646,9 @@ LEFT JOIN rfa_approve_codes rac ON rr.rfa_approve_code_id = rac.id;
|
||||
| projects | (project_code) | Unique project code |
|
||||
| contracts | (contract_code) | Unique contract code |
|
||||
| correspondences | (project_id, correspondence_number) | Unique document number per project |
|
||||
| rfas | (drawing_number) | Unique shop drawing number |
|
||||
| shop_drawings | (drawing_number) | Unique shop drawing number |
|
||||
| document_number_formats | (project_id, correspondence_type_id) | One format per type per project |
|
||||
| workflow_definitions | (workflow_code) | Unique workflow code |
|
||||
| workflow_definitions | (workflow_code, version) | Unique workflow code per version |
|
||||
|
||||
---
|
||||
|
||||
@@ -1671,7 +1697,7 @@ LEFT JOIN rfa_approve_codes rac ON rr.rfa_approve_code_id = rac.id;
|
||||
|
||||
## **16. 🔄 Data Migration & Seeding (การย้ายข้อมูล)**
|
||||
|
||||
### 16.1 Initial Seeding (V1.5.1)
|
||||
### 16.1 Initial Seeding (V1.7.0)
|
||||
|
||||
1. **Master Data**:
|
||||
* `organizations`: Owner, Consultant, Contractor
|
||||
@@ -1679,7 +1705,7 @@ LEFT JOIN rfa_approve_codes rac ON rr.rfa_approve_code_id = rac.id;
|
||||
* `correspondence_types`: LETTER, MEMO, TRANSMITTAL, RFA
|
||||
* `rfa_types`: DWG, MAT, DOC, RFI
|
||||
* `rfa_status_codes`: DFT, PEND, APPR, REJ
|
||||
* `disciplines`: GEN, STR, ARC, MEP (New V1.5.1)
|
||||
* `disciplines`: GEN, STR, ARC, MEP
|
||||
2. **System Users**:
|
||||
* `admin`: Super Admin
|
||||
* `system`: System Bot for automated tasks
|
||||
@@ -1688,11 +1714,11 @@ LEFT JOIN rfa_approve_codes rac ON rr.rfa_approve_code_id = rac.id;
|
||||
|
||||
* **Schema Migration**: Use TypeORM Migrations or raw SQL scripts (versioned).
|
||||
* **Data Migration**:
|
||||
* **V1.4.5 -> V1.5.1**:
|
||||
* Run SQL script `8_lcbp3_v1_5_1.sql`
|
||||
* Populate `disciplines` table.
|
||||
* Update `document_number_counters` PK (Requires careful migration of existing counters).
|
||||
* Initialize `workflow_definitions`.
|
||||
* **V1.6.0 -> V1.7.0**:
|
||||
* Run SQL script `9_lcbp3_v1_7_0.sql`
|
||||
* Migrate `document_number_counters` to 8-col composite PK.
|
||||
* Initialize `document_number_reservations`.
|
||||
* Update `json_schemas` with new columns.
|
||||
|
||||
---
|
||||
|
||||
@@ -1726,4 +1752,4 @@ LEFT JOIN rfa_approve_codes rac ON rr.rfa_approve_code_id = rac.id;
|
||||
|
||||
---
|
||||
|
||||
**End of Data Dictionary V1.5.1**
|
||||
**End of Data Dictionary V1.7.0**
|
||||
@@ -66,6 +66,8 @@ DROP TABLE IF EXISTS document_number_errors;
|
||||
|
||||
DROP TABLE IF EXISTS document_number_audit;
|
||||
|
||||
DROP TABLE IF EXISTS document_number_reservations;
|
||||
|
||||
-- ============================================================
|
||||
-- ส่วนที่ 2: ตาราง Junction (เชื่อมโยงข้อมูล M:N)
|
||||
-- ============================================================
|
||||
@@ -995,74 +997,58 @@ CREATE TABLE document_number_formats (
|
||||
CREATE TABLE document_number_counters (
|
||||
-- [v1.5.1] Composite Primary Key Columns (8 columns total)
|
||||
project_id INT NOT NULL COMMENT 'โครงการ',
|
||||
correspondence_type_id INT NULL COMMENT 'ประเภทเอกสาร (LETTER, RFA, TRANSMITTAL, etc.) NULL = default format for project',
|
||||
originator_organization_id INT NOT NULL COMMENT 'องค์กรผู้ส่ง',
|
||||
-- เปลี่ยนจาก NULL เป็น DEFAULT -1
|
||||
recipient_organization_id INT NOT NULL DEFAULT -1 COMMENT '[v1.5.1 NEW] องค์กรผู้รับ (-1 = ทุกองค์กร)',
|
||||
-- recipient_organization_id INT NULL COMMENT '[v1.5.1 NEW] องค์กรผู้รับ (NULL = ทุกองค์กร)',
|
||||
correspondence_type_id INT NOT NULL COMMENT 'ประเภทเอกสาร (LETTER, RFA, TRANSMITTAL, etc.)',
|
||||
-- เปลี่ยนจาก NULL เป็น DEFAULT 0
|
||||
recipient_organization_id INT NOT NULL DEFAULT 0 COMMENT '[v1.7.0] องค์กรผู้รับ 0 = no recipient (RFA)',
|
||||
sub_type_id INT DEFAULT 0 COMMENT '[v1.5.1 NEW] ประเภทย่อย สำหรับ TRANSMITTAL (0 = ไม่ระบุ)',
|
||||
rfa_type_id INT DEFAULT 0 COMMENT '[v1.5.1 NEW] ประเภท RFA เช่น SHD, RPT, MAT (0 = ไม่ใช่ RFA)',
|
||||
discipline_id INT DEFAULT 0 COMMENT 'สาขางาน เช่น TER, STR, GEO (0 = ไม่ระบุ)',
|
||||
current_year INT NOT NULL COMMENT 'ปี ค.ศ. ของตัวนับ (auto-reset ทุกปี)',
|
||||
reset_scope VARCHAR(20) NOT NULL COMMENT 'Scope of reset (PROJECT, ORGANIZATION, etc.)',
|
||||
-- Counter Data
|
||||
last_number INT DEFAULT 0 NOT NULL COMMENT 'เลขที่ล่าสุดที่ใช้ไปแล้ว (auto-increment)',
|
||||
version INT DEFAULT 0 NOT NULL COMMENT 'Optimistic Lock Version (TypeORM @VersionColumn)',
|
||||
last_number INT DEFAULT 0 COMMENT 'เลขที่ล่าสุดที่ใช้ไปแล้ว (auto-increment)',
|
||||
-- [v1.5.1 UPDATE] Primary Key: 5 columns -> 8 columns
|
||||
-- ใช้ COALESCE เพื่อรองรับ NULL ใน recipient_organization_id
|
||||
-- Metadata
|
||||
created_at DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
|
||||
updated_at DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
-- [v1.7.0 UPDATE] Primary Key: 5 columns -> 8 columns
|
||||
PRIMARY KEY (
|
||||
project_id,
|
||||
originator_organization_id,
|
||||
recipient_organization_id,
|
||||
-- [v1.5.1 NEW] Handle NULL values
|
||||
correspondence_type_id,
|
||||
sub_type_id,
|
||||
-- [v1.5.1 NEW]
|
||||
rfa_type_id,
|
||||
-- [v1.5.1 NEW]
|
||||
discipline_id,
|
||||
current_year
|
||||
reset_scope
|
||||
),
|
||||
-- Foreign Keys
|
||||
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (originator_organization_id) REFERENCES organizations (id) ON DELETE CASCADE,
|
||||
-- NOTE: recipient_organization_id uses -1 as sentinel for "all organizations"
|
||||
-- Therefore NO FK constraint is applied here (would fail for -1)
|
||||
FOREIGN KEY (correspondence_type_id) REFERENCES correspondence_types (id) ON DELETE CASCADE,
|
||||
-- [v1.5.1 NEW] Performance Indexes
|
||||
INDEX idx_counter_lookup (
|
||||
project_id,
|
||||
correspondence_type_id,
|
||||
current_year
|
||||
),
|
||||
INDEX idx_counter_org (
|
||||
originator_organization_id,
|
||||
current_year
|
||||
),
|
||||
-- [v1.5.1 NEW] Data Validation Constraints
|
||||
-- CONSTRAINT chk_last_number_positive CHECK (last_number >= 0),
|
||||
-- CONSTRAINT chk_current_year_valid CHECK (current_year BETWEEN 2020 AND 2100)
|
||||
-- Performance Indexes
|
||||
INDEX idx_counter_lookup (project_id, correspondence_type_id, reset_scope),
|
||||
INDEX idx_counter_org (originator_organization_id, reset_scope),
|
||||
-- Constraints
|
||||
CONSTRAINT chk_last_number_positive CHECK (last_number >= 0),
|
||||
CONSTRAINT chk_current_year CHECK (
|
||||
current_year BETWEEN 2020 AND 2100
|
||||
),
|
||||
CONSTRAINT chk_recipient_special CHECK (
|
||||
recipient_organization_id = -1
|
||||
OR recipient_organization_id > 0
|
||||
)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '[v1.5.1 UPDATE] ตารางเก็บ Running Number Counters - รองรับ 8-column composite PK';
|
||||
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_%')
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเก็บ Running Number Counters - รองรับ 8-column composite PK';
|
||||
|
||||
-- ==========================================================
|
||||
-- [v1.5.1 NEW] ตารางเก็บ Audit Trail สำหรับการสร้างเลขที่เอกสาร
|
||||
-- ตารางเก็บ Audit Trail สำหรับการสร้างเลขที่เอกสาร
|
||||
-- เพิ่มตาราง: document_number_audit
|
||||
-- เหตุผล: บันทึกประวัติการสร้างเลขที่ รองรับ audit requirement ≥ 7 ปี
|
||||
-- รองรับ: Req 3.11.8, Backend Plan T2.8
|
||||
-- ==========================================================
|
||||
CREATE TABLE document_number_audit (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID ของ audit record',
|
||||
id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID ของ audit record',
|
||||
-- Document Info
|
||||
document_id INT NOT NULL COMMENT 'ID ของเอกสารที่สร้างเลขที่ (correspondences.id)',
|
||||
generated_number VARCHAR(100) NOT NULL COMMENT 'เลขที่เอกสารที่สร้าง (ผลลัพธ์)',
|
||||
document_type VARCHAR(50),
|
||||
document_number VARCHAR(100) NOT NULL COMMENT 'เลขที่เอกสารที่สร้าง (ผลลัพธ์)',
|
||||
operation ENUM(
|
||||
'RESERVE',
|
||||
'CONFIRM',
|
||||
@@ -1070,24 +1056,42 @@ CREATE TABLE document_number_audit (
|
||||
'VOID_REPLACE',
|
||||
'CANCEL'
|
||||
) NOT NULL DEFAULT 'CONFIRM' COMMENT 'ประเภทการดำเนินการ',
|
||||
status ENUM(
|
||||
'RESERVED',
|
||||
'CONFIRMED',
|
||||
'CANCELLED',
|
||||
'VOID',
|
||||
'MANUAL'
|
||||
) NOT NULL DEFAULT 'RESERVED' COMMENT 'สถานะเลขที่เอกสาร',
|
||||
counter_key JSON NOT NULL COMMENT 'Counter key ที่ใช้ (JSON format) - 8 fields',
|
||||
metadata JSON COMMENT 'Additional context data',
|
||||
reservation_token VARCHAR(36) NULL,
|
||||
originator_organization_id INT NULL,
|
||||
recipient_organization_id INT NULL,
|
||||
|
||||
template_used VARCHAR(200) NOT NULL COMMENT 'Template ที่ใช้ในการสร้าง',
|
||||
old_value TEXT NULL,
|
||||
new_value TEXT NULL,
|
||||
-- User Info
|
||||
user_id INT NOT NULL COMMENT 'ผู้ขอสร้างเลขที่',
|
||||
ip_address VARCHAR(45) COMMENT 'IP address ของผู้ขอ (IPv4/IPv6)',
|
||||
user_agent TEXT COMMENT 'User agent string (browser info)',
|
||||
is_success BOOLEAN DEFAULT TRUE,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่/เวลาที่สร้าง',
|
||||
-- Performance & Error Tracking
|
||||
retry_count INT DEFAULT 0 COMMENT 'จำนวนครั้งที่ retry ก่อนสำเร็จ',
|
||||
lock_wait_ms INT COMMENT 'เวลารอ Redis lock (milliseconds)',
|
||||
total_duration_ms INT COMMENT 'เวลารวมทั้งหมดในการสร้าง (milliseconds)',
|
||||
fallback_used ENUM('NONE', 'DB_LOCK', 'RETRY') DEFAULT 'NONE' COMMENT 'Fallback strategy ที่ถูกใช้ (NONE=normal, DB_LOCK=Redis down, RETRY=conflict)',
|
||||
metadata JSON COMMENT 'Additional context data',
|
||||
|
||||
-- Indexes for performance
|
||||
INDEX idx_document_id (document_id),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_operation (operation),
|
||||
INDEX idx_document_number (document_number),
|
||||
INDEX idx_reservation_token (reservation_token),
|
||||
INDEX idx_created_at (created_at),
|
||||
INDEX idx_generated_number (generated_number),
|
||||
-- Foreign Keys
|
||||
FOREIGN KEY (document_id) REFERENCES correspondences (id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (user_id) REFERENCES users (user_id)
|
||||
@@ -1100,7 +1104,7 @@ CREATE TABLE document_number_audit (
|
||||
-- รองรับ: Req 3.11.6, Ops monitoring requirements
|
||||
-- ==========================================================
|
||||
CREATE TABLE document_number_errors (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID ของ error record',
|
||||
id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID ของ error record',
|
||||
-- Error Classification
|
||||
error_type ENUM(
|
||||
'LOCK_TIMEOUT',
|
||||
@@ -1130,6 +1134,43 @@ CREATE TABLE document_number_errors (
|
||||
INDEX idx_unresolved (resolved_at) -- Find unresolved errors
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '[v1.5.1 NEW] Error Log สำหรับ Document Numbering System';
|
||||
|
||||
-- =====================================================
|
||||
CREATE TABLE document_number_reservations (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
-- Reservation Details
|
||||
token VARCHAR(36) NOT NULL UNIQUE COMMENT 'UUID v4',
|
||||
document_number VARCHAR(100) NOT NULL UNIQUE,
|
||||
document_number_status ENUM('RESERVED', 'CONFIRMED', 'CANCELLED', 'VOID') NOT NULL DEFAULT 'RESERVED',
|
||||
-- Linkage
|
||||
document_id INT NULL COMMENT 'FK to documents (NULL until confirmed)',
|
||||
-- Context (for debugging)
|
||||
project_id INT NOT NULL,
|
||||
correspondence_type_id INT NOT NULL,
|
||||
originator_organization_id INT NOT NULL,
|
||||
recipient_organization_id INT DEFAULT 0,
|
||||
user_id INT NOT NULL,
|
||||
-- Timestamps
|
||||
reserved_at DATETIME(6) DEFAULT CURRENT_TIMESTAMP(6),
|
||||
expires_at DATETIME(6) NOT NULL,
|
||||
confirmed_at DATETIME(6) NULL,
|
||||
cancelled_at DATETIME(6) NULL,
|
||||
-- Audit
|
||||
ip_address VARCHAR(45),
|
||||
user_agent TEXT,
|
||||
metadata JSON NULL COMMENT 'Additional context',
|
||||
-- Indexes
|
||||
INDEX idx_token (token),
|
||||
INDEX idx_status (document_number_status),
|
||||
INDEX idx_status_expires (document_number_status, expires_at),
|
||||
INDEX idx_document_id (document_id),
|
||||
INDEX idx_user_id (user_id),
|
||||
INDEX idx_reserved_at (reserved_at),
|
||||
-- Foreign Keys
|
||||
FOREIGN KEY (document_id) REFERENCES correspondence_revisions(id) ON DELETE SET NULL,
|
||||
FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (correspondence_type_id) REFERENCES correspondence_types(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'Document Number Reservations - Two-Phase Commit';
|
||||
-- =====================================================
|
||||
-- 10. ⚙️ System & Logs (ระบบและ Log)
|
||||
-- =====================================================
|
||||
@@ -1391,8 +1432,6 @@ CREATE INDEX idx_document_number_counters_org ON document_number_counters (origi
|
||||
|
||||
CREATE INDEX idx_document_number_counters_type ON document_number_counters (correspondence_type_id);
|
||||
|
||||
CREATE INDEX idx_document_number_counters_year ON document_number_counters (current_year);
|
||||
|
||||
-- Indexes for tags
|
||||
CREATE INDEX idx_tags_name ON tags (tag_name);
|
||||
|
||||
@@ -1443,12 +1482,6 @@ CREATE INDEX idx_backup_logs_completed_at ON backup_logs (completed_at);
|
||||
-- Additional Composite Indexes for Performance
|
||||
-- =====================================================
|
||||
-- Composite index for document_number_counters for faster lookups
|
||||
CREATE INDEX idx_doc_counter_composite ON document_number_counters (
|
||||
project_id,
|
||||
originator_organization_id,
|
||||
correspondence_type_id,
|
||||
current_year
|
||||
);
|
||||
|
||||
-- Composite index for notifications for user-specific queries
|
||||
CREATE INDEX idx_notifications_user_unread ON notifications (user_id, is_read, created_at);
|
||||
@@ -2169,3 +2169,48 @@ VALUES (
|
||||
NOW()
|
||||
);
|
||||
|
||||
INSERT INTO `document_number_formats` (
|
||||
`id`,
|
||||
`project_id`,
|
||||
`correspondence_type_id`,
|
||||
`discipline_id`,
|
||||
`format_template`,
|
||||
`reset_sequence_yearly`,
|
||||
`example_number`,
|
||||
`padding_length`,
|
||||
`reset_annually`,
|
||||
`is_active`,
|
||||
`description`,
|
||||
`created_at`,
|
||||
`updated_at`
|
||||
)
|
||||
VALUES (
|
||||
1,
|
||||
1,
|
||||
NULL,
|
||||
0,
|
||||
'{ORG}-{RECIPIENT}-{SEQ:4}-{YEAR}',
|
||||
1,
|
||||
NULL,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
NULL,
|
||||
'2025-12-16 09:33:36',
|
||||
'2025-12-16 09:33:36'
|
||||
),
|
||||
(
|
||||
2,
|
||||
2,
|
||||
NULL,
|
||||
0,
|
||||
'{ORG}-{RECIPIENT}-{SEQ:4}-{YEAR}',
|
||||
1,
|
||||
NULL,
|
||||
4,
|
||||
1,
|
||||
1,
|
||||
NULL,
|
||||
'2025-12-16 09:34:10',
|
||||
'2025-12-16 09:34:10'
|
||||
);
|
||||
Reference in New Issue
Block a user