114 KiB
title, version, status, owner, last_updated, related
| title | version | status | owner | last_updated | related | ||
|---|---|---|---|---|---|---|---|
| Data & Storage: Data Dictionary and Data Model Architecture | 1.8.0 | released | Nattanin Peancharoen | 2026-02-28 |
|
1. Data Model Architecture Overview
ð 1.1 Overview
āđāļāļāļŠāļēāļĢāļāļĩāđāļāļāļīāļāļēāļĒāļŠāļāļēāļāļąāļāļĒāļāļĢāļĢāļĄāļāļāļ Data Model āļŠāļģāļŦāļĢāļąāļāļĢāļ°āļāļ LCBP3-DMS āđāļāļĒāļāļĢāļāļāļāļĨāļļāļĄāđāļāļĢāļāļŠāļĢāđāļēāļāļāļēāļāļāđāļāļĄāļđāļĨ, āļāļ§āļēāļĄāļŠāļąāļĄāļāļąāļāļāđāļĢāļ°āļŦāļ§āđāļēāļāļāļēāļĢāļēāļ, āđāļĨāļ°āļŦāļĨāļąāļāļāļēāļĢāļāļāļāđāļāļāļāļĩāđāļŠāļģāļāļąāļ
ðŊ 1.2 Design Principles
1. Separation of Concerns
- Master-Revision Pattern: āđāļĒāļāļāđāļāļĄāļđāļĨāļāļĩāđāđāļĄāđāđāļāļĨāļĩāđāļĒāļāđāļāļĨāļ (Master) āļāļēāļāļāđāļāļĄāļđāļĨāļāļĩāđāļĄāļĩāļāļēāļĢāđāļāđāđāļ (Revisions)
correspondences(Master) âcorrespondence_revisions(Revisions)rfas(Master) ârfa_revisions(Revisions)shop_drawings(Master) âshop_drawing_revisions(Revisions)
2. Data Integrity
- Foreign Key Constraints: āđāļāđ FK āļāļļāļāļāļ§āļēāļĄāļŠāļąāļĄāļāļąāļāļāđāđāļāļ·āđāļāļĢāļąāļāļĐāļēāļāļ§āļēāļĄāļŠāļĄāļāļđāļĢāļāđāļāļāļāļāđāļāļĄāļđāļĨ
- Soft Delete: āđāļāđ
deleted_atāđāļāļāļāļēāļĢāļĨāļāļāđāļāļĄāļđāļĨāļāļĢāļīāļ āđāļāļ·āđāļāļĢāļąāļāļĐāļēāļāļĢāļ°āļ§āļąāļāļī - Optimistic Locking: āđāļāđ
versioncolumn āđāļdocument_number_countersāļāđāļāļāļāļąāļ Race Condition
3. Flexibility & Extensibility
- JSON Details Field: āđāļāđāļāļāđāļāļĄāļđāļĨāđāļāļāļēāļ°āļāļĢāļ°āđāļ āļāđāļ
correspondence_revisions.details - Virtual Columns: āļŠāļĢāđāļēāļ Index āļāļēāļ JSON fields āļŠāļģāļŦāļĢāļąāļ Performance
- Master Data Tables: āđāļĒāļāļāđāļāļĄāļđāļĨ Master (Types, Status, Codes) āđāļāļ·āđāļāļāļ§āļēāļĄāļĒāļ·āļāļŦāļĒāļļāđāļ
4. Security & Audit
- RBAC (Role-Based Access Control): āļĢāļ°āļāļāļŠāļīāļāļāļīāđāđāļāļ Hierarchical Scope
- Audit Trail: āļāļąāļāļāļķāļāļāļđāđāļŠāļĢāđāļēāļ/āđāļāđāđāļ āđāļĨāļ°āđāļ§āļĨāļēāđāļāļāļļāļāļāļēāļĢāļēāļ
- Two-Phase File Upload: āļāđāļāļāļāļąāļāđāļāļĨāđāļāļĒāļ°āļāđāļ§āļĒ Temporary Storage
2. Database Schema Overview (ERD)
Entity Relationship Diagram
erDiagram
%% Core Entities
organizations ||--o{ users : "employs"
projects ||--o{ contracts : "contains"
projects ||--o{ correspondences : "manages"
%% RBAC
users ||--o{ user_assignments : "has"
roles ||--o{ user_assignments : "assigned_to"
roles ||--o{ role_permissions : "has"
permissions ||--o{ role_permissions : "granted_by"
%% Correspondences
correspondences ||--o{ correspondence_revisions : "has_revisions"
correspondence_types ||--o{ correspondences : "categorizes"
correspondence_status ||--o{ correspondence_revisions : "defines_state"
disciplines ||--o{ correspondences : "classifies"
%% RFAs
rfas ||--o{ rfa_revisions : "has_revisions"
rfa_types ||--o{ rfas : "categorizes"
rfa_status_codes ||--o{ rfa_revisions : "defines_state"
rfa_approve_codes ||--o{ rfa_revisions : "defines_result"
disciplines ||--o{ rfas : "classifies"
%% Drawings
shop_drawings ||--o{ shop_drawing_revisions : "has_revisions"
shop_drawing_main_categories ||--o{ shop_drawings : "categorizes"
shop_drawing_sub_categories ||--o{ shop_drawings : "sub_categorizes"
%% Attachments
attachments ||--o{ correspondence_attachments : "attached_to"
correspondences ||--o{ correspondence_attachments : "has"
3. Data Dictionary V1.8.0
āļŦāļĄāļēāļĒāđāļŦāļāļļ: PK = Primary Key, FK = Foreign Key, AI = AUTO_INCREMENT. āļĢāļđāļāđāļāļ Soft Delete āļāļ°āļāļĢāļēāļāļ Column
deleted_at DATETIME NULLāđāļāđāļāļĄāļēāļāļĢāļāļēāļ
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 ( CONTRACTOR, THIRD PARTY ) | | 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 (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 | | deleted_at | DATETIME | NULL | Soft delete timestamp | ** INDEXES **: - PRIMARY KEY (id) - UNIQUE (organization_code) - INDEX (is_active) ** Relationships **: - Referenced by: users, project_organizations, contract_organizations, correspondences, circulations ---
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 | | 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 (id) - UNIQUE (project_code) - INDEX (is_active) ** Relationships **: - Referenced by: contracts, correspondences, document_number_formats, drawings ---
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 | | deleted_at | DATETIME | NULL | Soft delete 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 ---
1.5 disciplines (NEW v1.5.1)
-
- Purpose **: āđāļāđāļāļāđāļāļĄāļđāļĨāļŠāļēāļāļēāļāļēāļ (Disciplines) āđāļĒāļāļāļēāļĄāļŠāļąāļāļāļē (Req 6B) | COLUMN Name | Data TYPE | Constraints | Description | |: -------------- | :----------- | :----------- | :--------------------- | | id | INT | PK, AI | UNIQUE identifier | | contract_id | INT | FK, NOT NULL | āļāļđāļāļāļąāļāļŠāļąāļāļāļē | | discipline_code | VARCHAR(10) | NOT NULL | āļĢāļŦāļąāļŠāļŠāļēāļāļē (āđāļāđāļ GEN, STR) | | code_name_th | VARCHAR(255) | NULL | āļāļ·āđāļāđāļāļĒ | | code_name_en | VARCHAR(255) | NULL | āļāļ·āđāļāļāļąāļāļāļĪāļĐ | | is_active | TINYINT(1) | DEFAULT 1 | āļŠāļāļēāļāļ°āļāļēāļĢāđāļāđāļāļēāļ | ** INDEXES **: - UNIQUE (contract_id, discipline_code) ---
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 | | email | 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 ---
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) | | 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, user_assignments ---
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 | | 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 (permission_id) - UNIQUE (permission_name) - INDEX (module) - INDEX (scope_level) - INDEX (is_active) ** Relationships **: - Referenced by: role_permissions ---
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 ---
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) ** Relationships **: - Parent: users, roles, organizations, projects, contracts ---
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 ---
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
2.8 user_preferences (NEW v1.5.1)
Purpose: āđāļāđāļāļāļēāļĢāļāļąāđāļāļāđāļēāļŠāđāļ§āļāļāļąāļ§āļāļāļāļāļđāđāđāļāđ (Req 5.5, 6.8.3)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| user_id | INT | PK, FK | User ID |
| notify_email | BOOLEAN | DEFAULT TRUE | āļĢāļąāļāļāļĩāđāļĄāļĨāđāļāđāļāđāļāļ·āļāļ |
| notify_line | BOOLEAN | DEFAULT TRUE | āļĢāļąāļāđāļĨāļāđāđāļāđāļāđāļāļ·āļāļ |
| digest_mode | BOOLEAN | DEFAULT FALSE | āļĢāļąāļāđāļāđāļāđāļāļ·āļāļāđāļāļāļĢāļ§āļĄ |
| ui_theme | VARCHAR(20) | DEFAULT ' light ' | UI Theme |
2.9 refresh_tokens (NEW v1.5.1)
Purpose: āđāļāđāļ Refresh Tokens āļŠāļģāļŦāļĢāļąāļāļāļēāļĢāļāļģ Authentication āđāļĨāļ° Token Rotation
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| token_id | INT | PK, AI | Unique Token ID |
| user_id | INT | FK, NOT NULL | āđāļāđāļēāļāļāļ Token |
| token_hash | VARCHAR(255) | NOT NULL | Hash āļāļāļ Refresh Token (Security) |
| expires_at | DATETIME | NOT NULL | āļ§āļąāļāļŦāļĄāļāļāļēāļĒāļļāļāļāļ Token |
| is_revoked | BOOLEAN | DEFAULT FALSE | āļŠāļāļēāļāļ°āļāļđāļāļĒāļāđāļĨāļīāļ (True = āđāļāđāļāļēāļāđāļĄāđāđāļāđ) |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | āđāļ§āļĨāļēāļāļĩāđāļŠāļĢāđāļēāļ |
| replaced_by_token | VARCHAR(255) | NULL | Token āđāļŦāļĄāđāļāļĩāđāļĄāļēāđāļāļāļāļĩāđ (āļāļĢāļāļĩ Token Rotation) |
Indexes:
- PRIMARY KEY (token_id)
- FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
- INDEX (user_id)
Relationships:
- Parent: users
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 |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Last update timestamp |
| deleted_at | DATETIME | NULL | Soft delete timestamp |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (type_code)
- INDEX (is_active)
- INDEX (sort_order)
Relationships:
- Referenced by: correspondences, document_number_formats, document_number_counters
3.2 correspondence_sub_types (NEW v1.5.1)
Purpose: āđāļāđāļāļāļĢāļ°āđāļ āļāļŦāļāļąāļāļŠāļ·āļāļĒāđāļāļĒ (Sub Types) āļŠāļģāļŦāļĢāļąāļ Mapping āđāļĨāļāļĢāļŦāļąāļŠ (Req 6B)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PK, AI | Unique identifier |
| contract_id | INT | FK, NOT NULL | āļāļđāļāļāļąāļāļŠāļąāļāļāļē |
| correspondence_type_id | INT | FK, NOT NULL | āļāļđāļāļāļąāļāļāļĢāļ°āđāļ āļāđāļāļāļŠāļēāļĢāļŦāļĨāļąāļ |
| sub_type_code | VARCHAR(20) | NOT NULL | āļĢāļŦāļąāļŠāļĒāđāļāļĒ (āđāļāđāļ MAT, SHP) |
| sub_type_name | VARCHAR(255) | NULL | āļāļ·āđāļāļāļĢāļ°āđāļ āļāļŦāļāļąāļāļŠāļ·āļāļĒāđāļāļĒ |
| sub_type_number | VARCHAR(10) | NULL | āđāļĨāļāļĢāļŦāļąāļŠāļŠāļģāļŦāļĢāļąāļ Running Number |
3.3 correspondences (UPDATE v1.7.0)
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 |
| discipline_id | INT | NULL, FK | [NEW] āļŠāļēāļāļēāļāļēāļ (āļāđāļēāļĄāļĩ) |
| 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 (discipline_id) REFERENCES disciplines(id) ON DELETE SET NULL
- 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, disciplines, projects, organizations, users
- Children: correspondence_revisions, correspondence_recipients, correspondence_tags, correspondence_references, correspondence_attachments, circulations, transmittals
3.4 correspondence_revisions (UPDATE v1.7.0)
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_doc_subtype | VARCHAR(50) | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column āļāļķāļ Type āļāļēāļ JSON details | | schema_version | INT | DEFAULT 1 | Version of the schema used with this details |
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)
- INDEX (correspondence_status_id)
- INDEX (is_current)
- INDEX (document_date)
- INDEX (issued_date)
- INDEX (v_ref_project_id)
- INDEX (v_doc_subtype)
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
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)
4. ð approval: RFA Tables (āđāļāļāļŠāļēāļĢāļāļāļāļāļļāļĄāļąāļāļī, Workflows)
4.1 rfa_types (UPDATE v1.7.0)
Purpose: Master table for RFA (Request for Approval) types
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique identifier |
| contract_id | INT | NOT NULL, FK | Contract reference |
| type_code | VARCHAR(20) | NOT NULL | Type code (DWG, DOC, MAT, etc.) |
| type_name_th | VARCHAR(100) | NOT NULL | Full type name (TH) |
| type_name_en | VARCHAR(100) | NOT NULL | Full type name (EN) |
| remark | TEXT | NULL | Remark |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (contract_id, type_code)
- FOREIGN KEY (contract_id) REFERENCES contracts(id) ON DELETE CASCADE
- INDEX (is_active)
Relationships:
- Referenced by: rfas
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
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
4.4 rfas (UPDATE v1.7.0)
Purpose: Master table for RFA documents (non-revisioned data)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PK, FK | Master RFA ID (Shared with correspondences) |
| rfa_type_id | INT | NOT NULL, FK | Reference to rfa_types |
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| created_by | INT | NULL, FK | User who created the record |
| deleted_at | DATETIME | NULL | Soft delete timestamp |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (id) REFERENCES correspondences(id) ON DELETE CASCADE
- FOREIGN KEY (rfa_type_id) REFERENCES rfa_types(id)
- FOREIGN KEY (created_by) REFERENCES users(user_id) ON DELETE SET NULL
- INDEX (rfa_type_id)
- INDEX (deleted_at)
Relationships:
- Parent: correspondences, rfa_types, users
- Children: rfa_revisions
4.5 rfa_revisions (UPDATE v1.7.0)
Purpose: Child table storing revision history of RFAs (1:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
| 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 | | details | JSON | NULL | Type-specific details (e.g., RFI questions) | | v_ref_drawing_count | INT | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column āļāļķāļ Drawing Count āļāļēāļ JSON details āđāļāļ·āđāļāļāļģ Index | | schema_version | INT | DEFAULT 1 | Version of the schema used with this details |
Indexes:
- PRIMARY KEY (id)
- 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)
- INDEX (v_ref_drawing_count): āļāļąāļ§āļāļĒāđāļēāļāļāļēāļĢ Index āļāđāļāļĄāļđāļĨāļāļąāļ§āđāļĨāļāđāļ JSON
Relationships:
- Parent: correspondences, rfas, rfa_status_codes, rfa_approve_codes, users
- Children: rfa_items
4.6 rfa_items
Purpose: Junction table linking RFA revisions to shop drawing revisions (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| rfa_revision_id | INT | PRIMARY KEY, FK | RFA Revision ID |
| shop_drawing_revision_id | INT | PRIMARY KEY, FK | Shop drawing revision ID |
Indexes:
- PRIMARY KEY (rfa_revision_id, shop_drawing_revision_id)
- FOREIGN KEY (rfa_revision_id) REFERENCES rfa_revisions(id) ON DELETE CASCADE
- FOREIGN KEY (shop_drawing_revision_id) REFERENCES shop_drawing_revisions(id) ON DELETE CASCADE
- INDEX (shop_drawing_revision_id)
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
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 (UPDATE v1.7.0)
Purpose: Junction table mapping sub-categories to main categories (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique mapping ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| sub_cat_id | INT | NOT NULL, FK | Reference to sub-category |
| cat_id | INT | NOT NULL, FK | Reference to main category |
Indexes:
- PRIMARY KEY (id)
- UNIQUE KEY (project_id, sub_cat_id, cat_id)
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- FOREIGN KEY (sub_cat_id) REFERENCES contract_drawing_sub_cats(id) ON DELETE CASCADE
- FOREIGN KEY (cat_id) REFERENCES contract_drawing_cats(id) ON DELETE CASCADE
- INDEX (sub_cat_id)
- INDEX (cat_id)
Relationships:
- Parent: projects, contract_drawing_sub_cats, contract_drawing_cats
- Referenced by: contract_drawings
Business Rules:
- Allows flexible categorization
- One sub-category can belong to multiple main categories
- Composite uniqueness enforced via UNIQUE constraint
5.5 contract_drawings (UPDATE v1.7.0)
Purpose: Master table for contract drawings (from contract specifications)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique drawing ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| condwg_no | VARCHAR(255) | NOT NULL | Contract drawing number |
| title | VARCHAR(255) | NOT NULL | Drawing title |
| map_cat_id | INT | NULL, FK | [CHANGED] Reference to mapping table |
| volume_id | INT | NULL, FK | Reference to volume |
| volume_page | INT | NULL | [NEW] Page number within volume |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
| deleted_at | DATETIME | NULL | Soft delete timestamp |
| updated_by | INT | NULL, FK | User who last updated |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- FOREIGN KEY (map_cat_id) REFERENCES contract_drawing_subcat_cat_maps(id) ON DELETE RESTRICT
- FOREIGN KEY (volume_id) REFERENCES contract_drawing_volumes(id) ON DELETE RESTRICT
- FOREIGN KEY (updated_by) REFERENCES users(user_id)
- UNIQUE KEY (project_id, condwg_no)
- INDEX (map_cat_id)
- INDEX (volume_id)
- INDEX (deleted_at)
Relationships:
- Parent: projects, contract_drawing_subcat_cat_maps, 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
- map_cat_id references the mapping table for flexible categorization
5.6 shop_drawing_main_categories (UPDATE v1.7.0)
Purpose: Master table for shop drawing main categories (discipline-level)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique category ID |
| project_id | INT | NOT NULL, FK | [NEW] Reference to projects |
| main_category_code | VARCHAR(50) | NOT NULL, UNIQUE | Category code (ARCH, STR, MEP, etc.) |
| main_category_name | VARCHAR(255) | NOT NULL | Category name |
| description | TEXT | NULL | Category description |
| 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)
- FOREIGN KEY (project_id) REFERENCES projects(id)
- UNIQUE (main_category_code)
- INDEX (is_active)
- INDEX (sort_order)
Relationships:
- Parent: projects
- Referenced by: shop_drawings, asbuilt_drawings
Business Rules:
- [CHANGED] Project-specific categories (was global)
- Typically represents engineering disciplines
5.7 shop_drawing_sub_categories (UPDATE v1.7.0)
Purpose: Master table for shop drawing sub-categories (component-level)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique sub-category ID |
| project_id | INT | NOT NULL, FK | [NEW] Reference to projects |
| sub_category_code | VARCHAR(50) | NOT NULL, UNIQUE | Sub-category code (STR-COLUMN, ARCH-DOOR, etc.) |
| sub_category_name | VARCHAR(255) | NOT NULL | Sub-category name |
| 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)
- FOREIGN KEY (project_id) REFERENCES projects(id)
- UNIQUE (sub_category_code)
- INDEX (is_active)
- INDEX (sort_order)
Relationships:
- Parent: projects
- Referenced by: shop_drawings, asbuilt_drawings
Business Rules:
- [CHANGED] Project-specific sub-categories (was global)
- [REMOVED] No longer hierarchical under main categories
- Represents specific drawing types or components
5.8 shop_drawings (UPDATE v1.7.0)
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 |
| 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
- [CHANGED] Title moved to shop_drawing_revisions table
5.9 shop_drawing_revisions (UPDATE v1.7.0)
Purpose: Child table storing revision history of shop drawings (1:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
| shop_drawing_id | INT | NOT NULL, FK | Master shop drawing ID |
| revision_number | INT | NOT NULL | Revision sequence (0, 1, 2...) |
| revision_label | VARCHAR(10) | NULL | Display revision (A, B, C...) |
| revision_date | DATE | NULL | Revision date |
| title | VARCHAR(500) | NOT NULL | [NEW] Drawing title |
| description | TEXT | NULL | Revision description/changes |
| legacy_drawing_number | VARCHAR(100) | NULL | [NEW] Original/legacy drawing number |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Revision creation timestamp |
Indexes:
- 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, asbuilt_revision_shop_revisions_refs
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
- [NEW] Title stored at revision level for version-specific naming
- [NEW] legacy_drawing_number supports data migration from old systems
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
5.11 asbuilt_drawings (NEW v1.7.0)
Purpose: Master table for AS Built drawings (final construction records)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique drawing ID |
| project_id | INT | NOT NULL, FK | Reference to projects |
| drawing_number | VARCHAR(100) | NOT NULL, UNIQUE | AS Built drawing number |
| main_category_id | INT | NOT NULL, FK | Reference to main category |
| sub_category_id | INT | NOT NULL, FK | Reference to sub-category |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
| deleted_at | DATETIME | NULL | Soft delete timestamp |
| updated_by | INT | NULL, FK | User who last updated |
Indexes:
- PRIMARY KEY (id)
- UNIQUE (drawing_number)
- FOREIGN KEY (project_id) REFERENCES projects(id)
- FOREIGN KEY (main_category_id) REFERENCES shop_drawing_main_categories(id)
- FOREIGN KEY (sub_category_id) REFERENCES shop_drawing_sub_categories(id)
- FOREIGN KEY (updated_by) REFERENCES users(user_id)
- INDEX (project_id)
- INDEX (main_category_id)
- INDEX (sub_category_id)
- INDEX (deleted_at)
Relationships:
- Parent: projects, shop_drawing_main_categories, shop_drawing_sub_categories, users
- Children: asbuilt_drawing_revisions
Business Rules:
- Drawing numbers are globally unique across all projects
- Represents final as-built construction drawings
- Can have multiple revisions
- Soft delete preserves history
- Uses same category structure as shop drawings
5.12 asbuilt_drawing_revisions (NEW v1.7.0)
Purpose: Child table storing revision history of AS Built drawings (1:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
| asbuilt_drawing_id | INT | NOT NULL, FK | Master AS Built drawing ID |
| revision_number | INT | NOT NULL | Revision sequence (0, 1, 2...) |
| revision_label | VARCHAR(10) | NULL | Display revision (A, B, C...) |
| revision_date | DATE | NULL | Revision date |
| title | VARCHAR(500) | NOT NULL | Drawing title |
| description | TEXT | NULL | Revision description/changes |
| legacy_drawing_number | VARCHAR(100) | NULL | Original/legacy drawing number |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Revision creation timestamp |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (asbuilt_drawing_id) REFERENCES asbuilt_drawings(id) ON DELETE CASCADE
- UNIQUE KEY (asbuilt_drawing_id, revision_number)
- INDEX (revision_date)
Relationships:
- Parent: asbuilt_drawings
- Referenced by: asbuilt_revision_shop_revisions_refs, asbuilt_drawing_revision_attachments
Business Rules:
- Revision numbers are sequential starting from 0
- Each revision can reference multiple shop drawing revisions
- Each revision can have multiple file attachments
- Title stored at revision level for version-specific naming
- legacy_drawing_number supports data migration from old systems
5.13 asbuilt_revision_shop_revisions_refs (NEW v1.7.0)
Purpose: Junction table linking AS Built drawing revisions to shop drawing revisions (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| asbuilt_drawing_revision_id | INT | PRIMARY KEY, FK | Reference to AS Built revision |
| shop_drawing_revision_id | INT | PRIMARY KEY, FK | Reference to shop drawing revision |
Indexes:
- PRIMARY KEY (asbuilt_drawing_revision_id, shop_drawing_revision_id)
- FOREIGN KEY (asbuilt_drawing_revision_id) REFERENCES asbuilt_drawing_revisions(id) ON DELETE CASCADE
- FOREIGN KEY (shop_drawing_revision_id) REFERENCES shop_drawing_revisions(id) ON DELETE CASCADE
- INDEX (shop_drawing_revision_id)
Relationships:
- Parent: asbuilt_drawing_revisions, shop_drawing_revisions
Business Rules:
- Tracks which shop drawings each AS Built drawing revision is based on
- Maintains construction document lineage
- One AS Built revision can reference multiple shop drawing revisions
- Supports traceability from final construction to approved shop drawings
5.14 asbuilt_drawing_revision_attachments (NEW v1.7.0)
Purpose: Junction table linking AS Built drawing revisions to file attachments (M:N)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| asbuilt_drawing_revision_id | INT | PRIMARY KEY, FK | Reference to AS Built revision |
| attachment_id | INT | PRIMARY KEY, FK | Reference to attachment file |
| file_type | ENUM('PDF', 'DWG', 'SOURCE', 'OTHER') | NULL | File type classification |
| is_main_document | BOOLEAN | DEFAULT FALSE | Main document flag (1 = primary file) |
Indexes:
- PRIMARY KEY (asbuilt_drawing_revision_id, attachment_id)
- FOREIGN KEY (asbuilt_drawing_revision_id) REFERENCES asbuilt_drawing_revisions(id) ON DELETE CASCADE
- FOREIGN KEY (attachment_id) REFERENCES attachments(id) ON DELETE CASCADE
- INDEX (attachment_id)
Relationships:
- Parent: asbuilt_drawing_revisions, attachments
Business Rules:
- Each AS Built revision can have multiple file attachments
- File types: PDF (documents), DWG (CAD files), SOURCE (source files), OTHER (miscellaneous)
- One attachment can be marked as main document per revision
- Cascade delete when revision is deleted
6. ð Circulations Tables (āđāļāđāļ§āļĩāļĒāļāļ āļēāļĒāđāļ)
6.1 circulation_status_codes
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
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 System Tables (āļĢāļ°āļāļāđāļĨāļāļāļĩāđāđāļāļāļŠāļēāļĢ)
9.1 document_number_formats
Purpose: Master table defining numbering formats for each document 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_string | VARCHAR(100) | NOT NULL | Format pattern (e.g., {ORG}-{TYPE}-{YYYY}-#) |
| description | TEXT | NULL | Format description |
| reset_annually | BOOLEAN | DEFAULT TRUE | Start sequence new every year |
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
Indexes:
- 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 (is_active)
Relationships:
- Parent: projects, correspondence_types
Business Rules:
- Defines how document numbers are constructed
- Supports placeholders: {PROJ}, {ORG}, {TYPE}, {YYYY}, {MM}, {#}
9.2 document_number_counters (UPDATE v1.7.0)
Purpose: Transaction table tracking running numbers (High Concurrency)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| project_id | INT | PK, NOT NULL | āđāļāļĢāļāļāļēāļĢ |
| originator_organization_id | INT | PK, NOT NULL | āļāļāļāđāļāļĢāļāļđāđāļŠāđāļ |
| recipient_organization_id | INT | PK, NOT NULL | āļāļāļāđāļāļĢāļāļđāđāļĢāļąāļ (0 = no recipient / RFA) |
| correspondence_type_id | INT | PK, NULL | āļāļĢāļ°āđāļ āļāđāļāļāļŠāļēāļĢ (NULL = default) |
| sub_type_id | INT | PK, DEFAULT 0 | āļāļĢāļ°āđāļ āļāļĒāđāļāļĒ āļŠāļģāļŦāļĢāļąāļ TRANSMITTAL (0 = āđāļĄāđāļĢāļ°āļāļļ) |
| rfa_type_id | INT | PK, DEFAULT 0 | āļāļĢāļ°āđāļ āļ RFA (0 = āđāļĄāđāđāļāđ RFA) |
| discipline_id | INT | PK, DEFAULT 0 | āļŠāļēāļāļēāļāļēāļ (0 = āđāļĄāđāļĢāļ°āļāļļ) |
| reset_scope | VARCHAR(20) | PK, NOT NULL | Scope of reset (YEAR_2024, MONTH_2024_01, NONE) |
| last_number | INT | DEFAULT 0 | āđāļĨāļāļĨāđāļēāļŠāļļāļāļāļĩāđāļāļđāļāđāļāđāļāļēāļāđāļāđāļĨāđāļ§ |
| version | INT | DEFAULT 0 | Optimistic Lock Version |
| updated_at | DATETIME(6) | ON UPDATE | āđāļ§āļĨāļēāļāļĩāđāļāļąāļāđāļāļāļĨāđāļēāļŠāļļāļ |
Indexes:
- PRIMARY KEY (project_id, originator_organization_id, recipient_organization_id, correspondence_type_id, sub_type_id, rfa_type_id, discipline_id, reset_scope)
- INDEX idx_counter_lookup (project_id, correspondence_type_id, reset_scope)
- INDEX idx_counter_org (originator_organization_id, reset_scope)
Business Rules:
- Composite Primary Key 8 Columns: āđāļāļ·āđāļāļĢāļāļāļĢāļąāļāļāļēāļĢāļĢāļąāļāđāļĨāļāļāļĩāđāļāļąāļāļāđāļāļāđāļĨāļ° Reset Scope āļāļĩāđāļŦāļĨāļēāļāļŦāļĨāļēāļĒ
- Concurrency Control: āđāļāđ Redis Lock āļŦāļĢāļ·āļ Optimistic Locking (version)
- Reset Scope: āđāļāđ Field
reset_scopeāļāļ§āļāļāļļāļĄāļāļēāļĢ Reset āđāļāļcurrent_yearāđāļāļāđāļāļīāļĄ
9.3 document_number_audit (UPDATE v1.7.0)
Purpose: Audit log for document number generation (Debugging & Tracking)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PK, AI | ID āļāļāļ audit record |
| document_id | INT | NULL, FK | ID āļāļāļāđāļāļāļŠāļēāļĢāļāļĩāđāļŠāļĢāđāļēāļāđāļĨāļāļāļĩāđ (NULL if failed) |
| document_type | VARCHAR(50) | NULL | āļāļĢāļ°āđāļ āļāđāļāļāļŠāļēāļĢ |
| document_number | VARCHAR(100) | NOT NULL | āđāļĨāļāļāļĩāđāđāļāļāļŠāļēāļĢāļāļĩāđāļŠāļĢāđāļēāļ (āļāļĨāļĨāļąāļāļāđ) |
| operation | ENUM | DEFAULT 'CONFIRM' | RESERVE, CONFIRM, MANUAL_OVERRIDE, etc. |
| status | ENUM | DEFAULT 'RESERVED' | RESERVED, CONFIRMED, CANCELLED, VOID |
| counter_key | JSON | NOT NULL | Counter key āļāļĩāđāđāļāđ (JSON 8 fields) |
| reservation_token | VARCHAR(36) | NULL | Token āļāļēāļĢāļāļāļ |
| idempotency_key | VARCHAR(128) | NULL | Idempotency Key from request |
| originator_organization_id | INT | NULL | āļāļāļāđāļāļĢāļāļđāđāļŠāđāļ |
| recipient_organization_id | INT | NULL | āļāļāļāđāļāļĢāļāļđāđāļĢāļąāļ |
| template_used | VARCHAR(200) | NOT NULL | Template āļāļĩāđāđāļāđāđāļāļāļēāļĢāļŠāļĢāđāļēāļ |
| old_value | TEXT | NULL | Previous value |
| new_value | TEXT | NULL | New value |
| user_id | INT | NULL, FK | āļāļđāđāļāļāļŠāļĢāđāļēāļāđāļĨāļāļāļĩāđ |
| is_success | BOOLEAN | DEFAULT TRUE | āļŠāļāļēāļāļ°āļāļ§āļēāļĄāļŠāļģāđāļĢāđāļ |
| created_at | TIMESTAMP | DEFAULT NOW | āļ§āļąāļāļāļĩāđ/āđāļ§āļĨāļēāļāļĩāđāļŠāļĢāđāļēāļ |
| total_duration_ms | INT | NULL | āđāļ§āļĨāļēāļĢāļ§āļĄāļāļąāđāļāļŦāļĄāļāđāļāļāļēāļĢāļŠāļĢāđāļēāļ (ms) |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (document_id) REFERENCES correspondences(id) ON DELETE CASCADE
- FOREIGN KEY (user_id) REFERENCES users(user_id)
- INDEX (document_id)
- INDEX (user_id)
- INDEX (status)
- INDEX (operation)
- INDEX (document_number)
- INDEX (reservation_token)
- INDEX (created_at)
9.4 document_number_errors (UPDATE v1.7.0)
Purpose: Error log for failed document number generation
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PK, AI | ID āļāļāļ error record |
| error_type | ENUM | NOT NULL | LOCK_TIMEOUT, VERSION_CONFLICT, DB_ERROR, etc. |
| error_message | TEXT | NULL | āļāđāļāļāļ§āļēāļĄ error |
| stack_trace | TEXT | NULL | Stack trace āļŠāļģāļŦāļĢāļąāļ debugging |
| context_data | JSON | NULL | Context āļāļāļ request |
| user_id | INT | NULL | āļāļđāđāļāļĩāđāđāļāļīāļ error |
| created_at | TIMESTAMP | DEFAULT NOW | āļ§āļąāļāļāļĩāđāđāļāļīāļ error |
| resolved_at | TIMESTAMP | NULL | āļ§āļąāļāļāļĩāđāđāļāđāđāļāđāļĨāđāļ§ |
Indexes:
- PRIMARY KEY (id)
- INDEX (error_type)
- INDEX (created_at)
- INDEX (user_id)
- INDEX (resolved_at)
9.5 document_number_reservations (NEW v1.7.0)
Purpose: Two-Phase Commit table for document number reservation
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PK, AI | Unique ID |
| token | VARCHAR(36) | UNIQUE, NOT NULL | UUID v4 Reservation Token |
| document_number | VARCHAR(100) | UNIQUE, NOT NULL | āđāļĨāļāļāļĩāđāđāļāļāļŠāļēāļĢāļāļĩāđāļāļāļ |
| document_number_status | ENUM | DEFAULT RESERVED | RESERVED, CONFIRMED, CANCELLED, VOID |
| document_id | INT | NULL, FK | ID āļāļāļāđāļāļāļŠāļēāļĢ (āđāļĄāļ·āđāļ Confirm āđāļĨāđāļ§) |
| expires_at | DATETIME(6) | NOT NULL | āđāļ§āļĨāļēāļŦāļĄāļāļāļēāļĒāļļāļāļēāļĢāļāļāļ |
| project_id | INT | NOT NULL, FK | Project Context |
| user_id | INT | NOT NULL, FK | User Context |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (document_id) REFERENCES correspondence_revisions(id) ON DELETE SET NULL
- FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE
- FOREIGN KEY (correspondence_type_id) REFERENCES correspondence_types(id) ON DELETE CASCADE
- FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE
- INDEX idx_token (token)
- INDEX idx_status (document_number_status)
- INDEX idx_status_expires (document_number_status, expires_at)
- INDEX idx_document_id (document_id)
- INDEX idx_user_id (user_id)
- INDEX idx_reserved_at (reserved_at)
10. âïļ Unified Workflow Engine Tables (UPDATE v1.7.0)
10.1 workflow_definitions
Purpose: āđāļāđāļāđāļĄāđāđāļāļ (Template) āļāļāļ Workflow (Definition / DSL)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | CHAR(36) | PK, UUID | Unique Workflow Definition ID |
| workflow_code | VARCHAR(50) | NOT NULL | āļĢāļŦāļąāļŠ Workflow (āđāļāđāļ RFA_FLOW_V1) |
| version | INT | DEFAULT 1 | āļŦāļĄāļēāļĒāđāļĨāļ Version |
| description | TEXT | NULL | āļāļģāļāļāļīāļāļēāļĒ Workflow |
| dsl | JSON | NOT NULL | āļāļīāļĒāļēāļĄ Workflow āļāđāļāļāļāļąāļ (YAML/JSON Format) |
| compiled | JSON | NOT NULL | āđāļāļĢāļāļŠāļĢāđāļēāļ Execution Tree āļāļĩāđ Compile āđāļĨāđāļ§ |
| is_active | BOOLEAN | DEFAULT TRUE | āļŠāļāļēāļāļ°āļāļēāļĢāđāļāđāļāļēāļ |
| created_at | TIMESTAMP | DEFAULT NOW | āļ§āļąāļāļāļĩāđāļŠāļĢāđāļēāļ |
| updated_at | TIMESTAMP | ON UPDATE | āļ§āļąāļāļāļĩāđāđāļāđāđāļāļĨāđāļēāļŠāļļāļ |
Indexes:
- PRIMARY KEY (id)
- UNIQUE KEY (workflow_code, version)
- INDEX (is_active)
10.2 workflow_instances
Purpose: āđāļāđāļāļŠāļāļēāļāļ°āļāļāļ Workflow āļāļĩāđāļāļģāļĨāļąāļāļĢāļąāļāļāļĒāļđāđāļāļĢāļīāļ (Runtime)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | CHAR(36) | PK, UUID | Unique Instance ID |
| definition_id | CHAR(36) | FK, NOT NULL | āļāđāļēāļāļāļīāļ Definition āļāļĩāđāđāļāđ |
| entity_type | VARCHAR(50) | NOT NULL | āļāļĢāļ°āđāļ āļāđāļāļāļŠāļēāļĢ (rfa_revision, correspondence...) |
| entity_id | VARCHAR(50) | NOT NULL | ID āļāļāļāđāļāļāļŠāļēāļĢ |
| current_state | VARCHAR(50) | NOT NULL | āļŠāļāļēāļāļ°āļāļąāļāļāļļāļāļąāļ |
| status | ENUM | DEFAULT 'ACTIVE' | ACTIVE, COMPLETED, CANCELLED, TERMINATED |
| context | JSON | NULL | āļāļąāļ§āđāļāļĢ Context āļŠāļģāļŦāļĢāļąāļāļāļąāļāļŠāļīāļāđāļ |
| created_at | TIMESTAMP | DEFAULT NOW | āđāļ§āļĨāļēāļāļĩāđāļŠāļĢāđāļēāļ |
| updated_at | TIMESTAMP | ON UPDATE | āđāļ§āļĨāļēāļāļĩāđāļāļąāļāđāļāļāļĨāđāļēāļŠāļļāļ |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (definition_id) REFERENCES workflow_definitions(id) ON DELETE CASCADE
- INDEX (entity_type, entity_id)
- INDEX (current_state)
10.3 workflow_histories
Purpose: āđāļāđāļāļāļĢāļ°āļ§āļąāļāļīāļāļēāļĢāļāļģāđāļāļīāļāļāļēāļĢāđāļāđāļāđāļĨāļ° Step (Audit Trail)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | CHAR(36) | PK, UUID | Unique ID |
| instance_id | CHAR(36) | FK, NOT NULL | āļāđāļēāļāļāļīāļ Instance |
| from_state | VARCHAR(50) | NOT NULL | āļŠāļāļēāļāļ°āļāđāļāļāļēāļ |
| to_state | VARCHAR(50) | NOT NULL | āļŠāļāļēāļāļ°āļāļĨāļēāļĒāļāļēāļ |
| action | VARCHAR(50) | NOT NULL | Action āļāļĩāđāļāļĢāļ°āļāļģ |
| action_by_user_id | INT | FK, NULL | User ID āļāļđāđāļāļĢāļ°āļāļģ |
| comment | TEXT | NULL | āļāļ§āļēāļĄāđāļŦāđāļ |
| metadata | JSON | NULL | Snapshot āļāđāļāļĄāļđāļĨ āļ āļāļāļ°āļāļąāđāļ |
| created_at | TIMESTAMP | DEFAULT NOW | āđāļ§āļĨāļēāļāļĩāđāļāļĢāļ°āļāļģ |
Indexes:
- PRIMARY KEY (id)
- FOREIGN KEY (instance_id) REFERENCES workflow_instances(id) ON DELETE CASCADE
- INDEX (instance_id)
- INDEX (action_by_user_id)
11. ðĨïļ System & Logs Tables (āļĢāļ°āļāļ, āļāļąāļāļāļķāļ)
Audit Logging Architecture:
1. Audit Logging
Table: audit_logs
āļāļąāļāļāļķāļāļāļēāļĢāđāļāļĨāļĩāđāļĒāļāđāļāļĨāļāļŠāļģāļāļąāļ:
- User actions (CREATE, UPDATE, DELETE)
- Entity type āđāļĨāļ° Entity ID
- Old/New values (JSON)
- IP Address, User Agent
2. User Preferences
Table: user_preferences
āđāļāđāļāļāļēāļĢāļāļąāđāļāļāđāļēāļŠāđāļ§āļāļāļąāļ§:
- Language preference
- Notification settings
- UI preferences (JSON)
3. JSON Schema Validation
Table: json_schemas
āđāļāđāļ Schema āļŠāļģāļŦāļĢāļąāļ Validate JSON fields:
correspondence_revisions.detailsuser_preferences.preferences
11.1 json_schemas (UPDATE v1.7.0)
Purpose: āđāļāđāļ Schema āļŠāļģāļŦāļĢāļąāļ Validate JSON Columns (Req 3.12)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PK, AI | Unique ID |
| schema_code | VARCHAR(100) | NOT NULL | āļĢāļŦāļąāļŠ Schema (āđāļāđāļ RFA_DWG) |
| version | INT | DEFAULT 1 | āđāļ§āļāļĢāđāļāļąāļāļāļāļ Schema |
| table_name | VARCHAR(100) | NOT NULL | āļāļ·āđāļāļāļēāļĢāļēāļāđāļāđāļēāļŦāļĄāļēāļĒ |
| schema_definition | JSON | NOT NULL | JSON Schema Definition |
| ui_schema | JSON | NULL | āđāļāļĢāļāļŠāļĢāđāļēāļ UI Schema āļŠāļģāļŦāļĢāļąāļ Frontend |
| virtual_columns | JSON | NULL | Config āļŠāļģāļŦāļĢāļąāļāļŠāļĢāđāļēāļ Virtual Columns |
| migration_script | JSON | NULL | Script āļŠāļģāļŦāļĢāļąāļāđāļāļĨāļāļāđāļāļĄāļđāļĨ |
| is_active | BOOLEAN | DEFAULT TRUE | āļŠāļāļēāļāļ°āļāļēāļĢāđāļāđāļāļēāļ |
11.2 audit_logs (UPDATE v1.7.0)
Purpose: Centralized audit logging for all system actions (Req 6.1)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| audit_id | BIGINT | PK, AI | Unique log ID |
| request_id | VARCHAR(100) | NULL | Trace ID linking to app logs |
| user_id | INT | NULL, FK | User who performed action |
| action | VARCHAR(100) | NOT NULL | Action name (e.g. rfa.create) |
| severity | ENUM | DEFAULT 'INFO' | INFO, WARN, ERROR, CRITICAL |
| entity_type | VARCHAR(50) | NULL | Module/Table name (e.g. rfa, correspondence) |
| entity_id | VARCHAR(50) | NULL | ID of affected entity |
| details_json | JSON | NULL | Context data / Old & New values |
| ip_address | VARCHAR(45) | NULL | User IP address |
| user_agent | VARCHAR(255) | NULL | User browser/client info |
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Log timestamp |
Indexes:
- PRIMARY KEY (audit_id, created_at) -- Partition Key
- INDEX idx_audit_user (user_id)
- INDEX idx_audit_action (action)
- INDEX idx_audit_entity (entity_type, entity_id)
- INDEX idx_audit_created (created_at)
Partitioning:
- PARTITION BY RANGE (YEAR(created_at)): āđāļāđāļ Partition āļĢāļēāļĒāļāļĩ āđāļāļ·āđāļāļāļĢāļ°āļŠāļīāļāļāļīāļ āļēāļāđāļāļāļēāļĢāđāļāđāļāļāđāļāļĄāļđāļĨāļĢāļ°āļĒāļ°āļĒāļēāļ§
11.3 notifications (UPDATE v1.7.0)
Purpose: System notifications for users
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique notification ID |
| user_id | INT | NOT NULL, FK | Recipient user ID |
| title | VARCHAR(255) | NOT NULL | Notification title |
| message | TEXT | NOT NULL | Notification body |
| notification_type | ENUM | NOT NULL | Type: EMAIL, LINE, SYSTEM |
| is_read | BOOLEAN | DEFAULT FALSE | Read status |
| entity_type | VARCHAR(50) | NULL | Related Entity Type |
| entity_id | INT | NULL | Related Entity ID |
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Notification timestamp |
Indexes:
- PRIMARY KEY (id, created_at) -- Partition Key
- INDEX idx_notif_user (user_id)
- INDEX idx_notif_type (notification_type)
- INDEX idx_notif_read (is_read)
- INDEX idx_notif_created (created_at)
Partitioning:
- PARTITION BY RANGE (YEAR(created_at)): āđāļāđāļ Partition āļĢāļēāļĒāļāļĩ
12. ð Views (āļĄāļļāļĄāļĄāļāļāļāđāļāļĄāļđāļĨ)
12.1 v_current_correspondences
Purpose: āđāļŠāļāļāļāđāļāļĄāļđāļĨ Correspondence Revision āļĨāđāļēāļŠāļļāļ (is_current = TRUE)
12.2 v_current_rfas
Purpose: āđāļŠāļāļāļāđāļāļĄāļđāļĨ RFA Revision āļĨāđāļēāļŠāļļāļ āļāļĢāđāļāļĄ Status āđāļĨāļ° Approve Code
12.3 v_user_tasks (Unified Workflow)
Purpose: āļĢāļ§āļĄāļĢāļēāļĒāļāļēāļĢāļāļēāļāļāļĩāđāļĒāļąāļāļāđāļēāļāļāļĒāļđāđ (Status = ACTIVE) āļāļēāļāļāļļāļāļĢāļ°āļāļ (RFA, Circulation, Correspondence) āđāļāļ·āđāļāļāļģāđāļāđāļŠāļāļāđāļ Dashboard
12.4 v_audit_log_details
Purpose: āđāļŠāļāļ audit_logs āļāļĢāđāļāļĄāļāđāļāļĄāļđāļĨ username āđāļĨāļ° email āļāļāļāļāļđāđāļāļĢāļ°āļāļģ
12.5 v_user_all_permissions
Purpose: āļĢāļ§āļĄāļŠāļīāļāļāļīāđāļāļąāđāļāļŦāļĄāļ (Global + Project + Organization) āļāļāļāļāļđāđāđāļāđāļāļļāļāļāļ
12.6 v_documents_with_attachments
Purpose: āđāļŠāļāļāđāļāļāļŠāļēāļĢāļāļąāđāļāļŦāļĄāļāļāļĩāđāļĄāļĩāđāļāļĨāđāđāļāļ (Correspondence, Circulation, Drawings)
12.7 v_document_statistics
Purpose: āđāļŠāļāļāļŠāļāļīāļāļīāđāļāļāļŠāļēāļĢāļāļēāļĄāļāļĢāļ°āđāļ āļāđāļĨāļ°āļŠāļāļēāļāļ°
13. ð Index Summaries (āļŠāļĢāļļāļ Index)
Performance Optimization Strategy:
1. Indexing Strategy
Primary Indexes:
- Primary Keys (AUTO_INCREMENT)
- Foreign Keys (automatic in InnoDB)
- Unique Constraints (business keys)
Secondary Indexes:
-- Correspondence search
CREATE INDEX idx_corr_type_status ON correspondence_revisions(correspondence_type_id, correspondence_status_id);
CREATE INDEX idx_corr_date ON correspondence_revisions(document_date);
-- Virtual columns for JSON
CREATE INDEX idx_v_ref_project ON correspondence_revisions(v_ref_project_id);
CREATE INDEX idx_v_doc_subtype ON correspondence_revisions(v_doc_subtype);
-- User lookup
CREATE INDEX idx_user_email ON users(email);
CREATE INDEX idx_user_org ON users(primary_organization_id, is_active);
2. Virtual Columns
āđāļāđ Virtual Columns āļŠāļģāļŦāļĢāļąāļ Index JSON fields:
ALTER TABLE correspondence_revisions
ADD COLUMN v_ref_project_id INT GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(details, '$.ref_project_id'))) VIRTUAL,
ADD INDEX idx_v_ref_project(v_ref_project_id);
3. Partitioning (Future)
āļāļīāļāļēāļĢāļāļē Partition āļāļēāļĢāļēāļ audit_logs āļāļēāļĄāļāļĩ:
ALTER TABLE audit_logs
PARTITION BY RANGE (YEAR(created_at)) (
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p2025 VALUES LESS THAN (2026),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
13.1 Performance Indexes
| Table Name | Index Columns | Purpose |
|---|---|---|
| correspondences | (project_id, correspondence_number) | Fast lookup by document number |
| correspondences | (correspondence_type_id) | Filter by type |
| correspondence_revisions | (correspondence_id, is_current) | Get current revision |
| rfas | (rfa_type_id) | Filter by RFA type |
| rfa_revisions | (rfa_id, is_current) | Get current RFA revision |
| rfa_revisions | (rfa_status_code_id) | Filter by status |
| audit_logs | (created_at) | Date range queries |
| audit_logs | (user_id) | User activity history |
| audit_logs | (module, action) | Action type analysis |
| notifications | (user_id, is_read) | Unread notifications query |
| document_number_counters | (project_id, correspondence_type_id, reset_scope) | Running number generation |
| workflow_instances | (entity_type, entity_id) | Workflow lookup by document ID |
| workflow_instances | (current_state) | Monitor active workflows |
13.2 Unique Constraints
| Table Name | Columns | Description |
|---|---|---|
| users | (username) | Unique login name |
| users | (email) | Unique email address |
| organizations | (organization_code) | Unique organization code |
| projects | (project_code) | Unique project code |
| contracts | (contract_code) | Unique contract code |
| correspondences | (project_id, correspondence_number) | Unique document number per project |
| shop_drawings | (drawing_number) | Unique shop drawing number |
| document_number_formats | (project_id, correspondence_type_id) | One format per type per project |
| workflow_definitions | (workflow_code, version) | Unique workflow code per version |
14. ðĄïļ Data Integrity Constraints (āļāļ§āļēāļĄāļāļđāļāļāđāļāļāļāļāļāļāđāļāļĄāļđāļĨ)
14.1 Soft Delete Policy
- Tables with
deleted_at:- users
- organizations
- projects
- contracts
- correspondences
- rfas
- shop_drawings
- contract_drawings
- Rule: Records are never physically deleted.
deleted_atis set to timestamp. - Query Rule: All standard queries MUST include
WHERE deleted_at IS NULL.
14.2 Foreign Key Cascades
- ON DELETE CASCADE:
- Used for child tables that cannot exist without parent (e.g.,
correspondence_revisions,rfa_revisions,correspondence_attachments).
- Used for child tables that cannot exist without parent (e.g.,
- ON DELETE RESTRICT:
- Used for master data references to prevent accidental deletion of used data (e.g.,
correspondence_types,organizations).
- Used for master data references to prevent accidental deletion of used data (e.g.,
- ON DELETE SET NULL:
- Used for optional references (e.g.,
created_by,originator_id).
- Used for optional references (e.g.,
15. ð Security & Permissions Model (āļāļ§āļēāļĄāļāļĨāļāļāļ āļąāļĒ)
15.1 Row-Level Security (RLS) Logic
- Organization Scope: Users can only see documents where
originator_idORrecipient_organization_idmatches their organization. - Project Scope: Users can only see documents within projects they are assigned to.
- Confidentiality: Documents marked
is_confidentialare visible ONLY to specific roles or users.
15.2 Role-Based Access Control (RBAC)
- Permissions are granular (e.g.,
correspondence.view,correspondence.create). - Roles aggregate permissions (e.g.,
Document Controller=view+create+edit). - Assignments link Users to Roles within a Context (Global, Project, or Organization).
16. ð Data Migration & Seeding (āļāļēāļĢāļĒāđāļēāļĒāļāđāļāļĄāļđāļĨ)
16.1 Initial Seeding (V1.7.0)
- Master Data:
organizations: Owner, Consultant, Contractorprojects: LCBP3correspondence_types: LETTER, MEMO, TRANSMITTAL, RFArfa_types: DWG, MAT, DOC, RFIrfa_status_codes: DFT, PEND, APPR, REJdisciplines: GEN, STR, ARC, MEP
- System Users:
admin: Super Adminsystem: System Bot for automated tasks
16.2 Migration Strategy
- Schema Migration: Use TypeORM Migrations or raw SQL scripts (versioned).
- Data Migration:
- V1.6.0 -> V1.7.0:
- Run SQL script
9_lcbp3_v1_7_0.sql - Migrate
document_number_countersto 8-col composite PK. - Initialize
document_number_reservations. - Update
json_schemaswith new columns.
- Run SQL script
- V1.6.0 -> V1.7.0:
16.3 Temporary Migration Tracking Tables (V1.8.0 n8n Migration)
āļāļēāļĢāļēāļāđāļŦāļĨāđāļēāļāļĩāđāļāļđāļāđāļāđāļāļąāđāļ§āļāļĢāļēāļ§āļĢāļ°āļŦāļ§āđāļēāļāļāļĢāļ°āļāļ§āļāļāļēāļĢ Migrate āđāļāļāļŠāļēāļĢ PDF 20,000 āļāļāļąāļāļāđāļ§āļĒ n8n (āļāļđāļĢāļēāļĒāļĨāļ°āđāļāļĩāļĒāļāđāļ <20>3-05-n8n-migration-setup-guide.md) āđāļĨāļ°āđāļĄāđāđāļāđāļāļēāļĢāļēāļ Business āļŦāļĨāļąāļāļāļāļāļĢāļ°āļāļ
16.3.1 migration_progress
Purpose: āđāļāđāļ Checkpoint āļŠāļāļēāļāļ°āļāļēāļĢ Migrate
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| batch_id | VARCHAR(50) | PRIMARY KEY | āļĢāļŦāļąāļŠāļāļļāļāļāļēāļĢ Migrate |
| last_processed_index | INT | DEFAULT 0 | āļĨāļģāļāļąāļāļĨāđāļēāļŠāļļāļāļāļĩāđāļāļĢāļ°āļĄāļ§āļĨāļāļĨāļāđāļēāļ |
| status | ENUM | DEFAULT 'RUNNING' | āļŠāļāļēāļāļ° (RUNNING, COMPLETED, FAILED) |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | āđāļ§āļĨāļēāļāļąāļāđāļāļāļĨāđāļēāļŠāļļāļ |
16.3.2 migration_review_queue
Purpose: āļāļīāļ§āđāļāļāļŠāļēāļĢāļāļĩāđāļāđāļāļāļāļēāļĢāđāļŦāđāđāļāđāļēāļŦāļāđāļēāļāļĩāđāļāļĢāļ§āļāļŠāļāļ (Confidence āļāđāļģāļāļ§āđāļēāđāļāļāļāđ) āļŦāļĄāļēāļĒāđāļŦāļāļļ: āđāļĄāļ·āđāļāļāļĢāļ§āļāļŠāļāļāļāđāļēāļāđāļĨāļ°āļŠāļĢāđāļēāļ Correspondence āļāļĢāļīāļāđāļĨāđāļ§ āļāđāļāļĄāļđāļĨāđāļāļāļĩāđāļāļēāļāļāļđāļāļĨāļāļŦāļĢāļ·āļāđāļāđāļāđāļāđāļ Log āđāļāđ
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique ID |
| document_number | VARCHAR(100) | NOT NULL, UNIQUE | āđāļĨāļāļāļĩāđāđāļāļāļŠāļēāļĢ (āļāļēāļ OCR) |
| title | TEXT | āļāļ·āđāļāđāļĢāļ·āđāļāļ | |
| original_title | TEXT | āļāļ·āđāļāđāļĢāļ·āđāļāļāļāđāļāļāļāļąāļāļāđāļāļāļāļĢāļ§āļāļŠāļāļ | |
| ai_suggested_category | VARCHAR(50) | āļŦāļĄāļ§āļāļŦāļĄāļđāđāļāļĩāđ AI āđāļāļ°āļāļģ | |
| ai_confidence | DECIMAL(4,3) | āļāđāļēāļāļ§āļēāļĄāļĄāļąāđāļāđāļāļāļāļ AI (0.000 - 1.000) | |
| ai_issues | JSON | āļĢāļēāļĒāļĨāļ°āđāļāļĩāļĒāļāļāļąāļāļŦāļēāļāļĩāđ AI āļāļ | |
| review_reason | VARCHAR(255) | āđāļŦāļāļļāļāļĨāļāļĩāđāļāđāļāļāļāļĢāļ§āļāļŠāļāļ (āđāļāđāļ Confidence āļāđāļģ) | |
| status | ENUM | DEFAULT 'PENDING' | PENDING, APPROVED, REJECTED |
| reviewed_by | VARCHAR(100) | āļāļđāđāļāļĢāļ§āļāļŠāļāļ | |
| reviewed_at | TIMESTAMP | NULL | āđāļ§āļĨāļēāļāļĩāđāļāļĢāļ§āļāļŠāļāļ |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | āļ§āļąāļāļāļĩāđāļāļąāļāļāļķāļāđāļāđāļēāļāļīāļ§ |
16.3.3 migration_errors
Purpose: āļāļąāļāļāļķāļāļāđāļāļāļīāļāļāļĨāļēāļ (Errors) āļĢāļ°āļŦāļ§āđāļēāļāļāļēāļĢāļāļģāļāļēāļāļāļāļ n8n workflow
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique ID |
| batch_id | VARCHAR(50) | INDEX | āļĢāļŦāļąāļŠāļāļļāļāļāļēāļĢ Migrate |
| document_number | VARCHAR(100) | āđāļĨāļāļāļĩāđāđāļāļāļŠāļēāļĢ | |
| error_type | ENUM | INDEX | āļāļĢāļ°āđāļ āļ Error (FILE_NOT_FOUND, AI_PARSE_ERROR, etc.) |
| error_message | TEXT | āļĢāļēāļĒāļĨāļ°āđāļāļĩāļĒāļ Error | |
| raw_ai_response | TEXT | Raw response āļāļēāļ AI āļāļĢāļāļĩāđāļāļĨāļāļĨāđāļĄāđāđāļāđ | |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | āļ§āļąāļāļāļĩāđāļāļąāļāļāļķāļ |
16.3.4 migration_fallback_state
Purpose: āļāļīāļāļāļēāļĄāļŠāļāļēāļāļ° Fallback āļāļāļ AI (āđāļāđāļ āđāļāļĨāļĩāđāļĒāļ Model āđāļĄāļ·āđāļ Error āļāļĩāđ)
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique ID |
| batch_id | VARCHAR(50) | UNIQUE | āļĢāļŦāļąāļŠāļāļļāļāļāļēāļĢ Migrate |
| recent_error_count | INT | DEFAULT 0 | āļāļģāļāļ§āļ Error āļĢāļ§āļāļĨāđāļēāļŠāļļāļ |
| is_fallback_active | BOOLEAN | DEFAULT FALSE | āļŠāļāļēāļāļ°āļāļēāļĢāđāļāđāļāļēāļ Fallback Model |
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | āđāļ§āļĨāļēāļāļąāļāđāļāļāļĨāđāļēāļŠāļļāļ |
16.3.5 import_transactions
Purpose: āļāđāļāļāļāļąāļāļāđāļāļĄāļđāļĨāļāđāļģ (Idempotency) āļĢāļ°āļŦāļ§āđāļēāļāļāļēāļĢ Patch āļāđāļāļĄāļđāļĨ
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique ID |
| idempotency_key | VARCHAR(255) | UNIQUE, NOT NULL | Key āļŠāļģāļŦāļĢāļąāļāđāļāđāļāļāđāļģ |
| document_number | VARCHAR(100) | āđāļĨāļāļāļĩāđāđāļāļāļŠāļēāļĢ | |
| batch_id | VARCHAR(100) | āļĢāļŦāļąāļŠāļāļļāļāļāļēāļĢ Migrate | |
| status_code | INT | DEFAULT 201 | HTTP Status āļāļāļāļāļēāļĢ Import |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | āļ§āļąāļāļāļĩāđāļāļąāļāļāļķāļ |
16.3.6 migration_daily_summary
Purpose: āļŠāļĢāļļāļāļĒāļāļāļāļēāļĢāļāļģāļāļēāļāļĢāļēāļĒāļ§āļąāļāđāļĒāļāļāļēāļĄ Batch
| Column Name | Data Type | Constraints | Description |
|---|---|---|---|
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique ID |
| batch_id | VARCHAR(50) | UNIQUE KEY PART 1 | āļĢāļŦāļąāļŠāļāļļāļāļāļēāļĢ Migrate |
| summary_date | DATE | UNIQUE KEY PART 2 | āļ§āļąāļāļāļĩāđāļŠāļĢāļļāļ |
| total_processed | INT | DEFAULT 0 | āļāļģāļāļ§āļāļāļĩāđāļāļĢāļ°āļĄāļ§āļĨāļāļĨāļĢāļ§āļĄ |
| auto_ingested | INT | DEFAULT 0 | āļāļģāļāļ§āļāļāļĩāđāđāļāđāļēāļŠāļđāđāļĢāļ°āļāļāļŠāļģāđāļĢāđāļ |
| sent_to_review | INT | DEFAULT 0 | āļāļģāļāļ§āļāļāļĩāđāļŠāđāļāļāļīāļ§āļāļĢāļ§āļāļŠāļāļ |
| rejected | INT | DEFAULT 0 | āļāļģāļāļ§āļāļāļĩāđāļāļđāļāļāļāļīāđāļŠāļ |
| errors | INT | DEFAULT 0 | āļāļģāļāļ§āļāļāļĩāđāđāļāļīāļ Error |
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | āļ§āļąāļāļāļĩāđāļāļąāļāļāļķāļ |
17. ð Monitoring & Maintenance (āļāļēāļĢāļāļđāđāļĨāļĢāļąāļāļĐāļē)
17.1 Database Maintenance
- Daily: Incremental Backup.
- Weekly: Full Backup +
OPTIMIZE TABLEfor heavy tables (audit_logs,notifications). - Monthly: Archive old
audit_logspartitions to cold storage.
17.2 Health Checks
- Monitor
document_number_errorsfor numbering failures. - Monitor
workflow_instancesfor stuck workflows (status = ' IN_PROGRESS '> 7 days). - Check
document_number_countersfor gaps or resets.
18. ð Best Practices
1. Naming Conventions
- Tables:
snake_case, plural (e.g.,correspondences,users) - Columns:
snake_case(e.g.,correspondence_number,created_at) - Foreign Keys:
{referenced_table_singular}_id(e.g.,project_id,user_id) - Junction Tables:
{table1}_{table2}(e.g.,correspondence_tags)
2. Timestamp Columns
āļāļļāļāļāļēāļĢāļēāļāļāļ§āļĢāļĄāļĩ:
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMPupdated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
3. Soft Delete
āđāļāđ deleted_at DATETIME NULL āđāļāļāļāļēāļĢāļĨāļāļāļĢāļīāļ:
-- Soft delete
UPDATE correspondences SET deleted_at = NOW() WHERE id = 1;
-- Query active records
SELECT * FROM correspondences WHERE deleted_at IS NULL;
4. JSON Field Guidelines
- āđāļāđāļŠāļģāļŦāļĢāļąāļāļāđāļāļĄāļđāļĨāļāļĩāđāđāļĄāđāļāđāļāļ Query āļāđāļāļĒ
- āļŠāļĢāđāļēāļ Virtual Columns āļŠāļģāļŦāļĢāļąāļ fields āļāļĩāđāļāđāļāļ Index
- Validate āļāđāļ§āļĒ JSON Schema
- Document structure āđāļ Data Dictionary
19. ð Glossary (āļāļģāļĻāļąāļāļāđ)
- RFA: Request for Approval (āđāļāļāļŠāļēāļĢāļāļāļāļāļļāļĄāļąāļāļī)
- Transmittal: Document Transmittal Sheet (āđāļāļāļģāļŠāđāļāđāļāļāļŠāļēāļĢ)
- Shop Drawing: āđāļāļāļāđāļāļŠāļĢāđāļēāļāļāļĩāđāļāļđāđāļĢāļąāļāđāļŦāļĄāļēāļāļąāļāļāļģ
- Contract Drawing: āđāļāļāļŠāļąāļāļāļē (āđāļāļāļāļąāđāļāļāđāļ)
- Revision: āļāļāļąāļāđāļāđāđāļ (0, 1, 2, A, B, C)
- Originator: āļāļđāđāļāļąāļāļāļģ/āļāļđāđāļŠāđāļāđāļāļāļŠāļēāļĢ
- Recipient: āļāļđāđāļĢāļąāļāđāļāļāļŠāļēāļĢ
- Workflow: āļāļĢāļ°āļāļ§āļāļāļēāļĢāļāļģāļāļēāļ/āļāļāļļāļĄāļąāļāļī
- Discipline: āļŠāļēāļāļēāļāļēāļ (āđāļāđāļ āđāļĒāļāļē, āļŠāļāļēāļāļąāļāļĒāđ, āđāļāļāđāļē)
End of Data Dictionary V1.8.0