251223:1649 On going update to 1.7.0: Refoctory drawing Module & document number Module
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

This commit is contained in:
admin
2025-12-23 16:49:16 +07:00
parent 0d6432ab83
commit 7db6a003db
81 changed files with 4703 additions and 1449 deletions

View File

@@ -2,11 +2,18 @@
เอกสารนี้สรุปโครงสร้างตาราง,
FOREIGN KEYS (FK),
และ 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` ---
และ Constraints ที่สำคัญทั้งหมดในฐานข้อมูล LCBP3 - DMS (v1.7.0) เพื่อใช้เป็นเอกสารอ้างอิงสำหรับทีมพัฒนา Backend (NestJS) และ Frontend (Next.js) โดยอิงจาก Requirements และ SQL Script ล่าสุด ** สถานะ: ** FINAL GUIDELINE ** วันที่: ** 2025 -12 -23 ** อ้างอิง: ** Requirements v1.7.0 & FullStackJS Guidelines v1.7.0 ** Classification: ** Internal Technical Documentation ## 📝 สรุปรายการปรับปรุง (Summary of Changes in v1.7.0)
1. **Drawing Tables Restructuring**:
- `contract_drawing_subcat_cat_maps`: เปลี่ยน PK จาก composite เป็น `id` AUTO_INCREMENT พร้อม UNIQUE constraint
- `contract_drawings`: เปลี่ยน `sub_cat_id``map_cat_id` และเพิ่ม `volume_page`
- `shop_drawing_main_categories` และ `shop_drawing_sub_categories`: เพิ่ม `project_id` (เปลี่ยนจาก global เป็น project-specific)
- `shop_drawings`: ย้าย `title` ไปยัง `shop_drawing_revisions`
- `shop_drawing_revisions`: เพิ่ม `title` และ `legacy_drawing_number`
2. **AS Built Drawings (NEW)**: เพิ่มตาราง `asbuilt_drawings`, `asbuilt_drawing_revisions`, `asbuilt_revision_shop_revisions_refs`, และ `asbuilt_drawing_revision_attachments`
3. **Document Numbering Overhaul**: ปรับปรุงโครงสร้าง `document_number_counters` เปลี่ยน PK เป็น Composite 8 columns และใช้ `reset_scope` แทน `current_year`
4. **Audit & Error Logging**: ปรับปรุงตาราง `document_number_audit`, `document_number_errors` และเพิ่ม `document_number_reservations`
5. **JSON Schemas**: เพิ่ม columns `version`, `table_name`, `ui_schema`, `virtual_columns`, `migration_script` ในตาราง `json_schemas`
6. **Schema Cleanup**: ลบ `correspondence_id` ออกจาก `rfa_revisions` และปรับปรุง Virtual Columns ใน `correspondence_revisions` ---
## **1. 🏢 Core & Master Data Tables (องค์กร, โครงการ, สัญญา)**
@@ -718,19 +725,21 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
---
### 5.4 contract_drawing_subcat_cat_maps
### 5.4 contract_drawing_subcat_cat_maps (UPDATE v1.7.0)
**Purpose**: Junction table mapping sub-categories to main categories (M:N)
| Column Name | Data Type | Constraints | Description |
| ----------- | --------- | --------------- | -------------------------- |
| project_id | INT | PRIMARY KEY, FK | Reference to projects |
| sub_cat_id | INT | PRIMARY KEY, FK | Reference to sub-category |
| cat_id | INT | PRIMARY KEY, FK | Reference to main category |
| Column Name | Data Type | Constraints | Description |
| ----------- | --------- | ------------------------------- | -------------------------- |
| **id** | **INT** | **PRIMARY KEY, AUTO_INCREMENT** | **Unique mapping ID** |
| project_id | INT | NOT NULL, FK | Reference to projects |
| sub_cat_id | INT | NOT NULL, FK | Reference to sub-category |
| cat_id | INT | NOT NULL, FK | Reference to main category |
**Indexes**:
* PRIMARY KEY (project_id, sub_cat_id, cat_id)
* PRIMARY KEY (id)
* **UNIQUE KEY (project_id, sub_cat_id, cat_id)**
* FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
* FOREIGN KEY (sub_cat_id) REFERENCES contract_drawing_sub_cats(id) ON DELETE CASCADE
* FOREIGN KEY (cat_id) REFERENCES contract_drawing_cats(id) ON DELETE CASCADE
@@ -740,47 +749,49 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
**Relationships**:
* Parent: projects, contract_drawing_sub_cats, contract_drawing_cats
* Referenced by: contract_drawings
**Business Rules**:
* Allows flexible categorization
* One sub-category can belong to multiple main categories
* All three fields required for uniqueness
* Composite uniqueness enforced via UNIQUE constraint
---
### 5.5 contract_drawings
### 5.5 contract_drawings (UPDATE v1.7.0)
**Purpose**: Master table for contract drawings (from contract specifications)
| Column Name | Data Type | Constraints | Description |
| ----------- | ------------ | ----------------------------------- | ------------------------- |
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique drawing ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| condwg_no | VARCHAR(255) | NOT NULL | Contract drawing number |
| title | VARCHAR(255) | NOT NULL | Drawing title |
| sub_cat_id | INT | NULL, FK | Reference to sub-category |
| volume_id | INT | NULL, FK | Reference to volume |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
| deleted_at | DATETIME | NULL | Soft delete timestamp |
| updated_by | INT | NULL, FK | User who last updated |
| Column Name | Data Type | Constraints | Description |
| --------------- | ------------ | ----------------------------------- | ---------------------------------------- |
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique drawing ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| condwg_no | VARCHAR(255) | NOT NULL | Contract drawing number |
| title | VARCHAR(255) | NOT NULL | Drawing title |
| **map_cat_id** | **INT** | **NULL, FK** | **[CHANGED] Reference to mapping table** |
| volume_id | INT | NULL, FK | Reference to volume |
| **volume_page** | **INT** | **NULL** | **[NEW] Page number within volume** |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
| deleted_at | DATETIME | NULL | Soft delete timestamp |
| updated_by | INT | NULL, FK | User who last updated |
**Indexes**:
* PRIMARY KEY (id)
* FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
* FOREIGN KEY (sub_cat_id) REFERENCES contract_drawing_sub_cats(id) ON DELETE RESTRICT
* **FOREIGN KEY (map_cat_id) REFERENCES contract_drawing_subcat_cat_maps(id) ON DELETE RESTRICT**
* FOREIGN KEY (volume_id) REFERENCES contract_drawing_volumes(id) ON DELETE RESTRICT
* FOREIGN KEY (updated_by) REFERENCES users(user_id)
* UNIQUE KEY (project_id, condwg_no)
* INDEX (sub_cat_id)
* INDEX (map_cat_id)
* INDEX (volume_id)
* INDEX (deleted_at)
**Relationships**:
* Parent: projects, contract_drawing_sub_cats, contract_drawing_volumes, users
* Parent: projects, contract_drawing_subcat_cat_maps, contract_drawing_volumes, users
* Referenced by: shop_drawing_revision_contract_refs, contract_drawing_attachments
**Business Rules**:
@@ -789,16 +800,18 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
* Represents baseline/contract drawings
* Referenced by shop drawings for compliance tracking
* Soft delete preserves history
* **map_cat_id references the mapping table for flexible categorization**
---
### 5.6 shop_drawing_main_categories
### 5.6 shop_drawing_main_categories (UPDATE v1.7.0)
**Purpose**: Master table for shop drawing main categories (discipline-level)
| Column Name | Data Type | Constraints | Description |
| ------------------ | ------------ | ----------------------------------- | ------------------------------------ |
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique category ID |
| **project_id** | **INT** | **NOT NULL, FK** | **[NEW] Reference to projects** |
| main_category_code | VARCHAR(50) | NOT NULL, UNIQUE | Category code (ARCH, STR, MEP, etc.) |
| main_category_name | VARCHAR(255) | NOT NULL | Category name |
| description | TEXT | NULL | Category description |
@@ -810,31 +823,33 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
**Indexes**:
* PRIMARY KEY (id)
* **FOREIGN KEY (project_id) REFERENCES projects(id)**
* UNIQUE (main_category_code)
* INDEX (is_active)
* INDEX (sort_order)
**Relationships**:
* Referenced by: shop_drawing_sub_categories, shop_drawings
* **Parent: projects**
* Referenced by: shop_drawings, asbuilt_drawings
**Business Rules**:
* Global categories (not project-specific)
* **[CHANGED] Project-specific categories (was global)**
* Typically represents engineering disciplines
---
### 5.7 shop_drawing_sub_categories
### 5.7 shop_drawing_sub_categories (UPDATE v1.7.0)
**Purpose**: Master table for shop drawing sub-categories (component-level)
| Column Name | Data Type | Constraints | Description |
| ----------------- | ------------ | ----------------------------------- | ----------------------------------------------- |
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique sub-category ID |
| **project_id** | **INT** | **NOT NULL, FK** | **[NEW] Reference to projects** |
| sub_category_code | VARCHAR(50) | NOT NULL, UNIQUE | Sub-category code (STR-COLUMN, ARCH-DOOR, etc.) |
| sub_category_name | VARCHAR(255) | NOT NULL | Sub-category name |
| main_category_id | INT | NOT NULL, FK | Reference to main category |
| description | TEXT | NULL | Sub-category description |
| sort_order | INT | DEFAULT 0 | Display order |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
@@ -844,26 +859,25 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
**Indexes**:
* PRIMARY KEY (id)
* **FOREIGN KEY (project_id) REFERENCES projects(id)**
* UNIQUE (sub_category_code)
* FOREIGN KEY (main_category_id) REFERENCES shop_drawing_main_categories(id)
* INDEX (main_category_id)
* INDEX (is_active)
* INDEX (sort_order)
**Relationships**:
* Parent: shop_drawing_main_categories
* Referenced by: shop_drawings
* **Parent: projects**
* Referenced by: shop_drawings, asbuilt_drawings
**Business Rules**:
* Global sub-categories (not project-specific)
* Hierarchical under main categories
* **[CHANGED] Project-specific sub-categories (was global)**
* **[REMOVED] No longer hierarchical under main categories**
* Represents specific drawing types or components
---
### 5.8 shop_drawings
### 5.8 shop_drawings (UPDATE v1.7.0)
**Purpose**: Master table for shop drawings (contractor-submitted)
@@ -872,7 +886,6 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique drawing ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| drawing_number | VARCHAR(100) | NOT NULL, UNIQUE | Shop drawing number |
| title | VARCHAR(500) | NOT NULL | Drawing title |
| main_category_id | INT | NOT NULL, FK | Reference to main category |
| sub_category_id | INT | NOT NULL, FK | Reference to sub-category |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
@@ -904,22 +917,25 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
* Represents contractor shop drawings
* Can have multiple revisions
* Soft delete preserves history
* **[CHANGED] Title moved to shop_drawing_revisions table**
---
### 5.9 shop_drawing_revisions
### 5.9 shop_drawing_revisions (UPDATE v1.7.0)
**Purpose**: Child table storing revision history of shop drawings (1:N)
| Column Name | Data Type | Constraints | Description |
| --------------- | ----------- | --------------------------- | ------------------------------ |
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
| shop_drawing_id | INT | NOT NULL, FK | Master shop drawing ID |
| revision_number | INT | NOT NULL | Revision sequence (0, 1, 2...) |
| revision_label | VARCHAR(10) | NULL | Display revision (A, B, C...) |
| revision_date | DATE | NULL | Revision date |
| description | TEXT | NULL | Revision description/changes |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Revision creation timestamp |
| Column Name | Data Type | Constraints | Description |
| ------------------------- | ---------------- | --------------------------- | ---------------------------------------- |
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
| shop_drawing_id | INT | NOT NULL, FK | Master shop drawing ID |
| revision_number | INT | NOT NULL | Revision sequence (0, 1, 2...) |
| revision_label | VARCHAR(10) | NULL | Display revision (A, B, C...) |
| revision_date | DATE | NULL | Revision date |
| **title** | **VARCHAR(500)** | **NOT NULL** | **[NEW] Drawing title** |
| description | TEXT | NULL | Revision description/changes |
| **legacy_drawing_number** | **VARCHAR(100)** | **NULL** | **[NEW] Original/legacy drawing number** |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Revision creation timestamp |
**Indexes**:
@@ -931,7 +947,7 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
**Relationships**:
* Parent: shop_drawings
* Referenced by: rfa_items, shop_drawing_revision_contract_refs, shop_drawing_revision_attachments
* Referenced by: rfa_items, shop_drawing_revision_contract_refs, shop_drawing_revision_attachments, asbuilt_revision_shop_revisions_refs
**Business Rules**:
@@ -939,6 +955,8 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
* Each revision can reference multiple contract drawings
* Each revision can have multiple file attachments
* Linked to RFAs for approval tracking
* **[NEW] Title stored at revision level for version-specific naming**
* **[NEW] legacy_drawing_number supports data migration from old systems**
---
@@ -970,6 +988,148 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
---
### 5.11 asbuilt_drawings (NEW v1.7.0)
**Purpose**: Master table for AS Built drawings (final construction records)
| Column Name | Data Type | Constraints | Description |
| ---------------- | ------------ | ----------------------------------- | -------------------------- |
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique drawing ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| drawing_number | VARCHAR(100) | NOT NULL, UNIQUE | AS Built drawing number |
| main_category_id | INT | NOT NULL, FK | Reference to main category |
| sub_category_id | INT | NOT NULL, FK | Reference to sub-category |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
| deleted_at | DATETIME | NULL | Soft delete timestamp |
| updated_by | INT | NULL, FK | User who last updated |
**Indexes**:
* PRIMARY KEY (id)
* UNIQUE (drawing_number)
* FOREIGN KEY (project_id) REFERENCES projects(id)
* FOREIGN KEY (main_category_id) REFERENCES shop_drawing_main_categories(id)
* FOREIGN KEY (sub_category_id) REFERENCES shop_drawing_sub_categories(id)
* FOREIGN KEY (updated_by) REFERENCES users(user_id)
* INDEX (project_id)
* INDEX (main_category_id)
* INDEX (sub_category_id)
* INDEX (deleted_at)
**Relationships**:
* Parent: projects, shop_drawing_main_categories, shop_drawing_sub_categories, users
* Children: asbuilt_drawing_revisions
**Business Rules**:
* Drawing numbers are globally unique across all projects
* Represents final as-built construction drawings
* Can have multiple revisions
* Soft delete preserves history
* Uses same category structure as shop drawings
---
### 5.12 asbuilt_drawing_revisions (NEW v1.7.0)
**Purpose**: Child table storing revision history of AS Built drawings (1:N)
| Column Name | Data Type | Constraints | Description |
| --------------------- | ------------ | --------------------------- | ------------------------------ |
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
| asbuilt_drawing_id | INT | NOT NULL, FK | Master AS Built drawing ID |
| revision_number | INT | NOT NULL | Revision sequence (0, 1, 2...) |
| revision_label | VARCHAR(10) | NULL | Display revision (A, B, C...) |
| revision_date | DATE | NULL | Revision date |
| title | VARCHAR(500) | NOT NULL | Drawing title |
| description | TEXT | NULL | Revision description/changes |
| legacy_drawing_number | VARCHAR(100) | NULL | Original/legacy drawing number |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Revision creation timestamp |
**Indexes**:
* PRIMARY KEY (id)
* FOREIGN KEY (asbuilt_drawing_id) REFERENCES asbuilt_drawings(id) ON DELETE CASCADE
* UNIQUE KEY (asbuilt_drawing_id, revision_number)
* INDEX (revision_date)
**Relationships**:
* Parent: asbuilt_drawings
* Referenced by: asbuilt_revision_shop_revisions_refs, asbuilt_drawing_revision_attachments
**Business Rules**:
* Revision numbers are sequential starting from 0
* Each revision can reference multiple shop drawing revisions
* Each revision can have multiple file attachments
* Title stored at revision level for version-specific naming
* legacy_drawing_number supports data migration from old systems
---
### 5.13 asbuilt_revision_shop_revisions_refs (NEW v1.7.0)
**Purpose**: Junction table linking AS Built drawing revisions to shop drawing revisions (M:N)
| Column Name | Data Type | Constraints | Description |
| --------------------------- | --------- | --------------- | ---------------------------------- |
| asbuilt_drawing_revision_id | INT | PRIMARY KEY, FK | Reference to AS Built revision |
| shop_drawing_revision_id | INT | PRIMARY KEY, FK | Reference to shop drawing revision |
**Indexes**:
* PRIMARY KEY (asbuilt_drawing_revision_id, shop_drawing_revision_id)
* FOREIGN KEY (asbuilt_drawing_revision_id) REFERENCES asbuilt_drawing_revisions(id) ON DELETE CASCADE
* FOREIGN KEY (shop_drawing_revision_id) REFERENCES shop_drawing_revisions(id) ON DELETE CASCADE
* INDEX (shop_drawing_revision_id)
**Relationships**:
* Parent: asbuilt_drawing_revisions, shop_drawing_revisions
**Business Rules**:
* Tracks which shop drawings each AS Built drawing revision is based on
* Maintains construction document lineage
* One AS Built revision can reference multiple shop drawing revisions
* Supports traceability from final construction to approved shop drawings
---
### 5.14 asbuilt_drawing_revision_attachments (NEW v1.7.0)
**Purpose**: Junction table linking AS Built drawing revisions to file attachments (M:N)
| Column Name | Data Type | Constraints | Description |
| --------------------------- | ------------------------------------- | --------------- | ------------------------------------- |
| asbuilt_drawing_revision_id | INT | PRIMARY KEY, FK | Reference to AS Built revision |
| attachment_id | INT | PRIMARY KEY, FK | Reference to attachment file |
| file_type | ENUM('PDF', 'DWG', 'SOURCE', 'OTHER') | NULL | File type classification |
| is_main_document | BOOLEAN | DEFAULT FALSE | Main document flag (1 = primary file) |
**Indexes**:
* PRIMARY KEY (asbuilt_drawing_revision_id, attachment_id)
* FOREIGN KEY (asbuilt_drawing_revision_id) REFERENCES asbuilt_drawing_revisions(id) ON DELETE CASCADE
* FOREIGN KEY (attachment_id) REFERENCES attachments(id) ON DELETE CASCADE
* INDEX (attachment_id)
**Relationships**:
* Parent: asbuilt_drawing_revisions, attachments
**Business Rules**:
* Each AS Built revision can have multiple file attachments
* File types: PDF (documents), DWG (CAD files), SOURCE (source files), OTHER (miscellaneous)
* One attachment can be marked as main document per revision
* Cascade delete when revision is deleted
---
## **6. 🔄 Circulations Tables (ใบเวียนภายใน)**
### 6.1 circulation_status_codes
@@ -1281,6 +1441,7 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
| correspondence_type_id | INT | NOT NULL, FK | Reference to correspondence_types |
| format_string | VARCHAR(100) | NOT NULL | Format pattern (e.g., {ORG}-{TYPE}-{YYYY}-#) |
| description | TEXT | NULL | Format description |
| reset_annually | BOOLEAN | DEFAULT TRUE | Start sequence new every year |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
**Indexes**:
@@ -1341,17 +1502,20 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
| Column Name | Data Type | Constraints | Description |
| :------------------------- | :----------- | :----------------- | :-------------------------------------- |
| id | INT | PK, AI | ID ของ audit record |
| document_id | INT | NOT NULL, FK | ID ของเอกสารที่สร้างเลขที่ |
| document_id | INT | NULL, FK | ID ของเอกสารที่สร้างเลขที่ (NULL if failed) |
| 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 การจอง |
| idempotency_key | VARCHAR(128) | NULL | Idempotency Key from request |
| originator_organization_id | INT | NULL | องค์กรผู้ส่ง |
| recipient_organization_id | INT | NULL | องค์กรผู้รับ |
| template_used | VARCHAR(200) | NOT NULL | Template ที่ใช้ในการสร้าง |
| user_id | INT | NOT NULL, FK | ผู้ขอสร้างเลขที่ |
| old_value | TEXT | NULL | Previous value |
| new_value | TEXT | NULL | New value |
| user_id | INT | NULL, FK | ผู้ขอสร้างเลขที่ |
| is_success | BOOLEAN | DEFAULT TRUE | สถานะความสำเร็จ |
| created_at | TIMESTAMP | DEFAULT NOW | วันที่/เวลาที่สร้าง |
| total_duration_ms | INT | NULL | เวลารวมทั้งหมดในการสร้าง (ms) |

View File

@@ -1,5 +1,5 @@
-- ==========================================================
-- DMS v1.6.0 Document Management System Database
-- DMS v1.7.0 Document Management System Database
-- Deploy Script Schema
-- Server: Container Station on QNAP TS-473A
-- Database service: MariaDB 11.8
@@ -10,11 +10,22 @@
-- reverse proxy: jc21/nginx-proxy-manager:latest
-- cron service: n8n
-- ==========================================================
-- [v1.6.0 UPDATE] Refactor Schema
-- Update: Upgraded from v1.5.1
-- Last Updated: 2025-12-13
-- [v1.7.0 UPDATE] Refactor Schema
-- Update: Upgraded from v1.6.0
-- Last Updated: 2025-12-18
-- Major Changes:
-- 1. ปรับปรุง: corespondences, correspondence_revisions, correspondence_recipients, rfas, rfa_revisions
-- 1. ปรับปรุง:
-- 1.1 TABLE contract_drawings
-- 1.2 TABLE contract_drawing_subcat_cat_maps
-- 1.3 TABLE shop_drawing_sub_categories
-- 1.4 TABLE shop_drawing_main_categories
-- 1.5 TABLE shop_drawings
-- 1.6 TABLE shop_drawing_revisions
-- 2. เพิ่ม:
-- 2.1 TABLE asbuilt_drawings
-- 2.2 TABLE asbuilt_drawing_revisions
-- 2.3 TABLE asbuilt_revision_shop_revisions_refs
-- 2.4 TABLE asbuilt_drawing_revision_attachments
-- ==========================================================
SET NAMES utf8mb4;
@@ -73,6 +84,8 @@ DROP TABLE IF EXISTS document_number_reservations;
-- ============================================================
DROP TABLE IF EXISTS correspondence_tags;
DROP TABLE IF EXISTS asbuilt_revision_shop_revisions_refs;
DROP TABLE IF EXISTS shop_drawing_revision_contract_refs;
DROP TABLE IF EXISTS contract_drawing_subcat_cat_maps;
@@ -86,6 +99,8 @@ DROP TABLE IF EXISTS circulation_attachments;
DROP TABLE IF EXISTS shop_drawing_revision_attachments;
DROP TABLE IF EXISTS asbuilt_drawing_revision_attachments;
DROP TABLE IF EXISTS correspondence_attachments;
DROP TABLE IF EXISTS attachments;
@@ -113,6 +128,8 @@ DROP TABLE IF EXISTS transmittal_items;
DROP TABLE IF EXISTS shop_drawing_revisions;
DROP TABLE IF EXISTS asbuilt_drawing_revisions;
DROP TABLE IF EXISTS rfa_items;
DROP TABLE IF EXISTS rfa_revisions;
@@ -135,6 +152,8 @@ DROP TABLE IF EXISTS contract_drawings;
DROP TABLE IF EXISTS shop_drawings;
DROP TABLE IF EXISTS asbuilt_drawings;
DROP TABLE IF EXISTS rfas;
DROP TABLE IF EXISTS correspondences;
@@ -720,12 +739,7 @@ CREATE TABLE contract_drawing_subcat_cat_maps (
project_id INT COMMENT 'ID ของโครงการ',
sub_cat_id INT COMMENT 'ID ของหมวดหมู่ย่อย',
cat_id INT COMMENT 'ID ของหมวดหมู่หลัก',
PRIMARY KEY (
id,
project_id,
sub_cat_id,
cat_id
),
UNIQUE KEY ux_map_unique (project_id, sub_cat_id, cat_id),
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE,
FOREIGN KEY (sub_cat_id) REFERENCES contract_drawing_sub_cats (id) ON DELETE CASCADE,
FOREIGN KEY (cat_id) REFERENCES contract_drawing_cats (id) ON DELETE CASCADE
@@ -821,6 +835,49 @@ CREATE TABLE shop_drawing_revision_contract_refs (
FOREIGN KEY (contract_drawing_id) REFERENCES contract_drawings (id) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเชื่อมระหว่าง shop_drawing_revisions กับ contract_drawings (M :N)';
-- ตาราง Master เก็บข้อมูล "AS Built"
CREATE TABLE asbuilt_drawings (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง',
project_id INT NOT NULL COMMENT 'โครงการ',
drawing_number VARCHAR(100) NOT NULL UNIQUE COMMENT 'เลขที่ AS Built Drawing',
main_category_id INT NOT NULL COMMENT 'หมวดหมู่หลัก',
sub_category_id INT NOT NULL COMMENT 'หมวดหมู่ย่อย',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้าง',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'วันที่แก้ไขล่าสุด',
deleted_at DATETIME NULL COMMENT 'วันที่ลบ',
updated_by INT COMMENT 'ผู้แก้ไขล่าสุด',
FOREIGN KEY (project_id) REFERENCES projects (id),
FOREIGN KEY (main_category_id) REFERENCES shop_drawing_main_categories (id),
FOREIGN KEY (sub_category_id) REFERENCES shop_drawing_sub_categories (id)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง Master เก็บข้อมูล "แบบก่อสร้าง"';
-- ตาราง "ลูก" เก็บประวัติ (Revisions) ของ shop_drawings (1:N)
CREATE TABLE asbuilt_drawing_revisions (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของ Revision',
asbuilt_drawing_id INT NOT NULL COMMENT 'Master ID',
revision_number INT NOT NULL COMMENT 'หมายเลข Revision (เช่น 0, 1, 2...)',
revision_label VARCHAR(10) COMMENT 'Revision ที่แสดง (เช่น A, B, 1.1)',
revision_date DATE COMMENT 'วันที่ของ Revision',
title VARCHAR(500) NOT NULL COMMENT 'ชื่อแบบ',
description TEXT COMMENT 'คำอธิบายการแก้ไข',
legacy_drawing_number VARCHAR(100) NULL COMMENT 'เลขที่เดิมของ AS Built Drawing',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้าง',
FOREIGN KEY (asbuilt_drawing_id) REFERENCES asbuilt_drawings (id) ON DELETE CASCADE,
UNIQUE KEY ux_sd_rev_drawing_revision (asbuilt_drawing_id, revision_number)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง "ลูก" เก็บประวัติ (Revisions) ของ asbuilt_drawings (1 :N)';
-- ตารางเชื่อมระหว่าง asbuilt_drawing_revisions กับ shop_drawings (M:N)
CREATE TABLE asbuilt_revision_shop_revisions_refs (
asbuilt_drawing_revision_id INT COMMENT 'ID ของ AS Built Drawing Revision',
shop_drawing_revision_id INT COMMENT 'ID ของ Shop Drawing Revision',
PRIMARY KEY (
asbuilt_drawing_revision_id,
shop_drawing_revision_id
),
FOREIGN KEY (asbuilt_drawing_revision_id) REFERENCES asbuilt_drawing_revisions (id) ON DELETE CASCADE,
FOREIGN KEY (shop_drawing_revision_id) REFERENCES shop_drawing_revisions (id) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเชื่อมระหว่าง asbuilt_drawing_revisions กับ shop_drawing_revisions (M :N)';
-- =====================================================
-- 6. 🔄 Circulations (ใบเวียนภายใน)
-- =====================================================
@@ -926,6 +983,25 @@ CREATE TABLE circulation_attachments (
FOREIGN KEY (attachment_id) REFERENCES attachments (id) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเชื่อม circulations กับ attachments (M :N)';
-- ตารางเชื่อม shop_drawing_revisions กับ attachments (M:N)
CREATE TABLE asbuilt_drawing_revision_attachments (
asbuilt_drawing_revision_id INT COMMENT 'ID ของ asbuilt Drawing Revision',
attachment_id INT COMMENT 'ID ของไฟล์แนบ',
file_type ENUM(
'PDF',
'DWG',
'SOURCE',
'OTHER '
) COMMENT 'ประเภทไฟล์',
is_main_document BOOLEAN DEFAULT FALSE COMMENT '(1 = ไฟล์หลัก)',
PRIMARY KEY (
asbuilt_drawing_revision_id,
attachment_id
),
FOREIGN KEY (asbuilt_drawing_revision_id) REFERENCES asbuilt_drawing_revisions (id) ON DELETE CASCADE,
FOREIGN KEY (attachment_id) REFERENCES attachments (id) ON DELETE CASCADE
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางเชื่อม asbuilt_drawing_revisions กับ attachments (M :N)';
-- ตารางเชื่อม shop_drawing_revisions กับ attachments (M:N)
CREATE TABLE shop_drawing_revision_attachments (
shop_drawing_revision_id INT COMMENT 'ID ของ Shop Drawing Revision',
@@ -973,13 +1049,10 @@ CREATE TABLE document_number_formats (
project_id INT NOT NULL COMMENT 'โครงการ',
correspondence_type_id INT NULL COMMENT 'ประเภทเอกสาร',
discipline_id INT DEFAULT 0 COMMENT 'สาขางาน (0 = ทุกสาขา/ไม่ระบุ)',
format_template VARCHAR(255) NOT NULL COMMENT 'รูปแบบ Template (เช่น {ORG}-{RECIPIENT}-{SEQ:4}-{YEAR:BE})',
reset_sequence_yearly TINYINT(1) DEFAULT 1,
example_number VARCHAR(100) COMMENT 'ตัวอย่างเลขที่ได้จาก Template',
padding_length INT DEFAULT 4 COMMENT 'ความยาวของลำดับเลข (Padding)',
format_string VARCHAR(100) NOT NULL COMMENT 'Format pattern (e.g., {ORG}-{TYPE}-{YYYY}-#)',
description TEXT COMMENT 'Format description',
reset_annually BOOLEAN DEFAULT TRUE COMMENT 'เริ่มนับใหม่ทุกปี',
is_active BOOLEAN DEFAULT TRUE COMMENT 'สถานะการใช้งาน',
description TEXT COMMENT 'คำอธิบายรูปแบบนี้',
is_active TINYINT(1) DEFAULT 1 COMMENT 'สถานะการใช้งาน',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้าง',
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'วันที่แก้ไขล่าสุด',
FOREIGN KEY (project_id) REFERENCES projects (id) ON DELETE CASCADE,
@@ -1038,10 +1111,11 @@ CREATE TABLE document_number_counters (
-- 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_%')
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';
-- ==========================================================
@@ -1052,7 +1126,7 @@ CREATE TABLE document_number_counters (
CREATE TABLE document_number_audit (
id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'ID ของ audit record',
-- Document Info
document_id INT NOT NULL COMMENT 'ID ของเอกสารที่สร้างเลขที่ (correspondences.id)',
document_id INT NULL COMMENT 'ID ของเอกสารที่สร้างเลขที่ (correspondences.id) - NULL if failed/reserved',
document_type VARCHAR(50),
document_number VARCHAR(100) NOT NULL COMMENT 'เลขที่เอกสารที่สร้าง (ผลลัพธ์)',
operation ENUM(
@@ -1062,23 +1136,23 @@ CREATE TABLE document_number_audit (
'VOID_REPLACE',
'CANCEL'
) NOT NULL DEFAULT 'CONFIRM' COMMENT 'ประเภทการดำเนินการ',
status ENUM(
STATUS ENUM(
'RESERVED',
'CONFIRMED',
'CANCELLED',
'CANCELLED',
'VOID',
'MANUAL'
) NOT NULL DEFAULT 'RESERVED' COMMENT 'สถานะเลขที่เอกสาร',
counter_key JSON NOT NULL COMMENT 'Counter key ที่ใช้ (JSON format) - 8 fields',
reservation_token VARCHAR(36) NULL,
idempotency_key VARCHAR(128) NULL COMMENT 'Idempotency Key from request',
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,
old_value TEXT NULL COMMENT 'Previous value for audit',
new_value TEXT NULL COMMENT 'New value for audit',
-- User Info
user_id INT NOT NULL COMMENT 'ผู้ขอสร้างเลขที่',
user_id INT 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,
@@ -1089,14 +1163,14 @@ CREATE TABLE document_number_audit (
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_status (STATUS),
INDEX idx_operation (operation),
INDEX idx_document_number (document_number),
INDEX idx_reservation_token (reservation_token),
INDEX idx_idempotency_key (idempotency_key),
INDEX idx_created_at (created_at),
-- Foreign Keys
FOREIGN KEY (document_id) REFERENCES correspondences (id) ON DELETE CASCADE,
@@ -1172,11 +1246,13 @@ CREATE TABLE document_number_reservations (
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
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)
-- =====================================================
@@ -1488,7 +1564,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
-- Composite index for notifications for user-specific queries
CREATE INDEX idx_notifications_user_unread ON notifications (user_id, is_read, created_at);
@@ -1902,4 +1977,8 @@ CREATE INDEX idx_correspondences_project_type ON correspondences (project_id, co
CREATE INDEX idx_corr_revisions_status_current ON correspondence_revisions (correspondence_status_id, is_current);
CREATE INDEX IDX_AUDIT_DOC_ID ON document_number_audit (document_id);
CREATE INDEX IDX_AUDIT_STATUS ON document_number_audit (status);
CREATE INDEX IDX_AUDIT_OPERATION ON document_number_audit (operation);
SET FOREIGN_KEY_CHECKS = 1;

File diff suppressed because it is too large Load Diff