690514:2019 204-rfa-approval-refactor #01
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
---
|
||||
title: 'Data & Storage: Data Dictionary and Data Model Architecture'
|
||||
version: 1.8.7
|
||||
version: 1.9.0
|
||||
status: released
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2026-04-14
|
||||
@@ -84,7 +84,7 @@ erDiagram
|
||||
|
||||
---
|
||||
|
||||
# 3. Data Dictionary V1.8.0
|
||||
# 3. Data Dictionary V1.9.0
|
||||
|
||||
> หมายเหตุ: PK = Primary Key, FK = Foreign Key, AI = AUTO_INCREMENT. รูปแบบ Soft Delete จะปรากฏ Column `deleted_at DATETIME NULL` เป็นมาตรฐาน
|
||||
|
||||
@@ -165,14 +165,14 @@ erDiagram
|
||||
### 2.2 roles
|
||||
- - Purpose **: MASTER TABLE defining system roles WITH scope levels | COLUMN Name | Data TYPE | Constraints | Description | | ----------- | ------------ | --------------------------- | ---------------------------------------------------- |
|
||||
| role_id | INT | PRIMARY KEY,
|
||||
AUTO_INCREMENT | UNIQUE identifier FOR role | | role_name | VARCHAR(100) | NOT NULL | Role name (e.g., 'Superadmin', 'Document Control') | | scope | ENUM | NOT NULL | Scope LEVEL: GLOBAL,
|
||||
AUTO_INCREMENT | UNIQUE identifier FOR role | | **uuid** | **UUID** | **NOT NULL, DEFAULT (UUID()), UNIQUE** | **[delta-11] UUID Public Identifier (ADR-019) — ใช้ใน API Response / distribution_recipients** | | role_name | VARCHAR(100) | NOT NULL | Role name (e.g., 'Superadmin', 'Document Control') | | scope | ENUM | NOT NULL | Scope LEVEL: GLOBAL,
|
||||
Organization,
|
||||
Project,
|
||||
Contract | | description | TEXT | NULL | Role description | | is_system | BOOLEAN | DEFAULT FALSE | System role flag (cannot be deleted) |
|
||||
| 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 |
|
||||
** INDEXES **: - PRIMARY KEY (role_id) - INDEX (scope) ** Relationships \*\*: - Referenced by: role_permissions,
|
||||
** INDEXES **: - PRIMARY KEY (role_id) - **UNIQUE INDEX idx_roles_uuid (uuid) [delta-11]** - INDEX (scope) ** Relationships \*\*: - Referenced by: role_permissions,
|
||||
user_assignments ---
|
||||
|
||||
### 2.3 permissions
|
||||
@@ -2337,4 +2337,258 @@ PENDING_REVIEW ──→ VERIFIED ──→ IMPORTED (terminal)
|
||||
|
||||
---
|
||||
|
||||
**End of Data Dictionary V1.8.0**
|
||||
**End of Data Dictionary V1.9.0**
|
||||
|
||||
---
|
||||
|
||||
## **20. 🔍 RFA Approval System Tables (NEW v1.9.0)**
|
||||
|
||||
> Feature Branch: `1-rfa-approval-refactor` | Schema File: `lcbp3-v1.9.0-rfa-approval-schema.sql`
|
||||
|
||||
### 20.1 review_teams
|
||||
|
||||
**Purpose**: ทีมตรวจสอบแยกตาม Discipline สำหรับ RFA Approval
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| --------------------- | ------------ | ------------------------------- | --------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal ID |
|
||||
| uuid | UUID | NOT NULL, UNIQUE, DEFAULT UUID()| UUID Public Identifier (ADR-019) |
|
||||
| project_id | INT | NOT NULL, FK | Reference to projects |
|
||||
| name | VARCHAR(100) | NOT NULL | Team name |
|
||||
| description | VARCHAR(255) | NULL | Team description |
|
||||
| default_for_rfa_types | TEXT | NULL | Comma-separated RFA type codes (e.g. SDW,DDW) |
|
||||
| is_active | TINYINT(1) | NOT NULL, DEFAULT 1 | Active status |
|
||||
| created_at | DATETIME(6) | NOT NULL, DEFAULT NOW | Record creation timestamp |
|
||||
| updated_at | DATETIME(6) | NOT NULL, ON UPDATE | Last update timestamp |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
- PRIMARY KEY (id)
|
||||
- UNIQUE KEY uq_review_teams_uuid (uuid)
|
||||
- KEY idx_review_teams_project (project_id, is_active)
|
||||
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
|
||||
|
||||
**Relationships**:
|
||||
|
||||
- Parent: projects
|
||||
- Children: review_team_members, review_tasks
|
||||
- Referenced by: distribution_recipients (recipient_type='TEAM')
|
||||
|
||||
---
|
||||
|
||||
### 20.2 review_team_members
|
||||
|
||||
**Purpose**: สมาชิกในทีมแยกตาม Discipline (M:N ระหว่าง review_teams และ users)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------- | ----------- | ------------------------------- | ------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal ID |
|
||||
| uuid | UUID | NOT NULL, UNIQUE, DEFAULT UUID()| UUID Public Identifier (ADR-019) |
|
||||
| team_id | INT | NOT NULL, FK | Reference to review_teams |
|
||||
| user_id | INT | NOT NULL, FK | Reference to users (user_id) |
|
||||
| discipline_id | INT | NOT NULL, FK | Reference to disciplines |
|
||||
| role | ENUM | NOT NULL, DEFAULT 'REVIEWER' | REVIEWER, LEAD, MANAGER |
|
||||
| priority_order | INT | NOT NULL, DEFAULT 0 | Assignment priority within discipline |
|
||||
| created_at | DATETIME(6) | NOT NULL, DEFAULT NOW | Record creation timestamp |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
- PRIMARY KEY (id)
|
||||
- UNIQUE KEY uq_review_team_members_uuid (uuid)
|
||||
- UNIQUE KEY uq_team_user_discipline (team_id, user_id, discipline_id)
|
||||
- FOREIGN KEY (team_id) REFERENCES review_teams(id) ON DELETE CASCADE
|
||||
- FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
|
||||
- FOREIGN KEY (discipline_id) REFERENCES disciplines(id)
|
||||
|
||||
---
|
||||
|
||||
### 20.3 response_codes
|
||||
|
||||
**Purpose**: รหัสตอบกลับมาตรฐาน (Approval Matrix) สำหรับ RFA Review
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| --------------- | --------- | ----------------------------------- | -------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal ID |
|
||||
| uuid | UUID | NOT NULL, UNIQUE, DEFAULT UUID() | UUID Public Identifier (ADR-019) |
|
||||
| code | VARCHAR(10)| NOT NULL | Response code (1A, 1B, 1C, 1D, 1E, 1F, 1G, 2, 3, 4) |
|
||||
| sub_status | VARCHAR(10)| NULL | Optional sub-status |
|
||||
| category | ENUM | NOT NULL | ENGINEERING, MATERIAL, CONTRACT, TESTING, ESG |
|
||||
| description_th | TEXT | NOT NULL | Thai description |
|
||||
| description_en | TEXT | NOT NULL | English description |
|
||||
| implications | JSON | NULL | {affectsSchedule, affectsCost, requiresContractReview} |
|
||||
| notify_roles | TEXT | NULL | Comma-separated roles to notify (e.g. CONTRACT_MANAGER,QS_MANAGER) |
|
||||
| is_active | TINYINT(1)| NOT NULL, DEFAULT 1 | Active status |
|
||||
| is_system | TINYINT(1)| NOT NULL, DEFAULT 0 | System default — cannot delete |
|
||||
| created_at | DATETIME(6)| NOT NULL, DEFAULT NOW | Record creation timestamp |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
- PRIMARY KEY (id)
|
||||
- UNIQUE KEY uq_response_codes_uuid (uuid)
|
||||
- UNIQUE KEY uq_response_code_category (code, category)
|
||||
- KEY idx_rc_category_active (category, is_active)
|
||||
|
||||
---
|
||||
|
||||
### 20.4 response_code_rules
|
||||
|
||||
**Purpose**: กฎการใช้ Response Code ต่อโครงการ/ประเภทเอกสาร (Project-level Override)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ---------------------- | ----------- | ---------------------------- | ---------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal ID |
|
||||
| uuid | UUID | NOT NULL, UNIQUE | UUID Public Identifier (ADR-019) |
|
||||
| project_id | INT | NULL, FK | NULL = global default |
|
||||
| document_type_id | INT | NOT NULL, FK | Reference to correspondence_types |
|
||||
| response_code_id | INT | NOT NULL, FK | Reference to response_codes |
|
||||
| is_enabled | TINYINT(1) | NOT NULL, DEFAULT 1 | Enable/disable this code for the context |
|
||||
| requires_comments | TINYINT(1) | NOT NULL, DEFAULT 0 | Force comment when selecting this code |
|
||||
| triggers_notification | TINYINT(1) | NOT NULL, DEFAULT 0 | Send notification when used |
|
||||
| parent_rule_id | INT | NULL, FK | For inheritance tracking |
|
||||
| created_at | DATETIME(6) | NOT NULL, DEFAULT NOW | Record creation timestamp |
|
||||
| updated_at | DATETIME(6) | NOT NULL, ON UPDATE | Last update timestamp |
|
||||
|
||||
**Business Rules**:
|
||||
|
||||
- `project_id = NULL` = Global default rule (applies to all projects)
|
||||
- Project-level rules override global defaults
|
||||
- UNIQUE constraint: (project_id, document_type_id, response_code_id)
|
||||
|
||||
---
|
||||
|
||||
### 20.5 review_tasks
|
||||
|
||||
**Purpose**: งานตรวจสอบสำหรับแต่ละ Discipline ใน Parallel Review Flow
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------------------ | ----------- | ----------------------------------- | --------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal ID |
|
||||
| uuid | UUID | NOT NULL, UNIQUE, DEFAULT UUID() | UUID Public Identifier (ADR-019) |
|
||||
| rfa_revision_id | INT | NOT NULL, FK | Reference to rfa_revisions |
|
||||
| team_id | INT | NOT NULL, FK | Reference to review_teams |
|
||||
| discipline_id | INT | NOT NULL, FK | Reference to disciplines |
|
||||
| assigned_to_user_id | INT | NULL, FK | Assigned reviewer (NULL = auto-assign) |
|
||||
| status | ENUM | NOT NULL, DEFAULT 'PENDING' | PENDING, IN_PROGRESS, COMPLETED, DELEGATED, EXPIRED, CANCELLED |
|
||||
| due_date | DATE | NULL | Review due date |
|
||||
| response_code_id | INT | NULL, FK | Selected response code |
|
||||
| comments | TEXT | NULL | Reviewer comments |
|
||||
| attachments | JSON | NULL | Array of attachment publicIds (ADR-021) |
|
||||
| delegated_from_user_id | INT | NULL | Original assignee when task was delegated |
|
||||
| completed_at | TIMESTAMP | NULL | Completion timestamp |
|
||||
| version | INT | NOT NULL, DEFAULT 1 | Optimistic locking (ADR-002) |
|
||||
| created_at | DATETIME(6) | NOT NULL, DEFAULT NOW | Record creation timestamp |
|
||||
| updated_at | DATETIME(6) | NOT NULL, ON UPDATE | Last update timestamp |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
- UNIQUE KEY uq_review_task_per_revision_discipline (rfa_revision_id, team_id, discipline_id)
|
||||
- KEY idx_review_tasks_assigned (assigned_to_user_id, status)
|
||||
- FOREIGN KEY (assigned_to_user_id) REFERENCES users(user_id) ON DELETE SET NULL
|
||||
|
||||
**Business Rules**:
|
||||
|
||||
- One task per revision + team + discipline combination (UNIQUE enforced)
|
||||
- `version` column used for optimistic locking (ADR-002)
|
||||
- `attachments` JSON stores publicIds — resolved via AttachmentsService (no FK)
|
||||
|
||||
---
|
||||
|
||||
### 20.6 delegations
|
||||
|
||||
**Purpose**: การมอบหมายงาน (Task Delegation) ระหว่างผู้ใช้
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------------ | ----------- | ------------------------------- | ----------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal ID |
|
||||
| uuid | UUID | NOT NULL, UNIQUE, DEFAULT UUID()| UUID Public Identifier (ADR-019) |
|
||||
| delegator_user_id | INT | NOT NULL, FK | ผู้มอบหมาย → users(user_id) |
|
||||
| delegate_user_id | INT | NOT NULL, FK | ผู้รับมอบหมาย → users(user_id) |
|
||||
| start_date | DATE | NOT NULL | วันที่เริ่มการมอบหมาย |
|
||||
| end_date | DATE | NULL | วันที่สิ้นสุด — BullMQ job flip is_active=0 เมื่อผ่าน (ADR-008) |
|
||||
| scope | ENUM | NOT NULL, DEFAULT 'ALL' | ALL, RFA_ONLY, CORRESPONDENCE_ONLY, SPECIFIC_TYPES |
|
||||
| document_types | TEXT | NULL | Comma-separated doc type codes when scope=SPECIFIC_TYPES |
|
||||
| is_active | TINYINT(1) | NOT NULL, DEFAULT 1 | Managed by BullMQ scheduler — ห้าม flip manual |
|
||||
| reason | TEXT | NULL | เหตุผลการมอบหมาย |
|
||||
| created_at | DATETIME(6) | NOT NULL, DEFAULT NOW | Record creation timestamp |
|
||||
| updated_at | DATETIME(6) | NOT NULL, ON UPDATE | Last update timestamp |
|
||||
|
||||
**Business Rules**:
|
||||
|
||||
- **Auto-expiry**: BullMQ Scheduled Job ตรวจ `end_date < NOW()` และ flip `is_active = 0` (ADR-008)
|
||||
- **Active check query**: `WHERE delegator_user_id = ? AND is_active = 1 AND start_date <= NOW() AND (end_date IS NULL OR end_date >= NOW())`
|
||||
- ห้ามเปลี่ยน `is_active` โดยตรงในระดับ Service — ใช้ BullMQ เท่านั้น
|
||||
|
||||
---
|
||||
|
||||
### 20.7 reminder_rules
|
||||
|
||||
**Purpose**: กฎการแจ้งเตือน (Reminder/Escalation) สำหรับ Review Tasks
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------------- | ----------- | ------------------------ | -------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal ID |
|
||||
| uuid | UUID | NOT NULL, UNIQUE | UUID Public Identifier (ADR-019) |
|
||||
| name | VARCHAR(100)| NOT NULL | Rule name |
|
||||
| project_id | INT | NULL, FK | NULL = global rule |
|
||||
| document_type_id | INT | NULL, FK | NULL = applies to all types |
|
||||
| trigger_days_before_due | INT | NOT NULL, DEFAULT 2 | วันก่อน due date ที่จะแจ้งเตือน |
|
||||
| escalation_days_after_due | INT | NOT NULL, DEFAULT 1 | วันหลัง due date ที่จะ escalate |
|
||||
| reminder_type | ENUM | NOT NULL | DUE_SOON, ON_DUE, OVERDUE, ESCALATION_L1, ESCALATION_L2 |
|
||||
| recipients | TEXT | NOT NULL | Comma-separated: ASSIGNEE, MANAGER, PROJECT_MANAGER |
|
||||
| message_template_th | TEXT | NOT NULL | Thai message template |
|
||||
| message_template_en | TEXT | NOT NULL | English message template |
|
||||
| is_active | TINYINT(1) | NOT NULL, DEFAULT 1 | Active status |
|
||||
| created_at | DATETIME(6) | NOT NULL, DEFAULT NOW | Record creation timestamp |
|
||||
| updated_at | DATETIME(6) | NOT NULL, ON UPDATE | Last update timestamp |
|
||||
|
||||
---
|
||||
|
||||
### 20.8 distribution_matrices
|
||||
|
||||
**Purpose**: ตารางกำหนดกฎการกระจายเอกสาร (Distribution Matrix) ตาม Response Code
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ---------------- | ----------- | ------------------------ | ---------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal ID |
|
||||
| uuid | UUID | NOT NULL, UNIQUE | UUID Public Identifier (ADR-019) |
|
||||
| name | VARCHAR(100)| NOT NULL | Matrix name |
|
||||
| project_id | INT | NULL, FK | NULL = global matrix |
|
||||
| document_type_id | INT | NOT NULL, FK | Reference to correspondence_types |
|
||||
| response_code_id | INT | NULL, FK | NULL = applies to all codes |
|
||||
| conditions | JSON | NULL | {codes:["1A","1B"], excludeCodes:["3","4"]} |
|
||||
| is_active | TINYINT(1) | NOT NULL, DEFAULT 1 | Active status |
|
||||
| created_at | DATETIME(6) | NOT NULL, DEFAULT NOW | Record creation timestamp |
|
||||
|
||||
---
|
||||
|
||||
### 20.9 distribution_recipients
|
||||
|
||||
**Purpose**: ผู้รับเอกสารใน Distribution Matrix (Polymorphic Reference)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------- | ----------- | ------------------------ | ----------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal ID |
|
||||
| uuid | UUID | NOT NULL, UNIQUE | UUID Public Identifier (ADR-019) |
|
||||
| matrix_id | INT | NOT NULL, FK | Reference to distribution_matrices |
|
||||
| recipient_type | ENUM | NOT NULL | USER, ORGANIZATION, TEAM, ROLE |
|
||||
| recipient_public_id | UUID | NOT NULL | publicId ของ target entity (ดูตาราง Polymorphic Resolution ด้านล่าง) |
|
||||
| delivery_method | ENUM | NOT NULL, DEFAULT 'BOTH' | EMAIL, IN_APP, BOTH |
|
||||
| sequence | INT | NULL | For ordered delivery |
|
||||
| created_at | DATETIME(6) | NOT NULL, DEFAULT NOW | Record creation timestamp |
|
||||
|
||||
**Polymorphic Resolution Table**:
|
||||
|
||||
| recipient_type | recipient_public_id อ้างอิง | FK | หมายเหตุ |
|
||||
|---|---|---|---|
|
||||
| USER | users.uuid | Soft (no FK) | Resolved via UserService |
|
||||
| ORGANIZATION | organizations.uuid | Soft (no FK) | Resolved via OrgService |
|
||||
| TEAM | review_teams.uuid | Soft (no FK) | Q4A — ทีมตรวจสอบ RFA |
|
||||
| ROLE | roles.uuid | Soft (no FK) | Q4B — ต้องใช้หลัง Apply delta-11 |
|
||||
|
||||
**Business Rules**:
|
||||
|
||||
- **ไม่มี FK constraint** บน recipient_public_id โดยออกแบบ (Polymorphic Pattern)
|
||||
- Service Layer ต้องตรวจสอบ existence ก่อน save
|
||||
- ใช้ index `idx_dr_type_recipient (recipient_type, recipient_public_id)` สำหรับ lookup performance
|
||||
|
||||
---
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Database Indexing & Performance Strategy
|
||||
|
||||
**Version:** 1.0.0
|
||||
**Version:** 1.1.0 (v1.9.0 Core Schema)
|
||||
**Context:** Production-scale (100k+ documents, High Concurrency)
|
||||
**Database:** MySQL 8.x (On-Premise via Docker)
|
||||
**Database:** MariaDB 11.x (Native UUID Support)
|
||||
|
||||
## 1. Core Principles (หลักการสำคัญ)
|
||||
|
||||
@@ -64,13 +64,45 @@ ADD INDEX `idx_doc_status_is_current` (`is_current`, `status`, `project_id`);
|
||||
ALTER TABLE `documents`
|
||||
ADD INDEX `idx_project_updated` (`project_id`, `updated_at` DESC);
|
||||
|
||||
-- สำหรับ Inbox / Pending Tasks ของ User
|
||||
-- สำหรับ Inbox / Pending Tasks ของ User (General Workflow)
|
||||
ALTER TABLE `workflow_instances`
|
||||
ADD INDEX `idx_assignee_status` (`assignee_id`, `status`, `created_at` DESC);
|
||||
|
||||
-- สำหรับ Optimistic Locking (ADR-001 v1.1)
|
||||
ALTER TABLE `workflow_instances`
|
||||
ADD INDEX `idx_wf_inst_version` (`id`, `version_no`);
|
||||
|
||||
```
|
||||
|
||||
### 3.2 Full-Text Search (ทางเลือกเบื้องต้นก่อนใช้ Elasticsearch)
|
||||
### 3.2 RFA Parallel Review & Delegation (v1.9.0)
|
||||
|
||||
ในระบบ RFA ใหม่ มีการใช้ Parallel Review และการมอบหมายงาน (Delegation) ซึ่งต้องการ Index เฉพาะทาง:
|
||||
|
||||
```sql
|
||||
-- สำหรับดึงงานที่รอตรวจแยกตาม Discipline และสถานะ
|
||||
ALTER TABLE `review_tasks`
|
||||
ADD INDEX `idx_review_tasks_lookup` (`assigned_to_user_id`, `status`, `discipline_id`);
|
||||
|
||||
-- สำหรับการตรวจสอบสิทธิ์การตรวจรายคน (Priority Order)
|
||||
ALTER TABLE `review_team_members`
|
||||
ADD INDEX `idx_rtm_lookup` (`team_id`, `user_id`, `is_active`);
|
||||
|
||||
-- สำหรับเช็คการมอบหมายงานที่ยังมีผลอยู่ (Managed by BullMQ)
|
||||
ALTER TABLE `delegations`
|
||||
ADD INDEX `idx_delegations_active_lookup` (`delegator_user_id`, `is_active`, `start_date`, `end_date`);
|
||||
```
|
||||
|
||||
### 3.3 Polymorphic Distribution Matrix
|
||||
|
||||
เนื่องจาก `distribution_recipients` เก็บ `recipient_public_id` แบบ UUID (ADR-019) และไม่มี Hard FK:
|
||||
|
||||
```sql
|
||||
-- สำหรับ Lookup ผู้รับเอกสารตามประเภท
|
||||
ALTER TABLE `distribution_recipients`
|
||||
ADD INDEX `idx_dr_type_recipient` (`recipient_type`, `recipient_public_id`);
|
||||
```
|
||||
|
||||
### 3.4 Full-Text Search (ทางเลือกเบื้องต้นก่อนใช้ Elasticsearch)
|
||||
|
||||
หากผู้ใช้ต้องการค้นหาจากชื่อเอกสาร (`title`) หรือเนื้อหาบางส่วน
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
---
|
||||
|
||||
title: 'Data & Storage: File Storage and Handling (Two-Phase)'
|
||||
version: 1.8.0
|
||||
version: 1.9.0
|
||||
status: drafted
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2026-02-22
|
||||
@@ -80,23 +80,30 @@ LCBP3-DMS ต้องจัดการ File Uploads สำหรับ Attachm
|
||||
```sql
|
||||
CREATE TABLE attachments (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
uuid UUID NOT NULL DEFAULT UUID() COMMENT 'UUID Public Identifier (ADR-019)',
|
||||
original_filename VARCHAR(255) NOT NULL,
|
||||
stored_filename VARCHAR(255) NOT NULL, -- UUID-based
|
||||
file_path VARCHAR(500) NOT NULL, -- QNAP Mount path
|
||||
mime_type VARCHAR(100) NOT NULL,
|
||||
file_size INT NOT NULL,
|
||||
checksum VARCHAR(64) NULL, -- SHA-256
|
||||
reference_date DATE NULL COMMENT 'ADR-019/ADR-003: folder partition date',
|
||||
|
||||
-- Two-Phase Fields
|
||||
is_temporary BOOLEAN DEFAULT TRUE,
|
||||
temp_id VARCHAR(100) NULL, -- UUID for temp reference
|
||||
expires_at DATETIME NULL, -- Temp file expiration
|
||||
|
||||
-- ADR-021: Integrated Workflow Context
|
||||
workflow_history_id CHAR(36) NULL COMMENT 'FK to workflow_histories.id for step-specific attachments',
|
||||
|
||||
uploaded_by_user_id INT NOT NULL,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
|
||||
FOREIGN KEY (uploaded_by_user_id) REFERENCES users(user_id),
|
||||
INDEX idx_temp_files (is_temporary, expires_at)
|
||||
FOREIGN KEY (workflow_history_id) REFERENCES workflow_histories(id) ON DELETE SET NULL,
|
||||
INDEX idx_temp_files (is_temporary, expires_at),
|
||||
INDEX idx_attachments_reference_date (reference_date)
|
||||
);
|
||||
```
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
| description | version |
|
||||
| ------------------------------------------------------------------ | ------- |
|
||||
| legacy PDF document migration to system v1.8.0 uses n8n and Ollama | 1.8.0 |
|
||||
| legacy PDF document migration to system v1.9.0 uses n8n and Ollama | 1.9.0 |
|
||||
|
||||
> **Note:** Category Enum system-driven, Idempotency Contract, Duplicate Handling Clarification, Storage Enforcement, Audit Log Enhancement, Review Queue Integration, Revision Drift Protection, Execution Time, Encoding Normalization, Security Hardening, Orchestrator on QNAP, AI Physical Isolation (Desktop Desk-5439), Folder Standard (/share/np-dms/n8n), **AI Tag Extraction & Auto-Tagging**
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
-- =============================================================================
|
||||
-- Delta 11: เพิ่ม uuid column ให้ roles table
|
||||
-- =============================================================================
|
||||
-- เหตุผล: roles ไม่มี uuid column ทำให้ distribution_recipients ไม่สามารถ
|
||||
-- อ้างอิง ROLE type ด้วย publicId ได้ตาม ADR-019
|
||||
-- ใช้ใน: distribution_recipients.recipient_public_id (recipient_type = 'ROLE')
|
||||
-- ADR: ADR-019 (Hybrid Identifier Strategy)
|
||||
-- Feature: v1.9.0 RFA Approval Refactor (1-rfa-approval-refactor)
|
||||
-- Created: 2026-05-13
|
||||
-- =============================================================================
|
||||
|
||||
ALTER TABLE `roles`
|
||||
ADD COLUMN `uuid` UUID NOT NULL DEFAULT (UUID())
|
||||
COMMENT 'UUID Public Identifier (ADR-019) — ใช้ใน API Response แทน role_id'
|
||||
AFTER `role_id`;
|
||||
|
||||
-- สร้าง Unique Index สำหรับ uuid
|
||||
CREATE UNIQUE INDEX `idx_roles_uuid` ON `roles` (`uuid`);
|
||||
|
||||
-- =============================================================================
|
||||
-- หมายเหตุ: หลัง Apply delta นี้แล้ว
|
||||
-- - roles ที่มีอยู่แล้วจะได้ uuid อัตโนมัติจาก DEFAULT (UUID())
|
||||
-- - distribution_recipients.recipient_public_id (type=ROLE) ให้ใช้ roles.uuid
|
||||
-- - TypeORM Entity: เพิ่ม @Column({ unique: true }) uuid: string; ใน RoleEntity
|
||||
-- =============================================================================
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
-- ==========================================================
|
||||
-- DMS v1.8.0 Migration Support Tables
|
||||
-- ไฟล์นี้แยกจาก schema หลัก (lcbp3-v1.8.0-schema-01/02/03)
|
||||
-- DMS v1.9.0 Migration Support Tables
|
||||
-- ไฟล์นี้แยกจาก schema หลัก (lcbp3-v1.9.0-schema-01/02/03)
|
||||
-- ใช้สำหรับ n8n Migration Workflow เท่านั้น
|
||||
-- ลบได้ทั้งหมดหลัง Migration เสร็จสิ้น
|
||||
-- ==========================================================
|
||||
@@ -1,8 +1,8 @@
|
||||
-- =============================================================================
|
||||
-- LCBP3-DMS v1.9.0 — RFA Approval System Refactor Schema
|
||||
-- Feature Branch: 1-rfa-approval-refactor
|
||||
-- Feature Branch: 204-rfa-approval-refactor
|
||||
-- ADR-009: No TypeORM migrations — edit SQL schema directly
|
||||
-- Created: 2026-05-12
|
||||
-- Created: 2026-05-13
|
||||
-- =============================================================================
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
@@ -42,7 +42,7 @@ CREATE TABLE IF NOT EXISTS `review_team_members` (
|
||||
KEY `idx_rtm_team` (`team_id`),
|
||||
KEY `idx_rtm_user` (`user_id`),
|
||||
CONSTRAINT `fk_rtm_team` FOREIGN KEY (`team_id`) REFERENCES `review_teams` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_rtm_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_rtm_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_rtm_discipline` FOREIGN KEY (`discipline_id`) REFERENCES `disciplines` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
@@ -120,7 +120,7 @@ CREATE TABLE IF NOT EXISTS `review_tasks` (
|
||||
CONSTRAINT `fk_rt_rfa_revision` FOREIGN KEY (`rfa_revision_id`) REFERENCES `rfa_revisions` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_rt_team` FOREIGN KEY (`team_id`) REFERENCES `review_teams` (`id`),
|
||||
CONSTRAINT `fk_rt_discipline` FOREIGN KEY (`discipline_id`) REFERENCES `disciplines` (`id`),
|
||||
CONSTRAINT `fk_rt_user` FOREIGN KEY (`assigned_to_user_id`) REFERENCES `users` (`id`) ON DELETE SET NULL,
|
||||
CONSTRAINT `fk_rt_user` FOREIGN KEY (`assigned_to_user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL,
|
||||
CONSTRAINT `fk_rt_response_code` FOREIGN KEY (`response_code_id`) REFERENCES `response_codes` (`id`) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
@@ -128,44 +128,44 @@ CREATE TABLE IF NOT EXISTS `review_tasks` (
|
||||
-- 6. delegations — การมอบหมายงาน
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `delegations` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`delegator_id` INT NOT NULL COMMENT 'ผู้มอบหมาย',
|
||||
`delegatee_id` INT NOT NULL COMMENT 'ผู้รับมอบหมาย',
|
||||
`start_date` DATE NOT NULL,
|
||||
`end_date` DATE NULL,
|
||||
`scope` ENUM('ALL','RFA_ONLY','CORRESPONDENCE_ONLY','SPECIFIC_TYPES') NOT NULL DEFAULT 'ALL',
|
||||
`document_types` TEXT NULL COMMENT 'Comma-separated doc type codes when scope=SPECIFIC_TYPES',
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`reason` TEXT NULL,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`delegator_user_id` INT NOT NULL COMMENT 'ผู้มอบหมาย (FK → users.user_id)',
|
||||
`delegate_user_id` INT NOT NULL COMMENT 'ผู้รับมอบหมาย (FK → users.user_id)',
|
||||
`start_date` DATE NOT NULL,
|
||||
`end_date` DATE NULL COMMENT 'BullMQ job flips is_active=0 when end_date < NOW() (ADR-008)',
|
||||
`scope` ENUM('ALL','RFA_ONLY','CORRESPONDENCE_ONLY','SPECIFIC_TYPES') NOT NULL DEFAULT 'ALL',
|
||||
`document_types` TEXT NULL COMMENT 'Comma-separated doc type codes when scope=SPECIFIC_TYPES',
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'Managed by BullMQ scheduler — do not flip manually',
|
||||
`reason` TEXT NULL,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_delegations_uuid` (`uuid`),
|
||||
KEY `idx_delegations_active` (`delegator_id`, `is_active`, `start_date`, `end_date`),
|
||||
KEY `idx_delegations_delegatee` (`delegatee_id`, `is_active`),
|
||||
CONSTRAINT `fk_del_delegator` FOREIGN KEY (`delegator_id`) REFERENCES `users` (`id`),
|
||||
CONSTRAINT `fk_del_delegatee` FOREIGN KEY (`delegatee_id`) REFERENCES `users` (`id`)
|
||||
KEY `idx_delegations_active` (`delegator_user_id`, `is_active`, `start_date`, `end_date`),
|
||||
KEY `idx_delegations_delegate` (`delegate_user_id`, `is_active`),
|
||||
CONSTRAINT `fk_del_delegator` FOREIGN KEY (`delegator_user_id`) REFERENCES `users` (`user_id`),
|
||||
CONSTRAINT `fk_del_delegate` FOREIGN KEY (`delegate_user_id`) REFERENCES `users` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 7. reminder_rules — กฎการแจ้งเตือน
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `reminder_rules` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`name` VARCHAR(100) NOT NULL,
|
||||
`project_id` INT NULL COMMENT 'NULL = global',
|
||||
`document_type_id` INT NULL COMMENT 'NULL = all types',
|
||||
`trigger_days_before_due` INT NOT NULL DEFAULT 2,
|
||||
`escalation_days_after_due` INT NOT NULL DEFAULT 1,
|
||||
`project_id` INT NULL COMMENT 'NULL = global',
|
||||
`document_type_id` INT NULL COMMENT 'NULL = all types',
|
||||
`trigger_days_before_due` INT NOT NULL DEFAULT 2,
|
||||
`escalation_days_after_due` INT NOT NULL DEFAULT 1,
|
||||
`reminder_type` ENUM('DUE_SOON','ON_DUE','OVERDUE','ESCALATION_L1','ESCALATION_L2') NOT NULL,
|
||||
`recipients` TEXT NOT NULL COMMENT 'Comma-separated: ASSIGNEE,MANAGER,PROJECT_MANAGER',
|
||||
`message_template_th` TEXT NOT NULL,
|
||||
`message_template_en` TEXT NOT NULL,
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
`recipients` TEXT NOT NULL COMMENT 'Comma-separated: ASSIGNEE,MANAGER,PROJECT_MANAGER',
|
||||
`message_template_th` TEXT NOT NULL,
|
||||
`message_template_en` TEXT NOT NULL,
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_reminder_rules_uuid` (`uuid`),
|
||||
KEY `idx_reminder_rules_active` (`is_active`, `project_id`)
|
||||
@@ -175,15 +175,15 @@ CREATE TABLE IF NOT EXISTS `reminder_rules` (
|
||||
-- 8. distribution_matrices — ตารางกระจายเอกสาร
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `distribution_matrices` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`name` VARCHAR(100) NOT NULL,
|
||||
`project_id` INT NULL COMMENT 'NULL = global',
|
||||
`document_type_id` INT NOT NULL,
|
||||
`response_code_id` INT NULL COMMENT 'NULL = applies to all codes',
|
||||
`conditions` JSON NULL COMMENT '{"codes":["1A","1B"],"excludeCodes":["3","4"]}',
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`project_id` INT NULL COMMENT 'NULL = global',
|
||||
`document_type_id` INT NOT NULL,
|
||||
`response_code_id` INT NULL COMMENT 'NULL = applies to all codes',
|
||||
`conditions` JSON NULL COMMENT '{"codes":["1A","1B"],"excludeCodes":["3","4"]}',
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_distribution_matrices_uuid` (`uuid`),
|
||||
KEY `idx_distribution_lookup` (`document_type_id`, `response_code_id`, `is_active`),
|
||||
@@ -195,22 +195,17 @@ CREATE TABLE IF NOT EXISTS `distribution_matrices` (
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `distribution_recipients` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()) COMMENT 'UUID Public Identifier (ADR-019)',
|
||||
`matrix_id` INT NOT NULL,
|
||||
`recipient_type` ENUM('USER','ORGANIZATION','TEAM','ROLE') NOT NULL,
|
||||
`recipient_public_id` UUID NOT NULL COMMENT 'publicId of user/org/team',
|
||||
`recipient_public_id` UUID NOT NULL COMMENT 'publicId of target: USER=users.uuid | ORGANIZATION=organizations.uuid | TEAM=review_teams.uuid | ROLE=roles.uuid',
|
||||
`delivery_method` ENUM('EMAIL','IN_APP','BOTH') NOT NULL DEFAULT 'BOTH',
|
||||
`sequence` INT NULL COMMENT 'For ordered delivery',
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_distribution_recipients_uuid` (`uuid`),
|
||||
KEY `idx_dr_matrix` (`matrix_id`),
|
||||
KEY `idx_dr_type_recipient` (`recipient_type`, `recipient_public_id`),
|
||||
CONSTRAINT `fk_dr_matrix` FOREIGN KEY (`matrix_id`) REFERENCES `distribution_matrices` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- =============================================================================
|
||||
-- Additional Indexes (Performance)
|
||||
-- =============================================================================
|
||||
-- (all created inline above with KEY statements)
|
||||
|
||||
-- =============================================================================
|
||||
-- END OF SCHEMA v1.9.0
|
||||
-- =============================================================================
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
COMMENT='Polymorphic recipients — no FK on recipient_public_id by design.';
|
||||
|
||||
+3
-3
@@ -1,9 +1,9 @@
|
||||
-- ==========================================================
|
||||
-- DMS v1.8.0 Schema Part 1/3: DROP Statements
|
||||
-- DMS v1.9.0 Schema Part 1/3: DROP Statements
|
||||
-- รันไฟล์นี้ก่อน เพื่อล้างตารางเดิมทั้งหมด
|
||||
-- ==========================================================
|
||||
-- ==========================================================
|
||||
-- DMS v1.8.0 Document Management System Database
|
||||
-- DMS v1.9.0 Document Management System Database
|
||||
-- Deploy Script Schema
|
||||
-- Server: Container Station on QNAP TS-473A
|
||||
-- Database service: MariaDB 11.8
|
||||
@@ -14,7 +14,7 @@
|
||||
-- reverse proxy: jc21/nginx-proxy-manager:latest
|
||||
-- cron service: n8n
|
||||
-- ==========================================================
|
||||
-- [v1.8.0 UPDATE] Prepare migration
|
||||
-- [v1.9.0 UPDATE] Prepare migration
|
||||
-- Update: Upgraded from v1.7.0
|
||||
-- Last Updated: 2026-02-27
|
||||
-- Major Changes:
|
||||
+215
-1
@@ -1,5 +1,5 @@
|
||||
-- ==========================================================
|
||||
-- DMS v1.8.0 Schema Part 2/3: CREATE TABLE Statements
|
||||
-- DMS v1.9.0 Schema Part 2/3: CREATE TABLE Statements
|
||||
-- รัน: mysql < 01-schema-drop.sql แล้วจึงรัน 02-schema-tables.sql
|
||||
-- ==========================================================
|
||||
SET NAMES utf8mb4;
|
||||
@@ -113,6 +113,7 @@ CREATE TABLE refresh_tokens (
|
||||
-- ตาราง Master เก็บ "บทบาท" ของผู้ใช้ในระบบ
|
||||
CREATE TABLE roles (
|
||||
role_id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของตาราง',
|
||||
uuid UUID NOT NULL DEFAULT UUID() COMMENT 'UUID Public Identifier (ADR-019)',
|
||||
-- role_code VARCHAR(50) NOT NULL UNIQUE COMMENT 'รหัสบทบาท (เช่น SUPER_ADMIN, ADMIN, EDITOR, VIEWER)',
|
||||
role_name VARCHAR(100) NOT NULL COMMENT 'ชื่อบทบาท',
|
||||
scope ENUM(
|
||||
@@ -1464,3 +1465,216 @@ CREATE TABLE ai_audit_logs (
|
||||
INDEX idx_ai_audit_model (ai_model),
|
||||
INDEX idx_ai_audit_status (STATUS)
|
||||
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ตาราง Audit Log การทำงาน AI ทุกครั้ง (ADR-018 Rule 5 Audit Logging)';
|
||||
|
||||
-- =============================================================================
|
||||
-- 20. RFA Approval System (v1.9.0)
|
||||
-- =============================================================================
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 20.1 review_teams — ทีมตรวจสอบแยกตาม Discipline
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `review_teams` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`project_id` INT NOT NULL,
|
||||
`name` VARCHAR(100) NOT NULL,
|
||||
`description` VARCHAR(255) NULL,
|
||||
`default_for_rfa_types` TEXT NULL COMMENT 'Comma-separated RFA type codes e.g. SDW,DDW',
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_review_teams_uuid` (`uuid`),
|
||||
KEY `idx_review_teams_project` (`project_id`, `is_active`),
|
||||
CONSTRAINT `fk_review_teams_project` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 20.2 review_team_members — สมาชิกในทีมแยกตาม Discipline
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `review_team_members` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`team_id` INT NOT NULL,
|
||||
`user_id` INT NOT NULL,
|
||||
`discipline_id` INT NOT NULL,
|
||||
`role` ENUM('REVIEWER','LEAD','MANAGER') NOT NULL DEFAULT 'REVIEWER',
|
||||
`priority_order` INT NOT NULL DEFAULT 0,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_review_team_members_uuid` (`uuid`),
|
||||
UNIQUE KEY `uq_team_user_discipline` (`team_id`, `user_id`, `discipline_id`),
|
||||
KEY `idx_rtm_team` (`team_id`),
|
||||
KEY `idx_rtm_user` (`user_id`),
|
||||
CONSTRAINT `fk_rtm_team` FOREIGN KEY (`team_id`) REFERENCES `review_teams` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_rtm_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_rtm_discipline` FOREIGN KEY (`discipline_id`) REFERENCES `disciplines` (`id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 20.3 response_codes — รหัสตอบกลับมาตรฐาน (Master Approval Matrix)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `response_codes` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`code` VARCHAR(10) NOT NULL COMMENT '1A, 1B, 1C, 1D, 1E, 1F, 1G, 2, 3, 4',
|
||||
`sub_status` VARCHAR(10) NULL,
|
||||
`category` ENUM('ENGINEERING','MATERIAL','CONTRACT','TESTING','ESG') NOT NULL,
|
||||
`description_th` TEXT NOT NULL,
|
||||
`description_en` TEXT NOT NULL,
|
||||
`implications` JSON NULL COMMENT '{"affectsSchedule":bool,"affectsCost":bool,"requiresContractReview":bool}',
|
||||
`notify_roles` TEXT NULL COMMENT 'Comma-separated roles e.g. CONTRACT_MANAGER,QS_MANAGER',
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`is_system` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'System default — cannot delete',
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_response_codes_uuid` (`uuid`),
|
||||
UNIQUE KEY `uq_response_code_category` (`code`, `category`),
|
||||
KEY `idx_rc_category_active` (`category`, `is_active`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 20.4 response_code_rules — กฎการใช้รหัสต่อโครงการ/ประเภทเอกสาร
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `response_code_rules` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`project_id` INT NULL COMMENT 'NULL = global default',
|
||||
`document_type_id` INT NOT NULL,
|
||||
`response_code_id` INT NOT NULL,
|
||||
`is_enabled` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`requires_comments` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`triggers_notification` TINYINT(1) NOT NULL DEFAULT 0,
|
||||
`parent_rule_id` INT NULL COMMENT 'For inheritance tracking',
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_response_code_rules_uuid` (`uuid`),
|
||||
UNIQUE KEY `uq_rule_per_project_doctype_code` (`project_id`, `document_type_id`, `response_code_id`),
|
||||
KEY `idx_response_rules_lookup` (`project_id`, `document_type_id`, `is_enabled`),
|
||||
CONSTRAINT `fk_rcr_response_code` FOREIGN KEY (`response_code_id`) REFERENCES `response_codes` (`id`),
|
||||
CONSTRAINT `fk_rcr_parent` FOREIGN KEY (`parent_rule_id`) REFERENCES `response_code_rules` (`id`) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 20.5 review_tasks — งานตรวจสอบสำหรับแต่ละ Discipline (Parallel Review)
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `review_tasks` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`rfa_revision_id` INT NOT NULL,
|
||||
`team_id` INT NOT NULL,
|
||||
`discipline_id` INT NOT NULL,
|
||||
`assigned_to_user_id` INT NULL COMMENT 'NULL = auto-assign by discipline',
|
||||
`status` ENUM('PENDING','IN_PROGRESS','COMPLETED','DELEGATED','EXPIRED','CANCELLED') NOT NULL DEFAULT 'PENDING',
|
||||
`due_date` DATE NULL,
|
||||
`response_code_id` INT NULL,
|
||||
`comments` TEXT NULL,
|
||||
`attachments` JSON NULL COMMENT 'Array of attachment publicIds',
|
||||
`delegated_from_user_id` INT NULL COMMENT 'Original assignee when delegated',
|
||||
`completed_at` TIMESTAMP NULL,
|
||||
`version` INT NOT NULL DEFAULT 1 COMMENT 'Optimistic locking (ADR-002)',
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_review_tasks_uuid` (`uuid`),
|
||||
UNIQUE KEY `uq_review_task_per_revision_discipline` (`rfa_revision_id`, `team_id`, `discipline_id`),
|
||||
KEY `idx_review_tasks_rfa_revision` (`rfa_revision_id`),
|
||||
KEY `idx_review_tasks_status` (`status`),
|
||||
KEY `idx_review_tasks_assigned` (`assigned_to_user_id`, `status`),
|
||||
CONSTRAINT `fk_rt_rfa_revision` FOREIGN KEY (`rfa_revision_id`) REFERENCES `rfa_revisions` (`id`) ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_rt_team` FOREIGN KEY (`team_id`) REFERENCES `review_teams` (`id`),
|
||||
CONSTRAINT `fk_rt_discipline` FOREIGN KEY (`discipline_id`) REFERENCES `disciplines` (`id`),
|
||||
CONSTRAINT `fk_rt_user` FOREIGN KEY (`assigned_to_user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL,
|
||||
CONSTRAINT `fk_rt_response_code` FOREIGN KEY (`response_code_id`) REFERENCES `response_codes` (`id`) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 20.6 delegations — การมอบหมายงาน
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `delegations` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`delegator_user_id` INT NOT NULL COMMENT 'ผู้มอบหมาย (FK → users.user_id)',
|
||||
`delegate_user_id` INT NOT NULL COMMENT 'ผู้รับมอบหมาย (FK → users.user_id)',
|
||||
`start_date` DATE NOT NULL,
|
||||
`end_date` DATE NULL COMMENT 'BullMQ job flips is_active=0 when end_date < NOW() (ADR-008)',
|
||||
`scope` ENUM('ALL','RFA_ONLY','CORRESPONDENCE_ONLY','SPECIFIC_TYPES') NOT NULL DEFAULT 'ALL',
|
||||
`document_types` TEXT NULL COMMENT 'Comma-separated doc type codes when scope=SPECIFIC_TYPES',
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'Managed by BullMQ scheduler — do not flip manually',
|
||||
`reason` TEXT NULL,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_delegations_uuid` (`uuid`),
|
||||
KEY `idx_delegations_active` (`delegator_user_id`, `is_active`, `start_date`, `end_date`),
|
||||
KEY `idx_delegations_delegate` (`delegate_user_id`, `is_active`),
|
||||
CONSTRAINT `fk_del_delegator` FOREIGN KEY (`delegator_user_id`) REFERENCES `users` (`user_id`),
|
||||
CONSTRAINT `fk_del_delegate` FOREIGN KEY (`delegate_user_id`) REFERENCES `users` (`user_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 20.7 reminder_rules — กฎการแจ้งเตือน
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `reminder_rules` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`name` VARCHAR(100) NOT NULL,
|
||||
`project_id` INT NULL COMMENT 'NULL = global',
|
||||
`document_type_id` INT NULL COMMENT 'NULL = all types',
|
||||
`trigger_days_before_due` INT NOT NULL DEFAULT 2,
|
||||
`escalation_days_after_due` INT NOT NULL DEFAULT 1,
|
||||
`reminder_type` ENUM('DUE_SOON','ON_DUE','OVERDUE','ESCALATION_L1','ESCALATION_L2') NOT NULL,
|
||||
`recipients` TEXT NOT NULL COMMENT 'Comma-separated: ASSIGNEE,MANAGER,PROJECT_MANAGER',
|
||||
`message_template_th` TEXT NOT NULL,
|
||||
`message_template_en` TEXT NOT NULL,
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
`updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_reminder_rules_uuid` (`uuid`),
|
||||
KEY `idx_reminder_rules_active` (`is_active`, `project_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 20.8 distribution_matrices — ตารางกระจายเอกสาร
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `distribution_matrices` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()),
|
||||
`name` VARCHAR(100) NOT NULL,
|
||||
`project_id` INT NULL COMMENT 'NULL = global',
|
||||
`document_type_id` INT NOT NULL,
|
||||
`response_code_id` INT NULL COMMENT 'NULL = applies to all codes',
|
||||
`conditions` JSON NULL COMMENT '{"codes":["1A","1B"],"excludeCodes":["3","4"]}',
|
||||
`is_active` TINYINT(1) NOT NULL DEFAULT 1,
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_distribution_matrices_uuid` (`uuid`),
|
||||
KEY `idx_distribution_lookup` (`document_type_id`, `response_code_id`, `is_active`),
|
||||
CONSTRAINT `fk_dm_response_code` FOREIGN KEY (`response_code_id`) REFERENCES `response_codes` (`id`) ON DELETE SET NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
-- -----------------------------------------------------------------------------
|
||||
-- 20.9 distribution_recipients — ผู้รับเอกสารใน Distribution Matrix
|
||||
-- -----------------------------------------------------------------------------
|
||||
CREATE TABLE IF NOT EXISTS `distribution_recipients` (
|
||||
`id` INT NOT NULL AUTO_INCREMENT,
|
||||
`uuid` UUID NOT NULL DEFAULT (UUID()) COMMENT 'UUID Public Identifier (ADR-019)',
|
||||
`matrix_id` INT NOT NULL,
|
||||
`recipient_type` ENUM('USER','ORGANIZATION','TEAM','ROLE') NOT NULL,
|
||||
`recipient_public_id` UUID NOT NULL COMMENT 'publicId of target: USER=users.uuid | ORGANIZATION=organizations.uuid | TEAM=review_teams.uuid | ROLE=roles.uuid',
|
||||
`delivery_method` ENUM('EMAIL','IN_APP','BOTH') NOT NULL DEFAULT 'BOTH',
|
||||
`sequence` INT NULL COMMENT 'For ordered delivery',
|
||||
`created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6),
|
||||
PRIMARY KEY (`id`),
|
||||
UNIQUE KEY `uq_distribution_recipients_uuid` (`uuid`),
|
||||
KEY `idx_dr_matrix` (`matrix_id`),
|
||||
KEY `idx_dr_type_recipient` (`recipient_type`, `recipient_public_id`),
|
||||
CONSTRAINT `fk_dr_matrix` FOREIGN KEY (`matrix_id`) REFERENCES `distribution_matrices` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
|
||||
COMMENT='Polymorphic recipients — no FK on recipient_public_id (by design). ROLE type uses roles.uuid (ADR-019)';
|
||||
|
||||
-- =============================================================================
|
||||
-- END OF SCHEMA v1.9.0
|
||||
-- =============================================================================
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
-- ==========================================================
|
||||
-- DMS v1.8.0 Schema Part 3/3: Views, Indexes, Partitioning
|
||||
-- DMS v1.9.0 Schema Part 3/3: Views, Indexes, Partitioning
|
||||
-- รัน: หลังจาก 02-schema-tables.sql เสร็จ
|
||||
-- ==========================================================
|
||||
SET NAMES utf8mb4;
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
-- ==========================================================
|
||||
-- DMS v1.8.0 Document Management System Database
|
||||
-- DMS v1.9.0 Document Management System Database
|
||||
-- Deploy Script Schema
|
||||
-- Server: Container Station on QNAP TS-473A
|
||||
-- Database service: MariaDB 11.8
|
||||
@@ -10,7 +10,7 @@
|
||||
-- reverse proxy: jc21/nginx-proxy-manager:latest
|
||||
-- cron service: n8n
|
||||
-- ==========================================================
|
||||
-- [v1.8.0 UPDATE] Prepare migration
|
||||
-- [v1.9.0 UPDATE] Prepare migration
|
||||
-- Update: Upgraded from v1.7.0
|
||||
-- Last Updated: 2026-02-27
|
||||
-- Major Changes:
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
-- ==========================================================
|
||||
-- DMS v1.8.0 Document Management System Database
|
||||
-- DMS v1.9.0 Document Management System Database
|
||||
-- Seed Contract Drawing data
|
||||
-- Server: Container Station on QNAP TS-473A
|
||||
-- Database service: MariaDB 11.8
|
||||
+66
-5
@@ -1,9 +1,9 @@
|
||||
-- ==========================================================
|
||||
-- DMS v1.8.0 - Permissions Seed Data (REORGANIZED)
|
||||
-- File: specs/07-database/lcbp3-v1.8.0-seed-permissions.sql
|
||||
-- DMS v1.9.0 - Permissions Seed Data (REORGANIZED)
|
||||
-- File: specs/07-database/lcbp3-v1.9.0-seed-permissions.sql
|
||||
-- Total Permissions: 85 (Reorganized with systematic ID allocation)
|
||||
-- Created: 2025-12-13
|
||||
-- Updated: 2026-02-28 (v1.8.0 merge)
|
||||
-- Updated: 2026-02-28 (v1.9.0 merge)
|
||||
-- ==========================================================
|
||||
-- Clear existing data
|
||||
TRUNCATE TABLE role_permissions;
|
||||
@@ -1069,7 +1069,7 @@ VALUES -- Contract Management
|
||||
|
||||
|
||||
-- ==========================================================
|
||||
-- MERGED FROM fix-project-permissions.sql (v1.8.0 Update)
|
||||
-- MERGED FROM fix-project-permissions.sql (v1.9.0 Update)
|
||||
-- ==========================================================
|
||||
-- Fix Project Permissions
|
||||
-- File: specs/07-database/fix-project-permissions.sql
|
||||
@@ -1099,4 +1099,65 @@ INSERT IGNORE INTO role_permissions (role_id, permission_id)
|
||||
VALUES (6, 202);
|
||||
-- 5. Grant project.view to Viewer (Role 5)
|
||||
INSERT IGNORE INTO role_permissions (role_id, permission_id)
|
||||
VALUES (5, 202);
|
||||
VALUES (5, 202);
|
||||
|
||||
-- ==========================================================
|
||||
-- 18. AI Module Permissions (ID 181-190) — ADR-023 v1.1
|
||||
-- Added: 2026-05-14 (Grilling Session)
|
||||
-- ==========================================================
|
||||
INSERT INTO permissions (
|
||||
permission_id,
|
||||
permission_name,
|
||||
description,
|
||||
module,
|
||||
is_active
|
||||
)
|
||||
VALUES (
|
||||
181,
|
||||
'ai.suggest',
|
||||
'รับ AI Suggestion เมื่อสร้าง/แก้ไขเอกสาร',
|
||||
'ai',
|
||||
1
|
||||
),
|
||||
(
|
||||
182,
|
||||
'ai.rag_query',
|
||||
'ใช้ RAG Q&A สืบค้นเอกสาร',
|
||||
'ai',
|
||||
1
|
||||
),
|
||||
(
|
||||
183,
|
||||
'ai.migration_manage',
|
||||
'จัดการ Migration Batch (Review/Import/Reject)',
|
||||
'ai',
|
||||
1
|
||||
),
|
||||
(
|
||||
184,
|
||||
'ai.audit_log_delete',
|
||||
'Hard Delete ai_audit_logs (Superadmin Only)',
|
||||
'ai',
|
||||
1
|
||||
);
|
||||
|
||||
-- Role 1: Superadmin — ได้รับทุก permission โดยอัตโนมัติผ่าน SELECT-all pattern (บรรทัด 825-829)
|
||||
-- Role 2: Org Admin — ai.suggest, ai.rag_query, ai.migration_manage
|
||||
INSERT IGNORE INTO role_permissions (role_id, permission_id)
|
||||
VALUES (2, 181),
|
||||
-- ai.suggest
|
||||
(2, 182),
|
||||
-- ai.rag_query
|
||||
(2, 183);
|
||||
|
||||
-- ai.migration_manage
|
||||
-- Role 3: Document Control — ai.suggest, ai.rag_query, ai.migration_manage
|
||||
INSERT IGNORE INTO role_permissions (role_id, permission_id)
|
||||
VALUES (3, 181),
|
||||
-- ai.suggest
|
||||
(3, 182),
|
||||
-- ai.rag_query
|
||||
(3, 183);
|
||||
|
||||
-- ai.migration_manage
|
||||
-- ai.audit_log_delete (184) — Superadmin เท่านั้น, ไม่ grant ให้ Role อื่น
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
-- ==========================================================
|
||||
-- DMS v1.8.0 Document Management System Database
|
||||
-- DMS v1.9.0 Document Management System Database
|
||||
-- Seed Shop Drawing data
|
||||
-- Server: Container Station on QNAP TS-473A
|
||||
-- Database service: MariaDB 11.8
|
||||
Reference in New Issue
Block a user