127 KiB
ตารางฐานข้อมูล (Data Dictionary) - LCBP3-DMS (V1.4.2)
เอกสารนี้สรุปโครงสร้างตาราง, Foreign Keys (FK), และ Constraints ที่สำคัญทั้งหมดในฐานข้อมูล LCBP3-DMS (v1.4.0) เพื่อใช้เป็นเอกสารอ้างอิงสำหรับทีมพัฒนา Backend (NestJS) และ Frontend (Next.js) โดยอิงจาก Requirements และ SQL Script ล่าสุด [GEMINI]
สถานะ: FINAL GUIDELINE วันที่: 2025-11-19 อ้างอิง: Requirements v1.4.2 & FullStackJS Guidelines v1.4.2 Classification: Internal Technical Documentation
1. 🏢 Core & Master Data Tables (องค์กร, โครงการ, สัญญา)
1.1 organization_roles
Purpose: Master table for organization role types in the system
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier for organization role |
| role_name | VARCHAR(20) | NOT NULL, UNIQUE | Role name (OWNER, DESIGNER, CONSULTANT, CONTRACTOR, THIRD PARTY) |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (role_name)
Business Rules:
- Predefined system roles for organization types
- Cannot be deleted if referenced by organizations
1.2 organizations
Purpose: Master table storing all organizations involved in the system
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier for organization |
| organization_code | VARCHAR(20) | NOT NULL, UNIQUE | Organization code (e.g., 'กทท.', 'TEAM') |
| organization_name | VARCHAR(255) | NOT NULL | Full organization name |
| is_active | BOOLEAN | DEFAULT TRUE | Active status (1=active, 0=inactive) |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (organization_code)
- INDEX (is_active)
Relationships:
- Referenced by: users, project_organizations, contract_organizations, correspondences, circulations
Seed Data: Pre-populated with 15 organizations including:
- Port Authority of Thailand (กทท.)
- Project supervision consultants (สค©.3-xx)
- Design consultants (TEAM)
- Construction supervisors (คคง.)
- Contractors (ผรม.1-4)
- Third parties (EN, CAR)
1.3 projects
Purpose: Master table for all projects in the system
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier for project |
| project_code | VARCHAR(50) | NOT NULL, UNIQUE | Project code (e.g., 'LCBP3') |
| project_name | VARCHAR(255) | NOT NULL | Full project name |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (project_code)
- INDEX (is_active)
Relationships:
- Referenced by: contracts, correspondences, document_number_formats, drawings
Seed Data: 5 projects for Laem Chabang Port Phase 3 (LCBP3) including main project and 4 sub-contracts
1.4 contracts
Purpose: Master table for contracts within projects
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier for contract |
| project_id | INT | NOT NULL, FK | Reference to projects table |
| contract_code | VARCHAR(50) | NOT NULL, UNIQUE | Contract code |
| contract_name | VARCHAR(255) | NOT NULL | Full contract name |
| description | TEXT | NULL | Contract description |
| start_date | DATE | NULL | Contract start date |
| end_date | DATE | NULL | Contract end date |
| is_active | BOOLEAN | DEFAULT TRUE | Active status |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (contract_code)
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- INDEX (project_id, is_active)
Relationships:
- Parent: projects
- Referenced by: contract_organizations, user_assignments
Seed Data: 7 contracts including design, supervision, construction, and environmental monitoring
2. 👥 Users & RBAC Tables (ผู้ใช้, สิทธิ์, บทบาท)
2.1 users
Purpose: Master table storing all system users
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| user_id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier for user |
| username | VARCHAR(50) | NOT NULL, UNIQUE | Login username |
| password_hash | VARCHAR(255) | NOT NULL | Hashed password (bcrypt) |
| first_name | VARCHAR(50) | NULL | User's first name |
| last_name | VARCHAR(50) | NULL | User's last name |
| VARCHAR(100) | NOT NULL, UNIQUE | Email address | |
| line_id | VARCHAR(100) | NULL | LINE messenger ID |
| primary_organization_id | INT | NULL, FK | Primary organization affiliation |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
| failed_attempts | INT | DEFAULT 0 | Failed login attempts counter |
| locked_until | DATETIME | NULL | Account lock expiration time |
| last_login_at | TIMESTAMP | NULL | Last successful login timestamp |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
| deleted_at | DATETIME | NULL | Deleted at |
Indexes:
- PRIMARY KEY (user_id)
- UNIQUE (username)
- UNIQUE (email)
- FOREIGN KEY (primary_organization_id) REFERENCES organizations(id) ON DELETE SET NULL
- INDEX (is_active)
- INDEX (email)
Relationships:
- Parent: organizations (primary_organization_id)
- Referenced by: user_assignments, audit_logs, notifications, circulation_routings
Security Features:
- Password stored as bcrypt hash
- Account locking after failed attempts
- Last login tracking
Seed Data: 3 initial users (superadmin, editor01, viewer01)
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, Organization, Project, Contract |
| description | TEXT | NULL | Role description |
| is_system | BOOLEAN | DEFAULT FALSE | System role flag (cannot be deleted) |
Indexes:
- PRIMARY KEY (role_id)
- INDEX (scope)
Relationships:
- Referenced by: role_permissions, user_assignments
Seed Data: 7 predefined roles
- Superadmin (Global) - Full system access
- Org Admin (Organization) - Organization management
- Document Control (Organization) - Document lifecycle management
- Editor (Organization) - Document creation and editing
- Viewer (Organization) - Read-only access
- Project Manager (Project) - Project-level management
- Contract Admin (Contract) - Contract-specific administration
2.3 permissions
Purpose: Master table defining all system permissions
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| permission_id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier for permission |
| permission_name | VARCHAR(100) | NOT NULL, UNIQUE | Permission code (e.g., 'rfas.create', 'document.view') |
| description | TEXT | NULL | Permission description |
| module | VARCHAR(50) | NULL | Related module name |
| scope_level | ENUM | NULL | Scope: GLOBAL, ORG, PROJECT |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
Indexes:
- PRIMARY KEY (permission_id)
- UNIQUE (permission_name)
- INDEX (module)
- INDEX (scope_level)
- INDEX (is_active)
Relationships:
- Referenced by: role_permissions
Permission Categories:
- System Management (1): system.manage_all
- Organization Management (2-5): create, edit, delete, view
- Project Management (6-9, 23-26): create, edit, delete, view, manage members/contracts/reports
- Role & Permission Management (10-13): create, edit, delete roles, assign permissions
- Master Data Management (14-17): document types, statuses, categories, tags
- User Management (18-22): create, edit, delete, view, assign organization
- Contract Management (27-28): manage members, view
- Document Management (29-44): CRUD operations, workflows, circulation
- Search & Reporting (48-49): advanced search, generate reports
Total Permissions: 49
2.4 role_permissions
Purpose: Junction table mapping roles to permissions (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| role_id | INT | PRIMARY KEY, FK | Reference to roles table |
| permission_id | INT | PRIMARY KEY, FK | Reference to permissions table |
Indexes:
- PRIMARY KEY (role_id, permission_id)
- FOREIGN KEY (role_id) REFERENCES roles(role_id) ON DELETE CASCADE
- FOREIGN KEY (permission_id) REFERENCES permissions(permission_id) ON DELETE CASCADE
- INDEX (permission_id)
Relationships:
- Parent: roles, permissions
Seed Data: Complete permission mappings for all 7 roles
- Superadmin: All 49 permissions
- Org Admin: 15 permissions (user/org/tag management, view access)
- Document Control: 26 permissions (full document lifecycle)
- Editor: 12 permissions (document CRUD without admin powers)
- Viewer: 2 permissions (view and search only)
- Project Manager: 23 permissions (project management + document CRUD)
- Contract Admin: 15 permissions (contract management + document CRUD)
2.5 user_assignments
Purpose: Junction table assigning users to roles with scope context
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| user_id | INT | NOT NULL, FK | Reference to users table |
| role_id | INT | NOT NULL, FK | Reference to roles table |
| organization_id | INT | NULL, FK | Organization scope (if applicable) |
| project_id | INT | NULL, FK | Project scope (if applicable) |
| contract_id | INT | NULL, FK | Contract scope (if applicable) |
| assigned_by_user_id | INT | NULL, FK | User who made the assignment |
| assigned_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Assignment timestamp |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
- FOREIGN KEY (role_id) REFERENCES roles(role_id) ON DELETE CASCADE
- FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- FOREIGN KEY (contract_id) REFERENCES contracts(id) ON DELETE CASCADE
- FOREIGN KEY (assigned_by_user_id) REFERENCES users(user_id)
- INDEX (user_id, role_id)
- INDEX (organization_id)
- INDEX (project_id)
- INDEX (contract_id)
Constraints:
- CHECK: Only one scope field (organization_id, project_id, contract_id) can be NOT NULL, or all NULL for Global scope
Relationships:
- Parent: users, roles, organizations, projects, contracts
Business Rules:
- User can have multiple role assignments with different scopes
- Scope inheritance: Contract → Project → Organization → Global
- Global scope: all scope fields are NULL
2.6 project_organizations
Purpose: Junction table linking projects to participating organizations (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| project_id | INT | PRIMARY KEY, FK | Reference to projects table |
| organization_id | INT | PRIMARY KEY, FK | Reference to organizations table |
Indexes:
- PRIMARY KEY (project_id, organization_id)
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE
- INDEX (organization_id)
Relationships:
- Parent: projects, organizations
Seed Data: Pre-populated with project-organization relationships
2.7 contract_organizations
Purpose: Junction table linking contracts to participating organizations with roles (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| contract_id | INT | PRIMARY KEY, FK | Reference to contracts table |
| organization_id | INT | PRIMARY KEY, FK | Reference to organizations table |
| role_in_contract | VARCHAR(100) | NULL | Organization's role in contract (Owner, Designer, Consultant, Contractor) |
Indexes:
- PRIMARY KEY (contract_id, organization_id)
- FOREIGN KEY (contract_id) REFERENCES contracts(id) ON DELETE CASCADE
- FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE
- INDEX (organization_id)
- INDEX (role_in_contract)
Relationships:
- Parent: contracts, organizations
Seed Data: Pre-populated with contract-organization-role relationships
3. ✉️ Correspondences Tables (เอกสารหลัก, Revisions, Workflows)
3.1 correspondence_types
Purpose: Master table for correspondence document types
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| type_code | VARCHAR(50) | NOT NULL, UNIQUE | Type code (e.g., 'RFA', 'RFI', 'TRANSMITTAL') |
| type_name | VARCHAR(255) | NOT NULL | Full type name |
| sort_order | INT | DEFAULT 0 | Display order |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (type_code)
- INDEX (is_active)
- INDEX (sort_order)
Relationships:
- Referenced by: correspondences, document_number_formats, document_number_counters
Seed Data: 10 correspondence types including RFA, RFI, TRANSMITTAL, EMAIL, INSTRUCTION, LETTER, MEMO, MOM, NOTICE, OTHER
3.2 correspondence_status
Purpose: Master table for correspondence status codes
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| status_code | VARCHAR(50) | NOT NULL, UNIQUE | Status code (e.g., 'DRAFT', 'SUBOWN') |
| status_name | VARCHAR(255) | NOT NULL | Full status name |
| sort_order | INT | DEFAULT 0 | Display order |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (status_code)
- INDEX (is_active)
- INDEX (sort_order)
Relationships:
- Referenced by: correspondence_revisions
Seed Data: 23 status codes covering draft, submission, reply, resubmission, closure, and cancellation states by different parties (Owner, Designer, CSC, Contractor)
3.3 correspondences
Purpose: Master table for correspondence documents (non-revisioned data)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Master correspondence ID |
| correspondence_number | VARCHAR(100) | NOT NULL | Document number (from numbering system) |
| correspondence_type_id | INT | NOT NULL, FK | Reference to correspondence_types |
| is_internal_communication | TINYINT(1) | DEFAULT 0 | Internal (1) or external (0) communication |
| project_id | INT | NOT NULL, FK | Reference to projects table |
| originator_id | INT | NULL, FK | Originating organization |
| 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 (correspondence_type_id) REFERENCES correspondence_types(id) ON DELETE RESTRICT
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- FOREIGN KEY (originator_id) REFERENCES organizations(id) ON DELETE SET NULL
- FOREIGN KEY (created_by) REFERENCES users(user_id) ON DELETE SET NULL
- UNIQUE KEY (project_id, correspondence_number)
- INDEX (correspondence_type_id)
- INDEX (originator_id)
- INDEX (deleted_at)
Relationships:
- Parent: correspondence_types, projects, organizations, users
- Children: correspondence_revisions, correspondence_recipients, correspondence_tags, correspondence_references, correspondence_attachments, circulations, transmittals
Business Rules:
- One correspondence can have multiple revisions
- Correspondence number must be unique within a project
- Soft delete preserves history
3.4 correspondence_revisions
Purpose: Child table storing revision history of correspondences (1:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
| correspondence_id | INT | NOT NULL, FK | Master correspondence ID |
| revision_number | INT | NOT NULL | Revision sequence (0, 1, 2...) |
| revision_label | VARCHAR(10) | NULL | Display revision (A, B, 1.1...) |
| is_current | BOOLEAN | DEFAULT FALSE | Current revision flag |
| correspondence_status_id | INT | NOT NULL, FK | Current status of this revision |
| title | VARCHAR(255) | NOT NULL | Document title |
| document_date | DATE | NULL | Document date |
| issued_date | DATETIME | NULL | Issue date |
| received_date | DATETIME | NULL | Received date |
| due_date | DATETIME | NULL | Due date for response |
| description | TEXT | NULL | Revision description |
| details | JSON | NULL | Type-specific details (e.g., RFI questions) |
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Revision creation timestamp |
| 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 |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (correspondence_id) REFERENCES correspondences(id) ON DELETE CASCADE
- FOREIGN KEY (correspondence_status_id) REFERENCES correspondence_status(id) ON DELETE RESTRICT
- FOREIGN KEY (created_by) REFERENCES users(user_id) ON DELETE SET NULL
- FOREIGN KEY (updated_by) REFERENCES users(user_id) ON DELETE SET NULL
- UNIQUE KEY (correspondence_id, revision_number)
- UNIQUE KEY (correspondence_id, is_current) - Only one current revision per correspondence
- INDEX (correspondence_status_id)
- INDEX (is_current)
- INDEX (document_date)
- INDEX (issued_date)
- INDEX (v_ref_project_id)
- INDEX (v_ref_type)
Relationships:
- Parent: correspondences, correspondence_status, users
Business Rules:
- Only one revision can be marked as current (is_current=TRUE) per correspondence
- Revision numbers are sequential starting from 0
- JSON details field allows type-specific data storage
3.5 correspondence_recipients
Purpose: Junction table for correspondence recipients (TO/CC) (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| correspondence_id | INT | PRIMARY KEY, FK | Reference to correspondences |
| recipient_organization_id | INT | PRIMARY KEY, FK | Recipient organization |
| recipient_type | ENUM('TO', 'CC') | PRIMARY KEY | Recipient type |
Indexes:
- PRIMARY KEY (correspondence_id, recipient_organization_id, recipient_type)
- FOREIGN KEY (correspondence_id) REFERENCES correspondence_revisions(correspondence_id) ON DELETE CASCADE
- FOREIGN KEY (recipient_organization_id) REFERENCES organizations(id) ON DELETE RESTRICT
- INDEX (recipient_organization_id)
- INDEX (recipient_type)
Relationships:
- Parent: correspondences, organizations
Business Rules:
- One organization can be both TO and CC recipient
- Cascade delete when correspondence is deleted
3.6 tags
Purpose: Master table for document tagging system
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique tag ID |
| tag_name | VARCHAR(100) | NOT NULL, UNIQUE | Tag name |
| description | TEXT | NULL | Tag description |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (tag_name)
- INDEX (tag_name) - For autocomplete
Relationships:
- Referenced by: correspondence_tags
3.7 correspondence_tags
Purpose: Junction table linking correspondences to tags (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| correspondence_id | INT | PRIMARY KEY, FK | Reference to correspondences |
| tag_id | INT | PRIMARY KEY, FK | Reference to tags |
Indexes:
- PRIMARY KEY (correspondence_id, tag_id)
- FOREIGN KEY (correspondence_id) REFERENCES correspondences(id) ON DELETE CASCADE
- FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE
- INDEX (tag_id)
Relationships:
- Parent: correspondences, tags
3.8 correspondence_references
Purpose: Junction table for cross-referencing correspondences (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| src_correspondence_id | INT | PRIMARY KEY, FK | Source correspondence ID |
| tgt_correspondence_id | INT | PRIMARY KEY, FK | Target (referenced) correspondence ID |
Indexes:
- PRIMARY KEY (src_correspondence_id, tgt_correspondence_id)
- FOREIGN KEY (src_correspondence_id) REFERENCES correspondences(id) ON DELETE CASCADE
- FOREIGN KEY (tgt_correspondence_id) REFERENCES correspondences(id) ON DELETE CASCADE
- INDEX (tgt_correspondence_id)
Relationships:
- Parent: correspondences (both sides)
Business Rules:
- Allows tracing document relationships
- Bi-directional references should be created as separate records
3.9 ตาราง correspondence_routing_templates
Purpose: เก็บข้อมูลแม่แบบ (Template) ของสายงานการส่งต่อเอกสารเพื่อขออนุมัติ ทำให้ไม่ต้องกำหนดขั้นตอนซ้ำทุกครั้ง สามารถสร้างเป็นแม่แบบทั่วไป หรือเฉพาะสำหรับโครงการใดโครงการหนึ่งได้
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลัก (Primary Key) ของแม่แบบ รันค่าอัตโนมัติ |
| template_name | VARCHAR(255) | NOT NULL | ชื่อของแม่แบบ เช่น "เสนอโครงการ", "ขออนุมัติจัดซื้อ" |
| description | TEXT | NULL | คำอธิบายรายละเอียดเกี่ยวกับแม่แบบนี้ |
| project_id | INT | NULL | ID ของโครงการที่แม่แบบนี้สังกัดอยู่ (ถ้ามี) ค่า NULL หมายถึง เป็น "แม่แบบทั่วไป" ที่สามารถใช้กับทุกโครงการได้ |
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | วันที่และเวลาที่สร้างแม่แบบนี้ |
| updated_at | TIMESTAMP | NOT NULL,`DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | วันที่และเวลาที่แก้ไขข้อมูลในแม่แบบนี้ล่าสุด |
| is_active | BOOLEAN | DEFAULT TRUE | สถานะใช้งาน |
| workflow_config | JSON | NULL | เก็บ State Machine Configuration หรือ Rules เพิ่มเติมที่ซับซ้อนกว่า Column ปกติ |
Indexes:
- ux_routing_template_name_project (template_name, project_id): ดัชนีแบบ UNIQUE ป้องกันการมีชื่อแม่แบบซ้ำกันในแต่ละโครงการ หรือในส่วนของแม่แบบทั่วไป (ที่ project_id เป็น NULL)
ความสัมพันธ์ Foreign Key:
- fk_crt_project: อ้างอิงไปยัง projects(id)
- ON DELETE CASCAD`: ถ้าโครงการ (projects) ถูกลบ แม่แบบที่เกี่ยวข้องกับโครงการนั้นๆ จะถูกลบไปด้วยทั้งหมด
3.10 ตาราง correspondence_routing_template_steps
Purpose: เก็บรายละเอียดของแต่ละขั้นตอน (Steps) ภายในแม่แบบสายงาน (correspondence_routing_templates) กำหนดว่าจะส่งไปที่องค์กรไหน ลำดับเป็นเท่าไร และเพื่อวัตถุประสงค์อะไร
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของขั้นตอน |
| template_id | INT | NOT NULL | ID ของแม่แบบที่ขั้นตอนนี้สังกัดอยู่ |
| sequence | INT | NOT NULL | ลำดับของขั้นตอน (1, 2, 3, ...) |
| to_organization_id | INT | NOT NULL | ID ขององค์กรที่เป็นผู้รับในขั้นตอนนี้ |
| step_purpose | ENUM | NOT NULL,DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้ ค่าที่เป็นไปได้: [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ] |
| expected_days | INT | NULL | วันที่คาดหวัง |
Indexes:
- ux_cor_template_sequence (template_id, sequence): ดัชนีแบบ UNIQUE ป้องกันการมีลำดับขั้นตอนซ้ำกันภายในแม่แบบเดียวกัน
ความสัมพันธ์ Foreign Key:
- fk_cwts_template: อ้างอิงไปยัง correspondence_routing_templates(id)
- ON DELETE CASCADE: ถ้าแม่แบบถูกลบ ขั้นตอนทั้งหมดภายในแม่แบบนั้นจะถูกลบไปด้วย
- fk_cwts_org: อ้างอิงไปยัง organizations(id)
- ON DELETE CASCADE: ถ้าองค์กรถูกลบ ขั้นตอนที่ชี้ไปยังองค์กรนั้นจะถูกลบ
3.11 ตาราง correspondence_routings
Purpose: เป็นตารางที่เก็บข้อมูลการส่งต่อเอกสารจริง (Instance/Run-time) ติดตามประวัติการเคลื่อนย้ายของแต่ละเอกสาร ว่าผ่านใครมาบ้าง อยู่ที่ใคร และสถานะปัจจุบันคืออะไร
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของรายการส่งต่อ |
| correspondence_id | INT | NOT NUL | ID ของเอกสาร (FK ไปยัง correspondence_revisions) |
| template_id | INT | NULL | ID ของแม่แบบที่ใช้สร้างสายงานนี้ (เก็บไว้เป็นข้อมูลอ้างอิง) |
| sequence | INT | NOT NULL | ลำดับของขั้นตอนการส่งต่อจริง |
| from_organization_id | INT | NOT NULL | ID ขององค์กรผู้ส่ง |
| to_organization_id | INT | NOT NULL | ID ขององค์กรผู้รับ |
| step_purpose | ENUM | NOT NULL, DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้จริง ค่าที่เป็นไปได้: [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ, FOR_ACTION: เพื่อดำเนินการ] |
| status | ENUM | NOT NULL, DEFAULT SENT | [ACTIONED: ดำเนินการแล้ว, FORWARDED: ส่งต่อแล้ว, REPLIE: ตอบกลับแล้ว] |
| comments | TEXT | NULL | หมายเหตุหรือความคิดเห็นในการส่งต่อ |
| due_date | DATETIME | NULL | วันที่ครบกำหนดที่ต้องดำเนินการในขั้นตอนนี้ |
| processed_by_user_id | INT | NULL | ID ของผู้ใช้ที่ดำเนินการในขั้นตอนนี้จริงๆ |
| processed_at | TIMESTAMP | NULL | เวลาที่ผู้ใช้ดำเนินการเสร็จสิ้น |
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | เวลาที่สร้างรายการส่งต่อนี้ |
| state_context | JSON | NULL | เก็บข้อมูล Context ของ Workflow ณ ขณะนั้น (Snapshot) |
Indexes:
- ux_cor_routing_sequence (correspondence_id, sequence): ดัชนีแบบ UNIQUE ทำให้มั่นใจได้ว่าแต่ละเอกสารจะมีขั้นตอนการส่งต่อตามลำดับได้เพียงชุดเดียว
ความสัมพันธ์ Foreign Key:
- fk_crs_correspondence: อ้างอิงไปยัง correspondence_revisions(correspondence_id)
- ON DELETE CASCADE`: ถ้าเอกสาร (revision) ถูกลบ ประวัติการส่งต่อทั้งหมดจะถูกลบไปด้วย
- fk_crs_template: อ้างอิงไปยัง correspondence_routing_templates(id)
- ON DELETE SET NULL: ถ้าแม่แบบถูกลบ ค่า template_id ในตารางนี้จะถูกเปลี่ยนเป็น NULL เพื่อรักษาประวัติการส่งต่อไว้
- fk_crs_from_org: อ้างอิงไปยัง organizations(id)
- ON DELETE CASCADE: ถ้าองค์กรผู้ส่งถูกลบ รายการส่งต่อนี้จะถูกลบ
- fk_crs_to_org: อ้างอิงไปยัง organizations(id)
- ON DELETE CASCADE: ถ้าองค์กรผู้รับถูกลบ รายการส่งต่อนี้จะถูกลบ
- fk_crs_processed_by_user: อ้างอิงไปยัง users(user_id)
- ON DELETE SET NULL: ถ้าผู้ใช้ถูกลบ ค่า processed_by_user_id จะถูกเปลี่ยนเป็น NULL เพื่อรักษาประวัติการดำเนินการไว้
3.12 ตาราง correspondence_status_transitions
Purpose: ตารางนี้ใช้กำหนดกฎ (State Machine) ว่าสถานะใดสามารถเปลี่ยนไปเป็นสถานะใดได้บ้าง โดยขึ้นอยู่กับประเภทของหนังสือ เพื่อควบคุมการไหลของสถานะให้ถูกต้องตามข้อบังคับ
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| type_id | INT | PRIMARY KEY | ID ของประเภทหนังสือ (เช่น หนังสือภายใน, หนังสือภายนอก) |
| from_status_id | INT | PRIMARY KEY | ID ของสถานะต้นทาง (เช่น ร่าง) |
| to_status_id | INT | PRIMARY KEY | ID ของสถานะปลายทาง (เช่น รออนุมัติ) |
คีย์หลัก (Primary Key):
- (type_id, from_status_id, to_status_id)`: คีย์หลักแบบประกอบ ทำให้แน่ใจว่าแต่ละประเภทหนังสือ การเปลี่ยนจากสถานะหนึ่งไปอีกสถานะหนึ่งจะซ้ำกันไม่ได้
ความสัมพันธ์ Foreign Key:
- fk_cst_type : อ้างอิงไปยัง correspondence_types(id)
- fk_cst_from : อ้างอิงไปยัง correspondence_status(id)
- fk_cst_to : อ้างอิงไปยัง correspondence_status(id)
- ไม่มีการกำหนด ON DELETE จึงเป็นค่าเริ่มต้น RESTRICT หมายความว่า จะลบประเภทหนังสือหรือสถานะไม่ได้ ถ้ายังมีการใช้งานอยู่ในตารางนี้
4. 📐 approval: RFA Tables (เอกสารขออนุมัติ, Workflows)
4.1 rfa_types
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 |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (type_code)
- INDEX (is_active)
- INDEX (sort_order)
Relationships:
- Referenced by: rfas
Seed Data: 11 RFA types including Shop Drawing (DWG), Document (DOC), Specification (SPC), Calculation (CAL), Test Report (TRP), Survey Report (SRY), QA/QC Document, Method Statement (MES), Material (MAT), As-Built (ASB), Other (OTH)
4.2 rfa_status_codes
Purpose: Master table for RFA status codes
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| status_code | VARCHAR(20) | NOT NULL, UNIQUE | Status code (DFT, FAP, FRE, etc.) |
| status_name | VARCHAR(100) | NOT NULL | Full status name |
| description | TEXT | NULL | Status description |
| sort_order | INT | DEFAULT 0 | Display order |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (status_code)
- INDEX (is_active)
- INDEX (sort_order)
Relationships:
- Referenced by: rfa_revisions
Seed Data: 7 status codes
- DFT: Draft
- FAP: For Approve
- FRE: For Review
- FCO: For Construction
- ASB: AS-Built
- OBS: Obsolete
- CC: Canceled
4.3 rfa_approve_codes
Purpose: Master table for RFA approval result codes
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| approve_code | VARCHAR(20) | NOT NULL, UNIQUE | Approval code (1A, 1C, 3R, etc.) |
| approve_name | VARCHAR(100) | NOT NULL | Full approval name |
| description | TEXT | NULL | Code description |
| sort_order | INT | DEFAULT 0 | Display order |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (approve_code)
- INDEX (is_active)
- INDEX (sort_order)
Relationships:
- Referenced by: rfa_revisions
Seed Data: 8 approval codes
- 1A: Approved by Authority
- 1C: Approved by CSC
- 1N: Approved As Note
- 1R: Approved with Remarks
- 3C: Consultant Comments
- 3R: Revise and Resubmit
- 4X: Reject
- 5N: No Further Action
4.4 rfas
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 |
| 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 (rfa_type_id) REFERENCES rfa_types(id)
- FOREIGN KEY (created_by) REFERENCES users(user_id) ON DELETE SET NULL
- INDEX (rfa_type_id)
- INDEX (deleted_at)
Relationships:
- Parent: rfa_types, users
- Children: rfa_revisions
Business Rules:
- One RFA can have multiple revisions
- Soft delete preserves history
4.5 rfa_revisions
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) |
| 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...) |
| is_current | BOOLEAN | DEFAULT FALSE | Current revision flag |
| rfa_status_code_id | INT | NOT NULL, FK | Current RFA status |
| rfa_approve_code_id | INT | NULL, FK | Approval result code |
| title | VARCHAR(255) | NOT NULL | RFA title |
| document_date | DATE | NULL | Document date |
| issued_date | DATE | NULL | Issue date for approval |
| received_date | DATETIME | NULL | Received date |
| approved_date | DATE | NULL | Approval date |
| description | TEXT | NULL | Revision description |
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Revision creation timestamp |
| created_by | INT | NULL, FK | User who created revision |
| updated_by | INT | NULL, FK | User who last updated |
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
- FOREIGN KEY (created_by) REFERENCES users(user_id) ON DELETE SET NULL
- FOREIGN KEY (updated_by) REFERENCES users(user_id) ON DELETE SET NULL
- UNIQUE KEY (rfa_id, revision_number)
- UNIQUE KEY (rfa_id, is_current)
- INDEX (rfa_status_code_id)
- INDEX (rfa_approve_code_id)
- INDEX (is_current)
Relationships:
- Parent: correspondences, rfas, rfa_status_codes, rfa_approve_codes, users
- Children: rfa_items, rfa_workflows
Business Rules:
- RFA is a specialized type of correspondence
- Only one revision can be current per RFA
- Links to shop drawings through rfa_items
4.6 rfa_items
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 |
Indexes:
- PRIMARY KEY (rfarev_correspondence_id, shop_drawing_revision_id)
- FOREIGN KEY (rfarev_correspondence_id) REFERENCES rfa_revisions(correspondence_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: rfa_revisions, shop_drawing_revisions
Business Rules:
- Used primarily for RFA type = 'DWG' (Shop Drawing)
- One RFA can contain multiple shop drawings
- One shop drawing can be referenced by multiple RFAs
4.7 rfa_workflow_templates
Purpose: Master table for RFA approval workflow templates
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique template ID |
| template_name | VARCHAR(100) | NOT NULL | Template name |
| description | TEXT | NULL | Template description |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
| workflow_config | JSON | NULL | เก็บ State Machine Configuration หรือ Rules เพิ่มเติมที่ซับซ้อนกว่า Column ปกติ |
Indexes:
- PRIMARY KEY (id)
- INDEX (is_active)
- INDEX (template_name)
Relationships:
- Children: rfa_workflow_template_steps
Business Rules:
- Defines reusable approval workflows for RFAs
- Can be assigned to specific RFA types or organizations
4.8 rfa_workflow_template_steps
Purpose: Child table defining steps in workflow templates
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique step ID |
| template_id | INT | NOT NULL, FK | Reference to workflow template |
| step_number | INT | NOT NULL | Step sequence order |
| organization_id | INT | NOT NULL, FK | Organization responsible for step |
| role_id | INT | NULL, FK | Required role for this step |
| action_type | ENUM | NULL | Action type: REVIEW, APPROVE, ACKNOWLEDGE |
| duration_days | INT | NULL | Expected duration in days |
| is_optional | BOOLEAN | DEFAULT FALSE | Optional step flag |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (template_id) REFERENCES rfa_workflow_templates(id) ON DELETE CASCADE
- FOREIGN KEY (organization_id) REFERENCES organizations(id)
- FOREIGN KEY (role_id) REFERENCES roles(role_id)
- INDEX (template_id, step_number)
- INDEX (organization_id)
Relationships:
- Parent: rfa_workflow_templates, organizations, roles
Business Rules:
- Steps are executed in step_number order
- Optional steps can be skipped
- Duration used for deadline calculation
4.9 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
5. 📐 Drawings Tables (แบบ, หมวดหมู่)
5.1 contract_drawing_volumes
Purpose: Master table for contract drawing volume classification
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique volume ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| volume_code | VARCHAR(50) | NOT NULL | Volume code |
| volume_name | VARCHAR(255) | NOT NULL | Volume name |
| description | TEXT | NULL | Volume description |
| sort_order | INT | DEFAULT 0 | Display order |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- UNIQUE KEY (project_id, volume_code)
- INDEX (sort_order)
Relationships:
- Parent: projects
- Referenced by: contract_drawings
Business Rules:
- Volume codes must be unique within a project
- Used for organizing large sets of contract drawings
5.2 contract_drawing_cats
Purpose: Master table for contract drawing main categories
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique category ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| cat_code | VARCHAR(50) | NOT NULL | Category code |
| cat_name | VARCHAR(255) | NOT NULL | Category name |
| description | TEXT | NULL | Category description |
| sort_order | INT | DEFAULT 0 | Display order |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- UNIQUE KEY (project_id, cat_code)
- INDEX (sort_order)
Relationships:
- Parent: projects
- Referenced by: contract_drawing_subcat_cat_maps
Business Rules:
- Category codes must be unique within a project
- Hierarchical relationship with sub-categories via mapping table
5.3 contract_drawing_sub_cats
Purpose: Master table for contract drawing sub-categories
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique sub-category ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| sub_cat_code | VARCHAR(50) | NOT NULL | Sub-category code |
| sub_cat_name | VARCHAR(255) | NOT NULL | Sub-category name |
| description | TEXT | NULL | Sub-category description |
| sort_order | INT | DEFAULT 0 | Display order |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- UNIQUE KEY (project_id, sub_cat_code)
- INDEX (sort_order)
Relationships:
- Parent: projects
- Referenced by: contract_drawings, contract_drawing_subcat_cat_maps
Business Rules:
- Sub-category codes must be unique within a project
- Can be mapped to multiple main categories via mapping table
5.4 contract_drawing_subcat_cat_maps
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 |
Indexes:
- PRIMARY 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
- INDEX (sub_cat_id)
- INDEX (cat_id)
Relationships:
- Parent: projects, contract_drawing_sub_cats, contract_drawing_cats
Business Rules:
- Allows flexible categorization
- One sub-category can belong to multiple main categories
- All three fields required for uniqueness
5.5 contract_drawings
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 |
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 (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 (volume_id)
- INDEX (deleted_at)
Relationships:
- Parent: projects, contract_drawing_sub_cats, contract_drawing_volumes, users
- Referenced by: shop_drawing_revision_contract_refs, contract_drawing_attachments
Business Rules:
- Drawing numbers must be unique within a project
- Represents baseline/contract drawings
- Referenced by shop drawings for compliance tracking
- Soft delete preserves history
5.6 shop_drawing_main_categories
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 |
| 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 |
| sort_order | INT | DEFAULT 0 | Display order |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (main_category_code)
- INDEX (is_active)
- INDEX (sort_order)
Relationships:
- Referenced by: shop_drawing_sub_categories, shop_drawings
Business Rules:
- Global categories (not project-specific)
- Typically represents engineering disciplines
5.7 shop_drawing_sub_categories
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 |
| 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 |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (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
Business Rules:
- Global sub-categories (not project-specific)
- Hierarchical under main categories
- Represents specific drawing types or components
5.8 shop_drawings
Purpose: Master table for shop drawings (contractor-submitted)
| 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 | 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 |
| 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: shop_drawing_revisions
Business Rules:
- Drawing numbers are globally unique across all projects
- Represents contractor shop drawings
- Can have multiple revisions
- Soft delete preserves history
5.9 shop_drawing_revisions
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 |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (shop_drawing_id) REFERENCES shop_drawings(id) ON DELETE CASCADE
- UNIQUE KEY (shop_drawing_id, revision_number)
- INDEX (revision_date)
Relationships:
- Parent: shop_drawings
- Referenced by: rfa_items, shop_drawing_revision_contract_refs, shop_drawing_revision_attachments
Business Rules:
- Revision numbers are sequential starting from 0
- Each revision can reference multiple contract drawings
- Each revision can have multiple file attachments
- Linked to RFAs for approval tracking
5.10 shop_drawing_revision_contract_refs
Purpose: Junction table linking shop drawing revisions to referenced contract drawings (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| shop_drawing_revision_id | INT | PRIMARY KEY, FK | Reference to shop drawing revision |
| contract_drawing_id | INT | PRIMARY KEY, FK | Reference to contract drawing |
Indexes:
- PRIMARY KEY (shop_drawing_revision_id, contract_drawing_id)
- FOREIGN KEY (shop_drawing_revision_id) REFERENCES shop_drawing_revisions(id) ON DELETE CASCADE
- FOREIGN KEY (contract_drawing_id) REFERENCES contract_drawings(id) ON DELETE CASCADE
- INDEX (contract_drawing_id)
Relationships:
- Parent: shop_drawing_revisions, contract_drawings
Business Rules:
- Tracks which contract drawings each shop drawing revision is based on
- Ensures compliance with contract specifications
- One shop drawing revision can reference multiple contract drawings
6. 🔄 Circulations Tables (ใบเวียนภายใน)
6.1 circulation_status_codes
Purpose: Master table for circulation workflow status codes
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique status ID |
| code | VARCHAR(20) | NOT NULL, UNIQUE | Status code (OPEN, IN_REVIEW, COMPLETED, CANCELLED) |
| description | VARCHAR(50) | NOT NULL | Status description |
| sort_order | INT | DEFAULT 0 | Display order |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (code)
- INDEX (is_active)
- INDEX (sort_order)
Relationships:
- Referenced by: circulations
Seed Data: 4 status codes
- OPEN: Initial status when created
- IN_REVIEW: Under review by recipients
- COMPLETED: All recipients have responded
- CANCELLED: Withdrawn/cancelled
6.2 circulations
Purpose: Master table for internal circulation sheets (document routing)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique circulation ID |
| correspondence_id | INT | UNIQUE, FK | Link to correspondence (1:1 relationship) |
| organization_id | INT | NOT NULL, FK | Organization that owns this circulation |
| circulation_no | VARCHAR(100) | NOT NULL | Circulation sheet number |
| circulation_subject | VARCHAR(500) | NOT NULL | Subject/title |
| circulation_status_code | VARCHAR(20) | NOT NULL, FK | Current status code |
| created_by_user_id | INT | NOT NULL, FK | User who created circulation |
| submitted_at | TIMESTAMP | NULL | Submission timestamp |
| closed_at | TIMESTAMP | NULL | Closure timestamp |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (correspondence_id)
- FOREIGN KEY (correspondence_id) REFERENCES correspondences(id)
- FOREIGN KEY (organization_id) REFERENCES organizations(id)
- FOREIGN KEY (circulation_status_code) REFERENCES circulation_status_codes(code)
- FOREIGN KEY (created_by_user_id) REFERENCES users(user_id)
- INDEX (organization_id)
- INDEX (circulation_status_code)
- INDEX (created_by_user_id)
Relationships:
- Parent: correspondences, organizations, circulation_status_codes, users
- Children: circulation_routings, circulation_attachments
Business Rules:
- Internal document routing within organization
- One-to-one relationship with correspondences
- Tracks document review/approval workflow
- Status progression: OPEN → IN_REVIEW → COMPLETED/CANCELLED
6.3 circulation_templates
Purpose: Master table for circulation workflow templates
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique template ID |
| template_name | VARCHAR(100) | NOT NULL | Template name |
| description | TEXT | NULL | Template description |
| organization_id | INT | NOT NULL, FK | Template owner organization |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (organization_id) REFERENCES organizations(id)
- INDEX (organization_id)
- INDEX (is_active)
Relationships:
- Parent: organizations
- Children: circulation_template_assignees
Business Rules:
- Organization-specific templates
- Defines reusable routing workflows
6.4 circulation_template_assignees
Purpose: Child table defining steps in circulation templates
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique step ID |
| template_id | INT | NOT NULL, FK | Reference to template |
| step_number | INT | NOT NULL | Step sequence order |
| organization_id | INT | NOT NULL, FK | Organization responsible for step |
| role_id | INT | NULL, FK | Required role for this step |
| duration_days | INT | NULL | Expected duration in days |
| is_optional | BOOLEAN | DEFAULT FALSE | Optional step flag |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (template_id) REFERENCES circulation_templates(id) ON DELETE CASCADE
- FOREIGN KEY (organization_id) REFERENCES organizations(id)
- FOREIGN KEY (role_id) REFERENCES roles(role_id)
- INDEX (template_id, step_number)
- INDEX (organization_id)
Relationships:
- Parent: circulation_templates, organizations, roles
Business Rules:
- Steps executed in step_number order
- Optional steps can be skipped
- Duration used for deadline calculation
6.5 circulation_routings
Purpose: Transaction log table tracking actual circulation routing execution
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique routing log ID |
| circulation_id | INT | NOT NULL, FK | Reference to circulation |
| step_number | INT | NOT NULL | Current step number |
| organization_id | INT | NOT NULL, FK | Organization responsible |
| assigned_to | INT | NULL, FK | Assigned user ID |
| 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 |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (circulation_id) REFERENCES circulations(id) ON DELETE CASCADE
- FOREIGN KEY (organization_id) REFERENCES organizations(id)
- FOREIGN KEY (assigned_to) REFERENCES users(user_id)
- INDEX (circulation_id, step_number)
- INDEX (assigned_to, status)
- INDEX (status)
Relationships:
- Parent: circulations, organizations, users
Business Rules:
- Records actual routing history
- Multiple records per circulation (one per step)
- Tracks who reviewed/approved and when
- Used in v_user_tasks view for pending items
7. 📤 Transmittals Tables (เอกสารนำส่ง)
7.1 transmittals
Purpose: Child table for transmittal-specific data (1:1 with correspondences)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| correspondence_id | INT | PRIMARY KEY, FK | Reference to correspondences (1:1) |
| purpose | ENUM | NULL | Purpose: FOR_APPROVAL, FOR_INFORMATION, FOR_REVIEW, OTHER |
| remarks | TEXT | NULL | Additional remarks |
Indexes:
- PRIMARY KEY (correspondence_id)
- FOREIGN KEY (correspondence_id) REFERENCES correspondences(id) ON DELETE CASCADE
- INDEX (purpose)
Relationships:
- Parent: correspondences
- Children: transmittal_items
Business Rules:
- One-to-one relationship with correspondences
- Transmittal is a correspondence type for forwarding documents
- Contains metadata about the transmission
7.2 transmittal_items
Purpose: Junction table listing documents included in transmittal (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique item ID |
| transmittal_id | INT | NOT NULL, FK | Reference to transmittal |
| item_correspondence_id | INT | NOT NULL, FK | Reference to document being transmitted |
| quantity | INT | DEFAULT 1 | Number of copies |
| remarks | VARCHAR(255) | NULL | Item-specific remarks |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (transmittal_id) REFERENCES transmittals(correspondence_id) ON DELETE CASCADE
- FOREIGN KEY (item_correspondence_id) REFERENCES correspondences(id) ON DELETE CASCADE
- UNIQUE KEY (transmittal_id, item_correspondence_id)
- INDEX (item_correspondence_id)
Relationships:
- Parent: transmittals, correspondences
Business Rules:
- One transmittal can contain multiple documents
- Tracks quantity of physical copies (if applicable)
- Links to any type of correspondence document
8. 📎 File Management Tables (ไฟล์แนบ)
8.1 attachments
Purpose: Central repository for all file attachments in the system
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique attachment ID |
| original_filename | VARCHAR(255) | NOT NULL | Original filename from upload |
| stored_filename | VARCHAR(255) | NOT NULL | System-generated unique filename |
| file_path | VARCHAR(500) | NOT NULL | Full file path on server (/share/dms-data/) |
| mime_type | VARCHAR(100) | NOT NULL | MIME type (application/pdf, image/jpeg, etc.) |
| file_size | INT | NOT NULL | File size in bytes |
| uploaded_by_user_id | INT | NOT NULL, FK | User who uploaded file |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Upload timestamp |
| is_temporary | BOOLEAN | DEFAULT TRUE | ระบุว่าเป็นไฟล์ชั่วคราว (ยังไม่ได้ Commit) |
| temp_id* | VARCHAR(100) | NULL | ID ชั่วคราวสำหรับอ้างอิงตอน Upload Phase 1 (อาจใช้ร่วมกับ id หรือแยกก็ได้) |
| expires_at | DATETIME | NULL | เวลาหมดอายุของไฟล์ Temp (เพื่อให้ Cron Job ลบออก) |
| checksum | VARCHAR(64) | NULL | SHA-256 Checksum สำหรับ Verify File Integrity [Req 3.9.3] |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (uploaded_by_user_id) REFERENCES users(user_id) ON DELETE CASCADE
- INDEX (stored_filename)
- INDEX (mime_type)
- INDEX (uploaded_by_user_id)
- INDEX (created_at)
Relationships:
- Parent: users
- Referenced by: correspondence_attachments, circulation_attachments, shop_drawing_revision_attachments, contract_drawing_attachments
Business Rules:
- Central storage prevents file duplication
- Stored filename prevents naming conflicts
- File path points to QNAP NAS storage
- Original filename preserved for download
- One file record can be linked to multiple documents
8.2 correspondence_attachments
Purpose: Junction table linking correspondences to file attachments (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| correspondence_id | INT | PRIMARY KEY, FK | Reference to correspondences |
| attachment_id | INT | PRIMARY KEY, FK | Reference to attachments |
| is_main_document | BOOLEAN | DEFAULT FALSE | Main/primary document flag |
Indexes:
- PRIMARY KEY (correspondence_id, attachment_id)
- FOREIGN KEY (correspondence_id) REFERENCES correspondences(id) ON DELETE CASCADE
- FOREIGN KEY (attachment_id) REFERENCES attachments(id) ON DELETE CASCADE
- INDEX (attachment_id)
- INDEX (is_main_document)
Relationships:
- Parent: correspondences, attachments
Business Rules:
- One correspondence can have multiple attachments
- One attachment can be linked to multiple correspondences
- is_main_document identifies primary file (typically PDF)
8.3 circulation_attachments
Purpose: Junction table linking circulations to file attachments (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| circulation_id | INT | PRIMARY KEY, FK | Reference to circulations |
| attachment_id | INT | PRIMARY KEY, FK | Reference to attachments |
| is_main_document | BOOLEAN | DEFAULT FALSE | Main/primary document flag |
Indexes:
- PRIMARY KEY (circulation_id, attachment_id)
- FOREIGN KEY (circulation_id) REFERENCES circulations(id) ON DELETE CASCADE
- FOREIGN KEY (attachment_id) REFERENCES attachments(id) ON DELETE CASCADE
- INDEX (attachment_id)
- INDEX (is_main_document)
Relationships:
- Parent: circulations, attachments
8.4 shop_drawing_revision_attachments
Purpose: Junction table linking shop drawing revisions to file attachments (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| shop_drawing_revision_id | INT | PRIMARY KEY, FK | Reference to shop drawing revision |
| attachment_id | INT | PRIMARY KEY, FK | Reference to attachments |
| file_type | ENUM | NULL | File type: PDF, DWG, SOURCE, OTHER |
| is_main_document | BOOLEAN | DEFAULT FALSE | Main/primary document flag |
Indexes:
- PRIMARY KEY (shop_drawing_revision_id, attachment_id)
- FOREIGN KEY (shop_drawing_revision_id) REFERENCES shop_drawing_revisions(id) ON DELETE CASCADE
- FOREIGN KEY (attachment_id) REFERENCES attachments(id) ON DELETE CASCADE
- INDEX (attachment_id)
- INDEX (file_type)
- INDEX (is_main_document)
Relationships:
- Parent: shop_drawing_revisions, attachments
Business Rules:
- file_type categorizes drawing file formats
- Typically includes PDF for viewing and DWG for editing
- SOURCE may include native CAD files
8.5 contract_drawing_attachments
Purpose: Junction table linking contract drawings to file attachments (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| contract_drawing_id | INT | PRIMARY KEY, FK | Reference to contract drawing |
| attachment_id | INT | PRIMARY KEY, FK | Reference to attachments |
| file_type | ENUM | NULL | File type: PDF, DWG, SOURCE, OTHER |
| is_main_document | BOOLEAN | DEFAULT FALSE | Main/primary document flag |
Indexes:
- PRIMARY KEY (contract_drawing_id, attachment_id)
- FOREIGN KEY (contract_drawing_id) REFERENCES contract_drawings(id) ON DELETE CASCADE
- FOREIGN KEY (attachment_id) REFERENCES attachments(id) ON DELETE CASCADE
- INDEX (attachment_id)
- INDEX (file_type)
- INDEX (is_main_document)
Relationships:
- Parent: contract_drawings, attachments
9. 🔢 Document Numbering Tables (การสร้างเลขที่เอกสาร)
9.1 document_number_formats
Purpose: Master table defining document numbering templates per project and type
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique format ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| correspondence_type_id | INT | NOT NULL, FK | Reference to correspondence types |
| format_template | VARCHAR(255) | NOT NULL | Template string (e.g., '{ORG_CODE}-{TYPE_CODE}-{SEQ:4}') |
| description | TEXT | NULL | Format description |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- FOREIGN KEY (correspondence_type_id) REFERENCES correspondence_types(id) ON DELETE CASCADE
- UNIQUE KEY (project_id, correspondence_type_id)
- INDEX (project_id)
- INDEX (correspondence_type_id)
Relationships:
- Parent: projects, correspondence_types
Business Rules:
- One format template per project per correspondence type combination
- Template placeholders: {ORG_CODE}, {TYPE_CODE}, {YEAR}, {SEQ:n} where n is zero-padding length
- Used by document numbering module to generate unique document numbers
9.2 document_number_counters
Purpose: Transaction table maintaining running sequence numbers for document numbering
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| project_id | INT | PRIMARY KEY, FK | Reference to projects |
| originator_organization_id | INT | PRIMARY KEY, FK | Originating organization |
| correspondence_type_id | INT | PRIMARY KEY, FK | Reference to correspondence types |
| current_year | INT | PRIMARY KEY | Year (Buddhist calendar) |
| version | INT | DEFAULT 0 | ใช้สำหรับ Optimistic Locking (ตรวจสอบค่าก่อน Update) |
| last_number | INT | DEFAULT 0 | Last assigned sequence number |
Indexes:
- PRIMARY KEY (project_id, originator_organization_id, correspondence_type_id, current_year)
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- FOREIGN KEY (originator_organization_id) REFERENCES organizations(id) ON DELETE CASCADE
- FOREIGN KEY (correspondence_type_id) REFERENCES correspondence_types(id) ON DELETE CASCADE
- INDEX (project_id)
- INDEX (originator_organization_id)
- INDEX (correspondence_type_id)
- INDEX (current_year)
Relationships:
- Parent: projects, organizations, correspondence_types
Business Rules:
- Composite primary key ensures unique counters per project/organization/type/year
- Counter resets each year
- Thread-safe increments handled by DocumentNumberingService in NestJS using Redis Lock and Optimistic Locking on version column
- last_number tracks highest assigned number
- Used with document_number_formats to generate complete document numbers
10. ⚙️ System & Logs Tables (ระบบและ Log)
10.1 audit_logs
Purpose: Comprehensive audit trail for all significant system actions
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| audit_id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | Unique audit log ID |
| user_id | INT | NULL, FK | User who performed action |
| action | VARCHAR(100) | NOT NULL | Action code (e.g., 'rfa.create', 'login.success') |
| entity_type | VARCHAR(50) | NULL | Entity/module affected (e.g., 'rfa', 'correspondence') |
| entity_id | VARCHAR(50) | NULL | Primary ID of affected record |
| details_json | JSON | NULL | Additional context/details in JSON format |
| ip_address | VARCHAR(45) | NULL | Client IP address (supports IPv6) |
| user_agent | VARCHAR(255) | NULL | Browser user agent string |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Action timestamp |
| 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 |
| request_id | VARCHAR(100) | NULL | Request ID/Trace ID เพื่อเชื่อมโยงกับ App Logs |
| severity | ENUM('INFO', 'WARN', 'ERROR', 'CRITICAL') | NULL | ระดับความรุนแรงของเหตุการณ์ |
Indexes:
- PRIMARY KEY (audit_id)
- FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE SET NULL
- INDEX (user_id)
- INDEX (action)
- INDEX (entity_type, entity_id)
- INDEX (created_at)
- INDEX (ip_address)
- INDEX (v_ref_project_id)
- INDEX (v_ref_type)
Relationships:
- Parent: users
Business Rules:
- Immutable records (no updates/deletes)
- Captures all CRUD operations on sensitive data
- Includes authentication events (login, logout, failed attempts)
- JSON details field for flexible data storage
- Retention policy: typically 7 years for compliance
- Used for security audits, compliance reporting, and troubleshooting
Common Actions:
- Authentication: login.success, login.failed, logout
- Documents: correspondence.create, correspondence.update, rfa.submit
- Users: user.create, user.deactivate, role.assign
- Workflow: rfa.approve, rfa.reject, circulation.complete
10.2 notifications
Purpose: User notification queue for email, LINE, and in-system alerts
| 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/subject |
| message | TEXT | NOT NULL | Notification message body |
| notification_type | ENUM | NOT NULL | Type: EMAIL, LINE, SYSTEM |
| is_read | BOOLEAN | DEFAULT FALSE | Read status flag |
| entity_type | VARCHAR(50) | NULL | Related entity type (e.g., 'rfa', 'circulation') |
| entity_id | INT | NULL | Related entity ID |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Notification creation timestamp |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
- INDEX (user_id)
- INDEX (notification_type)
- INDEX (is_read)
- INDEX (entity_type, entity_id)
- INDEX (created_at)
- COMPOSITE INDEX (user_id, is_read, created_at) - For user notification listing
Relationships:
- Parent: users
Business Rules:
- EMAIL: Sent via SMTP to user's email address
- LINE: Sent via LINE Notify API to user's LINE ID
- SYSTEM: In-app notifications displayed in user interface
- Same notification can trigger multiple types (EMAIL + SYSTEM)
- entity_type/entity_id allow deep-linking to related records
- is_read flag only applicable for SYSTEM notifications
- Auto-cleanup: delete read notifications older than 30 days
Common Notification Triggers:
- Task assignment (circulation routing, RFA workflow)
- Document status changes (submitted, approved, rejected)
- Approaching deadlines
- System announcements
- Mention in comments
10.3 search_indices
Purpose: Full-text search index for document content
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique index ID |
| entity_type | VARCHAR(50) | NOT NULL | Entity type (e.g., 'correspondence', 'rfa') |
| entity_id | INT | NOT NULL | Entity primary ID |
| content | TEXT | NOT NULL | Searchable text content |
| indexed_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Last indexing timestamp |
Indexes:
- PRIMARY KEY (id)
- INDEX (entity_type, entity_id)
- INDEX (indexed_at)
Business Rules:
- Automatically populated/updated when documents change
- Content includes: title, description, document number, metadata
- May include OCR text from PDF attachments (future enhancement)
- Used by advanced search functionality
- Periodic re-indexing to catch missed updates
- Supports Boolean operators, phrase searching
Search Features:
- Natural language queries
- Wildcard support (*, ?)
- Boolean operators (AND, OR, NOT)
- Phrase matching with quotes
- Result ranking by relevance
10.4 backup_logs
Purpose: Log table tracking database and file backup operations
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique backup log ID |
| backup_type | ENUM | NOT NULL | Type: DATABASE, FILES, FULL |
| backup_path | VARCHAR(500) | NOT NULL | Path to backup file/directory |
| file_size | BIGINT | NULL | Backup file size in bytes |
| status | ENUM | NOT NULL | Status: STARTED, COMPLETED, FAILED |
| started_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Backup start timestamp |
| completed_at | TIMESTAMP | NULL | Backup completion timestamp |
| error_message | TEXT | NULL | Error details if failed |
Indexes:
- PRIMARY KEY (id)
- INDEX (backup_type)
- INDEX (status)
- INDEX (started_at)
- INDEX (completed_at)
Business Rules:
- DATABASE: MariaDB dump of database schema and data
- FILES: Backup of attachment files from QNAP storage
- FULL: Complete system backup (database + files)
- Triggered by n8n cron jobs
- Backup retention policy defined in backup strategy
- Failed backups trigger alert notifications
- completed_at - started_at = backup duration
Monitoring:
- Alert if no successful backup in 24 hours
- Track backup size trends over time
- Verify backup integrity with test restores
10.5 json_schemas
Purpose: องรับ Centralized JSON Schema Registry เพื่อ Validate ข้อมูล JSON Details ของเอกสารแต่ละประเภท ตาม Requirements 6.11.1 และ Backend Plan T2.5.1
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT |
PK, AI | Unique Identifier |
| schema_code | VARCHAR(100) |
UNIQUE, NOT NULL | รหัส Schema (เช่น RFA_DWG_V1, CORR_RFI_V1) |
| version | INT |
NOT NULL | เวอร์ชันของ Schema |
| schema_definition | JSON |
NOT NULL | โครงสร้าง JSON Schema (Standard JSON Schema format) |
| is_active | BOOLEAN |
DEFAULT TRUE | สถานะการใช้งาน |
| created_at | TIMESTAMP |
วันที่สร้าง |
10.6 user_preferences
Purpose: แยกข้อมูลการตั้งค่าส่วนตัว (เช่น Notification Settings) ออกจากตาราง Users เพื่อความยืดหยุ่น ตาม Requirements 5.5 และ 6.8.3
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| user_id | INT |
PK, FK | อ้างอิงตาราง users |
| notify_email | BOOLEAN |
DEFAULT TRUE | รับแจ้งเตือนทางอีเมล |
| notify_line | BOOLEAN |
DEFAULT TRUE | รับแจ้งเตือนทาง LINE |
| digest_mode | BOOLEAN |
DEFAULT TRUE | รับแจ้งเตือนแบบรวม (Digest) แทน Real-time |
| ui_theme | VARCHAR(20) |
DEFAULT 'light' | ธีมหน้าจอ (Light/Dark) |
| updated_at | TIMESTAMP |
วันที่แก้ไขล่าสุด |
11. 📊 Views & Procedures (วิว และ โปรซีเดอร์)
11.1 v_current_correspondences
Purpose: View showing current revision of all non-RFA correspondences
Columns:
- correspondence_id, correspondence_number, correspondence_type_id/code/name
- project_id, project_code, project_iname
- organization_id, organization_code, organization_name
- revision_id, revision_number, revision_label
- title, document_date, issued_date, received_date, due_date
- correspondence_status_id, correspondence_status_code, correspondence_status_name
- created_by, created_by_username, revision_created_at
Filters:
- is_current = TRUE (only latest revision)
- correspondence_type NOT IN ('RFA') (excludes RFAs)
- deleted_at IS NULL (excludes soft-deleted records)
Business Rules:
- Provides flattened view of current correspondence state
- Joins correspondence_revisions with is_current flag
- Used by dashboard, document listing screens
- Excludes RFAs (they have separate view)
11.2 v_current_rfas
Purpose: View showing current revision of all RFA documents
Columns:
- rfa_id, rfa_type_id, rfa_type_code, rfa_type_name
- correspondence_id, correspondence_number
- project_id, project_code, project_iname
- organization_id, organization_name
- revision_id, revision_number, revision_label
- title, document_date, issued_date, received_date, approved_date
- rfa_status_code_id, rfa_status_code, rfa_status_name
- rfa_approve_code_id, rfa_approve_code, rfa_approve_code_name
- created_by, created_by_username, revision_created_at
Filters:
- is_current = TRUE
- deleted_at IS NULL (both rfas and correspondences)
Business Rules:
- Specialized view for RFA documents
- Includes RFA-specific fields (approval codes, approved date)
- Joins across rfas → rfa_revisions → correspondences
- Used by RFA management screens
11.3 v_contract_parties_all
Purpose: View showing all organization relationships across contracts and projects
Columns:
- contract_id, contract_code, contract_name
- project_id, project_code, project_iname
- organization_id, organization_code, organization_name
- role_in_contract
Business Rules:
- Joins contracts → projects → contract_organizations → organizations
- Shows only active contracts (is_active = TRUE)
- Used for permission checks and document routing
- Supports multi-organization projects/contracts
11.4 v_user_tasks
Purpose: View showing pending tasks assigned to users (action items)
Columns:
- routing_id, circulation_id, circulation_no, circulation_subject
- correspondence_id, correspondence_number
- project_id, project_code, project_name
- user_id, username, first_name, last_name
- organization_id, organization_name
- step_number, task_status, comments
- completed_at, assigned_at, circulation_created_at
Filters:
- status IN ('PENDING', 'IN_PROGRESS')
- assigned_to IS NOT NULL
Business Rules:
- Shows circulation routings requiring user action
- Used for "My Tasks" / "Inbox" functionality
- Excludes completed/cancelled tasks
- Ordered by creation date (oldest first)
11.5 v_audit_log_details
Purpose: View enriching audit logs with user information
Columns:
- audit_id, user_id, username, email, first_name, last_name
- action, entity_type, entity_id
- details_json, ip_address, user_agent
- created_at
Business Rules:
- Joins audit_logs with users table
- Used for audit trail reports
- Includes user details even if user later deleted (LEFT JOIN)
11.6 v_user_all_permissions
Purpose: View showing all effective permissions for users across all scopes
Columns:
- user_id, role_id, role_name
- permission_id, permission_name
- module, scope_level
- organization_id, project_id, contract_id
- permission_scope (GLOBAL, ORGANIZATION, PROJECT, CONTRACT)
Business Rules:
- UNION of permissions from Global, Organization, Project, and Contract scopes
- Used for authorization checks
- Considers role-permission mappings at all levels
- Only shows active permissions (is_active = 1)
- One row per user-permission-scope combination
Usage Example:
SELECT permission_name
FROM v_user_all_permissions
WHERE user_id = ?
AND project_id = ?
AND permission_name = 'document.edit';
11.7 v_documents_with_attachments
Purpose: View showing all documents and their attachment counts
Columns:
- document_type (CORRESPONDENCE, CIRCULATION, SHOP_DRAWING, CONTRACT_DRAWING)
- document_id, document_number
- project_id, project_code, project_name
- attachment_count, latest_attachment_date
Business Rules:
- UNION of all document types with attachments
- Used for document listing with file indicators
- Helps identify documents missing attachments
- Aggregates count per document
11.8 v_document_statistics
Purpose: View providing aggregated document statistics by project, type, and status
Columns:
- project_id, project_code, project_name
- correspondence_type_id, correspondence_type_code, correspondence_type_name
- status_id, status_code, status_name
- document_count, revision_count
Business Rules:
- CROSS JOIN creates all possible combinations
- LEFT JOIN shows zeros for combinations with no documents
- Only includes active projects, types, and statuses
- Used for dashboard charts and reports
- Groups by project → type → status
Database Indexes Summary
Performance Optimization Indexes
Primary Indexes (automatic with PRIMARY KEY):
- All tables have PRIMARY KEY with AUTO_INCREMENT
Foreign Key Indexes (automatic with FOREIGN KEY):
- All FK relationships automatically indexed
Additional Performance Indexes:
-
Correspondence Tables:
idx_correspondences_type_projecton (correspondence_type_id, project_id)idx_corr_revisions_current_statuson (is_current, correspondence_status_id)idx_corr_revisions_correspondence_currenton (correspondence_id, is_current)idx_correspondences_project_typeon (project_id, correspondence_type_id)
-
RFA Tables:
idx_rfa_revisions_current_statuson (is_current, rfa_status_code_id)idx_rfa_revisions_rfa_currenton (rfa_id, is_current)
-
Circulation Tables:
idx_circulation_routings_status_assignedon (status, assigned_to)idx_circulation_routings_circulation_statuson (circulation_id, status)
-
Document Numbering:
idx_doc_counter_compositeon (project_id, originator_organization_id, correspondence_type_id, current_year)
-
Audit & Notifications:
idx_audit_logs_reportingon (created_at, entity_type, action)idx_notifications_user_unreadon (user_id, is_read, created_at)
Data Integrity Constraints
Foreign Key Constraints
Cascade Delete:
- Parent-child relationships where child should be deleted with parent
- Examples: correspondence_revisions, shop_drawing_revisions, project/contract relationships
Restrict Delete:
- Prevents deletion if references exist
- Examples: correspondence_types, rfa_status_codes, organizations (when referenced)
Set NULL:
- Preserves record but removes reference
- Examples: originator_id, created_by, updated_by
Unique Constraints
-
Globally Unique:
- usernames, emails
- shop_drawing.drawing_number
-
Unique Within Scope:
- (project_id, correspondence_number)
- (project_id, condwg_no)
- (correspondence_id, revision_number)
- (rfa_id, revision_number)
-
Composite Unique:
- (correspondence_id, is_current) - ensures only one current revision
- (project_id, correspondence_type_id) - in document_number_formats
Check Constraints
- user_assignments.chk_scope:
- Ensures only one scope field (organization_id, project_id, contract_id) is NOT NULL
- OR all are NULL for Global scope
Business Rule Constraints
-
Soft Delete Pattern:
- deleted_at timestamp instead of hard delete
- Preserves audit trail and relationships
- Applied to: correspondences, rfas, shop_drawings, contract_drawings
-
Current Revision Pattern:
- is_current flag with UNIQUE constraint
- Ensures only one current revision per document
-
Sequential Numbering:
- revision_number starts at 0, increments by 1
- Enforced by application logic + stored procedure
Security & Permissions Model
Access Control Hierarchy
Global Scope (Superadmin)
└── Organization Scope (Org Admin, Document Control)
└── Project Scope (Project Manager)
└── Contract Scope (Contract Admin)
Permission Inheritance
- Users can have multiple role assignments at different scopes
- More specific scopes inherit access from broader scopes
- Permission checks evaluate all applicable scopes
- View v_user_all_permissions aggregates effective permissions
Role-Based Access Control (RBAC)
7 Predefined Roles:
- Superadmin (Global) - Full system access
- Org Admin (Organization) - Organization management
- Document Control (Organization) - Document lifecycle + admin powers
- Editor (Organization) - Document CRUD
- Viewer (Organization) - Read-only
- Project Manager (Project) - Project + document management
- Contract Admin (Contract) - Contract-specific management
Permission Categories (49 total)
- System Management (1): Full system control
- Organization Management (4): CRUD on organizations
- Project Management (8): CRUD + member/contract management
- Role & Permission Management (4): RBAC administration
- Master Data Management (4): Document types, categories, tags
- User Management (5): User CRUD + organization assignment
- Contract Management (2): Contract administration
- Document Management (16): Full document lifecycle
- Workflow Management (3): Approval workflow control
- Search & Reporting (2): Advanced search, report generation
Data Migration & Seeding
Pre-populated Master Data
- organization_roles: Not used in current implementation
- organizations: 15 organizations (Owner, Consultants, Contractors, Third parties)
- projects: 5 projects (LCBP3 + 4 sub-contracts)
- contracts: 7 contracts
- users: 3 initial users (superadmin, editor01, viewer01)
- roles: 7 predefined roles
- permissions: 49 system permissions
- role_permissions: Complete permission mappings
- project_organizations: Project-organization relationships
- contract_organizations: Contract-organization-role relationships
- correspondence_types: 10 types
- correspondence_status: 23 status codes
- rfa_types: 11 types
- rfa_status_codes: 7 statuses
- rfa_approve_codes: 8 approval codes
- circulation_status_codes: 4 statuses
Initial Passwords
All seed users have password: password123
- Hashed as:
$2y$10$0kjBMxWq7E4G7P.dc8r5i.cjiPBiup553AsFpDfxUt31gKg9h/udq - Must be changed on first login in production
Backup & Recovery Strategy
Database Backup
Strategy:
- Daily full database backups
- Hourly incremental backups (transaction logs)
- Retention: 30 days online, 7 years archived
Backup Method:
- MariaDB mysqldump for logical backups
- MariaDB Backup (Mariabackup) for physical backups
- Automated via n8n cron workflows
File Backup
Strategy:
- Daily backup of /share/dms-data/ directory
- QNAP snapshot every 4 hours
- Offsite replication to secondary NAS
File Organization:
/share/dms-data/
├── attachments/
│ ├── 2025/
│ │ ├── 01/
│ │ │ └── {uuid}-{filename}
│ │ └── 02/
│ └── 2024/
└── temp/
Recovery Procedures
- Point-in-Time Recovery: Using transaction logs
- Full Restore: From latest full backup
- Selective Restore: Individual tables or records
- File Recovery: From QNAP snapshots or backup
Performance Optimization
Query Optimization
- Use Indexed Columns: WHERE, JOIN, ORDER BY clauses
- Avoid SELECT: Specify needed columns
- Use Views: For complex, frequently-used queries
- Limit Result Sets: Use LIMIT and pagination
- Analyze Slow Queries: Enable slow query log
Index Maintenance
-- Check index usage
SELECT * FROM information_schema.STATISTICS
WHERE TABLE_SCHEMA = 'lcbp3';
-- Optimize tables
OPTIMIZE TABLE correspondences;
-- Analyze tables
ANALYZE TABLE correspondences;
Connection Pooling
- Backend uses connection pool (NestJS TypeORM)
- Min pool size: 5
- Max pool size: 20
- Idle timeout: 10 minutes
Data Validation Rules
Required Fields Validation
At Application Level:
- Email format validation
- Date range validation (start_date < end_date)
- File size limits (5MB per attachment)
- File type restrictions (PDF, DWG, DOC, XLS, images)
At Database Level:
- NOT NULL constraints
- UNIQUE constraints
- Foreign key constraints
- Check constraints (user_assignments scope)
Business Logic Validation
-
Document Workflow:
- Cannot edit submitted documents (unless Document Control)
- Cannot skip workflow steps (unless forced)
- Must provide approval comments
-
User Management:
- Cannot delete users with active assignments
- Cannot deactivate own account
- Must have valid organization for non-Global roles
-
File Management:
- Original filename preserved for audit
- Unique stored filename prevents conflicts
- File path must exist and be accessible
Change Log & Versioning
Database Version: v1.4.0
Changes from v1.3.0:
- Added comprehensive RBAC system (roles, permissions, user_assignments)
- Refactored organization-project-contract relationships
- Added junction tables for M:N relationships
- Implemented soft delete pattern
- Added full-text search support
- Enhanced audit logging with JSON details
- Added circulation workflow templates
- Improved document numbering with stored procedure
- Added comprehensive views for common queries
- Optimized indexes for performance
Migration Path:
- v1.3.0 → v1.4.0: Run migration script (not provided in this excerpt)
- Backup database before migration
- Test migration on staging environment first
Technical Specifications
Database Configuration
MariaDB Server:
- Version: 10.11
- Character Set: utf8mb4
- Collation: utf8mb4_general_ci
- Time Zone: +07:00 (Bangkok/Asia)
- SQL Mode: STRICT_TRANS_TABLES, NO_ENGINE_SUBSTITUTION
Connection Settings:
- Host: Container on QNAP TS-473A
- Port: 3306 (default)
- Max Connections: 100
- Max Packet Size: 64MB
Table Engine
InnoDB Features Used:
- ACID compliance
- Foreign key constraints
- Row-level locking
- Crash recovery
- Transaction support
Storage Requirements
Estimated Initial Size:
- Database: ~50 MB (with seed data)
- Indexes: ~20 MB
- Total: ~70 MB
Growth Estimates:
- 1,000 documents/month: +100 MB/month (database)
- 10 attachments/document @ 2MB avg: +20 GB/month (files)
- Plan for 1TB+ storage within first year
Application Integration
Backend (NestJS)
TypeORM Entities:
- One entity class per table
- Decorators for columns, relationships
- DTOs for data transfer
- Repositories for data access
Key Modules:
- AuthModule: Authentication, authorization
- DocumentsModule: Correspondence, RFA management
- DrawingsModule: Shop drawing, contract drawing
- WorkflowModule: Circulation, approval workflows
- FilesModule: Attachment management
- UsersModule: User, role, permission management
Frontend (Next.js)
Key Features:
- Document listing/search
- Document creation wizards
- Workflow approval interface
- File upload/download
- User management console
- Dashboard analytics
Integration Points
-
Document Numbering:
- Call DocumentNumberingService.generateNextNumber() (NestJS) which handles Redis locking and retry logic
- Format with template from document_number_formats
- Store in correspondences.correspondence_number
-
File Upload:
- Upload to QNAP /share/dms-data/
- Create attachment record
- Link via junction table
-
Workflow Execution:
- Check rfa_workflow_templates
- Create rfa_workflows records
- Update status as steps complete
- Send notifications
-
Permission Checks:
- Query v_user_all_permissions
- Cache results per session
- Re-check on sensitive operations
Monitoring & Maintenance
Health Checks
-- Database size
SELECT
table_schema,
SUM(data_length + index_length) / 1024 / 1024 AS size_mb
FROM information_schema.TABLES
WHERE table_schema = 'dms_db'
GROUP BY table_schema;
-- Table sizes
SELECT
table_name,
(data_length + index_length) / 1024 / 1024 AS size_mb,
table_rows
FROM information_schema.TABLES
WHERE table_schema = 'dms_db'
ORDER BY (data_length + index_length) DESC;
-- Active connections
SHOW PROCESSLIST;
-- Lock wait statistics
SELECT * FROM information_schema.INNODB_LOCK_WAITS;
Scheduled Maintenance
Daily:
- Full database backup
- Check backup log for failures
- Monitor disk space
Weekly:
- OPTIMIZE tables
- ANALYZE tables
- Review slow query log
- Check for deadlocks
Monthly:
- Review audit logs
- Clean up old notifications (30+ days)
- Archive old audit logs (7+ years)
- Verify backup integrity (test restore)
Quarterly:
- Review and optimize indexes
- Update database statistics
- Capacity planning review
Glossary
Terms:
- Correspondence: Any formal document exchanged between parties
- RFA: Request for Approval - formal submittal for review/approval
- Circulation: Internal document routing workflow
- Transmittal: Cover sheet for forwarding multiple documents
- Shop Drawing: Detailed construction drawing from contractor
- Contract Drawing: Baseline drawing from contract specifications
- Revision: Version of a document
- Originator: Organization that creates/sends a document
- Recipient: Organization that receives a document (TO or CC)
- Scope: Level of permission application (Global, Organization, Project, Contract)
Acronyms:
- DMS: Document Management System
- LCBP3: Laem Chabang Port Phase 3
- RBAC: Role-Based Access Control
- RFA: Request for Approval
- RFI: Request for Information
- CSC: Construction Supervision Consultant
- TO: Primary recipient (action required)
- CC: Carbon copy (for information)
- QNAP: Network Attached Storage device manufacturer
Document Control:
- Document: Data Dictionary v1.4.2
- Version: 1.4
- Date: 2025-11-19
- Author: NAP LCBP3-DMS & Gemini
- Status: FINAL
- Classification: Internal Technical Documentation
- Approved By: Nattanin
End of Data Dictionary v1.4.2 (ฉบับปรับปรุง)