From 7259cbf67a78fe681ce95b1c53d9ec8c5b871835 Mon Sep 17 00:00:00 2001 From: admin Date: Tue, 19 May 2026 17:19:24 +0700 Subject: [PATCH] 690519:1719 224 to 226 AI #02 --- CONTRIBUTING.md | 2 +- .../performance/pattern-matcher.perf-spec.ts | 12 +- .../03-01-data-dictionary.md | 104 +++- specs/03-Data-and-Storage/README.md | 34 +- .../deltas/01-add-reference-date.sql | 4 - .../deltas/02-add-rbac-bulk-permission.sql | 12 - .../deltas/03-fix-numbering-enums.sql | 30 - ...add-workflow-history-id-to-attachments.sql | 25 - .../deltas/05-add-circulation-deadline.sql | 13 - ...06-add-circulation-workflow-definition.sql | 87 --- ...-add-contract-id-to-workflow-instances.sql | 22 - .../08-add-rag-status-to-attachments.sql | 11 - .../deltas/08b-create-document-chunks.sql | 25 - .../deltas/08c-seed-rag-permissions.sql | 8 - ...9-add-version-no-to-workflow-instances.sql | 17 - ...ion-by-user-uuid-to-workflow-histories.sql | 14 - .../deltas/11-add-uuid-to-roles.sql | 25 - .../deltas/12-unified-ai-architecture.sql | 88 --- .../deltas/14-add-migration-review-queue.sql | 56 -- .../deltas/15-add-ai-processing-status.sql | 14 - .../deltas/16-add-intent-classification.sql | 60 -- .../deltas/17-seed-intent-patterns.sql | 89 --- .../lcbp3-v1.9.0-rfa-approval-schema.sql | 211 ------- .../lcbp3-v1.9.0-schema-02-tables.sql | 80 ++- .../lcbp3-v1.9.0-schema-03-views-indexes.sql | 17 + .../lcbp3-v1.9.0-seed-basic.sql | 527 ++++++++++++++++++ .../lcbp3-v1.9.0-seed-permissions.sql | 42 +- specs/06-Decision-Records/README.md | 17 +- specs/200-fullstacks/README.md | 5 + specs/README.md | 10 +- 30 files changed, 783 insertions(+), 878 deletions(-) delete mode 100644 specs/03-Data-and-Storage/deltas/01-add-reference-date.sql delete mode 100644 specs/03-Data-and-Storage/deltas/02-add-rbac-bulk-permission.sql delete mode 100644 specs/03-Data-and-Storage/deltas/03-fix-numbering-enums.sql delete mode 100644 specs/03-Data-and-Storage/deltas/04-add-workflow-history-id-to-attachments.sql delete mode 100644 specs/03-Data-and-Storage/deltas/05-add-circulation-deadline.sql delete mode 100644 specs/03-Data-and-Storage/deltas/06-add-circulation-workflow-definition.sql delete mode 100644 specs/03-Data-and-Storage/deltas/07-add-contract-id-to-workflow-instances.sql delete mode 100644 specs/03-Data-and-Storage/deltas/08-add-rag-status-to-attachments.sql delete mode 100644 specs/03-Data-and-Storage/deltas/08b-create-document-chunks.sql delete mode 100644 specs/03-Data-and-Storage/deltas/08c-seed-rag-permissions.sql delete mode 100644 specs/03-Data-and-Storage/deltas/09-add-version-no-to-workflow-instances.sql delete mode 100644 specs/03-Data-and-Storage/deltas/10-add-action-by-user-uuid-to-workflow-histories.sql delete mode 100644 specs/03-Data-and-Storage/deltas/11-add-uuid-to-roles.sql delete mode 100644 specs/03-Data-and-Storage/deltas/12-unified-ai-architecture.sql delete mode 100644 specs/03-Data-and-Storage/deltas/14-add-migration-review-queue.sql delete mode 100644 specs/03-Data-and-Storage/deltas/15-add-ai-processing-status.sql delete mode 100644 specs/03-Data-and-Storage/deltas/16-add-intent-classification.sql delete mode 100644 specs/03-Data-and-Storage/deltas/17-seed-intent-patterns.sql delete mode 100644 specs/03-Data-and-Storage/lcbp3-v1.9.0-rfa-approval-schema.sql diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 1caf1aad..1ed0b349 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,6 +1,6 @@ # 📝 Contributing to LCBP3-DMS Specifications -> แนวทางการมีส่วนร่วมในการพัฒนาเอกสาร Specifications ของโครงการ LCBP3-DMS (v1.9.2) +> แนวทางการมีส่วนร่วมในการพัฒนาเอกสาร Specifications ของโครงการ LCBP3-DMS (v1.9.5) ยินดีต้อนรับสู่คู่มือการมีส่วนร่วมในการพัฒนาเอกสาร Specifications! เอกสารนี้จะช่วยให้คุณเข้าใจวิธีการสร้าง แก้ไข และปรับปรุงเอกสารข้อกำหนดของโครงการได้อย่างมีประสิทธิภาพ diff --git a/backend/tests/performance/pattern-matcher.perf-spec.ts b/backend/tests/performance/pattern-matcher.perf-spec.ts index 25858399..83d79178 100644 --- a/backend/tests/performance/pattern-matcher.perf-spec.ts +++ b/backend/tests/performance/pattern-matcher.perf-spec.ts @@ -58,14 +58,9 @@ describe('PatternMatcherService — Performance', () => { expect(result?.intentCode).toBe('SUMMARIZE_DOCUMENT'); const avg = times.reduce((a, b) => a + b, 0) / times.length; - const max = Math.max(...times); + const _max = Math.max(...times); // Kept for potential future debugging const p95 = times.sort((a, b) => a - b)[Math.floor(times.length * 0.95)]; - // eslint-disable-next-line no-console -- performance logging allowed in test - console.log( - `Pattern Match Perf: avg=${avg.toFixed(3)}ms, p95=${p95.toFixed(3)}ms, max=${max.toFixed(3)}ms` - ); - // SC-001: synthetic worst-case (100+ patterns รวม 50 invalid regex try-catch) // ค่า threshold สูงเพื่อรองรับ CI/IDE background load — regression detection only // Production (keyword-only, 10-20 patterns): < 1ms @@ -100,11 +95,6 @@ describe('PatternMatcherService — Performance', () => { const avg = times.reduce((a, b) => a + b, 0) / times.length; const p95 = times.sort((a, b) => a - b)[Math.floor(times.length * 0.95)]; - // eslint-disable-next-line no-console -- performance logging allowed in test - console.log( - `Pattern Miss Perf: avg=${avg.toFixed(3)}ms, p95=${p95.toFixed(3)}ms` - ); - // SC-001: worst-case full scan (100+ patterns รวม 50 invalid regex try-catch) // Production keyword-only จะ < 1ms — ค่านี้เพื่อ regression detection expect(avg).toBeLessThan(200); diff --git a/specs/03-Data-and-Storage/03-01-data-dictionary.md b/specs/03-Data-and-Storage/03-01-data-dictionary.md index ae494b15..2edbcb01 100644 --- a/specs/03-Data-and-Storage/03-01-data-dictionary.md +++ b/specs/03-Data-and-Storage/03-01-data-dictionary.md @@ -2371,7 +2371,43 @@ PENDING_REVIEW ──→ VERIFIED ──→ IMPORTED (terminal) --- -### 19.3 Confidence Scoring Strategy (ADR-020) +### 19.3 `document_chunks` + +**วัตถุประสงค์:** เก็บ vector metadata สำหรับ RAG ingestion ตาม ADR-022 + +| Column | Type | Nullable | Description | +|--------|------|----------|-------------| +| `id` | CHAR(36) | NO | UUID = Qdrant point ID | +| `document_id` | CHAR(36) | NO | FK → attachments.public_id (UUIDv7) | +| `chunk_index` | INT | NO | ลำดับ chunk ภายใน document | +| `content` | TEXT | NO | เนื้อหา chunk หลัง PyThaiNLP normalize | +| `doc_type` | VARCHAR(20) | NO | CORR, RFA, DRAWING, CONTRACT, RPT, TRANS | +| `doc_number` | VARCHAR(100) | YES | หมายเลขเอกสาร เช่น REF-2026-001 | +| `revision` | VARCHAR(20) | YES | Revision เช่น Rev.A | +| `project_code` | VARCHAR(50) | NO | รหัสโครงการ (ใช้ filter) | +| `project_public_id` | CHAR(36) | NO | UUIDv7 ของโครงการ (Qdrant tenant key) | +| `version` | VARCHAR(20) | YES | เวอร์ชันเอกสาร เช่น 1.0, 2.1 (ถ้ามี) | +| `classification` | ENUM | NO | PUBLIC, INTERNAL, CONFIDENTIAL (DEFAULT: INTERNAL) | +| `embedding_model` | VARCHAR(100) | NO | nomic-embed-text | +| `created_at` | DATETIME(3) | NO | วันที่สร้าง | + +**Indexes**: + +- PRIMARY KEY (id) +- INDEX idx_chunks_document_id (document_id) +- INDEX idx_chunks_doc_number_rev (doc_number, revision) +- INDEX idx_chunks_project (project_public_id) +- FULLTEXT INDEX ft_chunks_content (content) + +**Business Rules**: + +1. **Project Isolation** — Qdrant queries MUST include project_public_id filter (compile-time enforcement per ADR-023A) +2. **Chunk Size** — 512 tokens with 64 tokens overlap (ADR-023A RAG embed scope) +3. **Embedding Model** — nomic-embed-text only (ADR-023A 2-model stack) + +--- + +### 19.4 Confidence Scoring Strategy (ADR-020) | Score Range | Action | Description | |-------------|--------|-------------| @@ -2382,6 +2418,72 @@ PENDING_REVIEW ──→ VERIFIED ──→ IMPORTED (terminal) --- +### 19.4 Intent Classification Tables (ADR-024) + +> เพิ่มใน v1.9.0 — Feature 224-intent-classification | ตารางสำหรับ Hybrid Intent Classifier (Pattern Match + LLM Fallback) + +#### 19.4.1 `ai_intent_definitions` + +**วัตถุประสงค์:** เก็บ Intent Definitions (ประเภทความตั้งใจของผู้ใช้) สำหรับ Hybrid Intent Classifier ตาม ADR-024 + +| Column Name | Data Type | Constraints | Description | +| ----------- | --------- | ----------- | ----------- | +| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal PK (ห้าม expose ใน API) | +| public_id | UUID | NOT NULL, UNIQUE, DEFAULT UUID() | UUID Public Identifier (ADR-019) | +| intent_code | VARCHAR(50) | NOT NULL, UNIQUE | รหัส Intent เช่น RAG_QUERY, GET_RFA | +| description_th | VARCHAR(255) | NOT NULL | คำอธิบายภาษาไทย | +| description_en | VARCHAR(255) | NOT NULL | คำอธิบายภาษาอังกฤษ | +| category | ENUM | NOT NULL | read, suggest, utility | +| is_active | BOOLEAN | NOT NULL, DEFAULT TRUE | สถานะการใช้งาน | +| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | วันที่สร้าง | +| updated_at | TIMESTAMP | NOT NULL, ON UPDATE CURRENT_TIMESTAMP | วันที่แก้ไขล่าสุด | + +**Indexes**: +- PRIMARY KEY (id) +- UNIQUE KEY uk_intent_public_id (public_id) +- UNIQUE KEY uk_intent_code (intent_code) +- INDEX idx_intent_active (is_active, category) + +**Business Rules**: +1. **Intent Categories** — read (ดึงข้อมูล), suggest (แนะนำ), utility (อื่นๆ) +2. **Active Status** — Intent ที่ไม่ active จะไม่ถูกใช้ในการ classify +3. **Seed Data** — 12 Intent Definitions พร้อม patterns v1 (RAG_QUERY, GET_RFA, GET_DRAWING, ฯลฯ) + +--- + +#### 19.4.2 `ai_intent_patterns` + +**วัตถุประสงค์:** เก็บ Patterns (keyword และ regex) สำหรับ Pattern Matching ใน Hybrid Intent Classifier + +| Column Name | Data Type | Constraints | Description | +| ----------- | --------- | ----------- | ----------- | +| id | INT | PRIMARY KEY, AUTO_INCREMENT | Internal PK (ห้าม expose ใน API) | +| public_id | UUID | NOT NULL, UNIQUE, DEFAULT UUID() | UUID Public Identifier (ADR-019) | +| intent_code | VARCHAR(50) | NOT NULL, FK | รหัส Intent (FK to ai_intent_definitions) | +| language | ENUM | NOT NULL, DEFAULT 'any' | th, en, any | +| pattern_type | ENUM | NOT NULL, DEFAULT 'keyword' | keyword, regex | +| pattern_value | VARCHAR(255) | NOT NULL | ค่า pattern (keyword หรือ regex) | +| priority | INT | NOT NULL, DEFAULT 100 | ลำดับความสำคัญ (ยิ่งน้อยยิ่งสำคัญ) | +| is_active | BOOLEAN | NOT NULL, DEFAULT TRUE | สถานะการใช้งาน | +| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | วันที่สร้าง | +| updated_at | TIMESTAMP | NOT NULL, ON UPDATE CURRENT_TIMESTAMP | วันที่แก้ไขล่าสุด | + +**Indexes**: +- PRIMARY KEY (id) +- UNIQUE KEY uk_pattern_public_id (public_id) +- INDEX idx_pattern_intent_code (intent_code) +- INDEX idx_pattern_active_priority (is_active, priority ASC) +- CONSTRAINT fk_intent_pattern_definition FOREIGN KEY (intent_code) REFERENCES ai_intent_definitions(intent_code) ON UPDATE CASCADE ON DELETE RESTRICT + +**Business Rules**: +1. **Pattern Types** — keyword (ตรงตัว), regex (regular expression) +2. **Priority** — ยิ่งน้อยยิ่งสำคัญ (ตัวอย่าง: keyword=10, regex=5) +3. **Language** — th (ไทย), en (อังกฤษ), any (ทุกภาษา) +4. **Seed Data** — ~45 patterns สำหรับ 12 Intents (ยกเว้น FALLBACK) +5. **LLM Fallback** — เมื่อไม่ match pattern ไหนเลย → ใช้ LLM (gemma4:e4b Q8_0) ตาม ADR-023A + +--- + ## **20. 📖 Glossary (คำศัพท์)** - **RFA**: Request for Approval (เอกสารขออนุมัติ) diff --git a/specs/03-Data-and-Storage/README.md b/specs/03-Data-and-Storage/README.md index 38a4da08..85c70364 100644 --- a/specs/03-Data-and-Storage/README.md +++ b/specs/03-Data-and-Storage/README.md @@ -11,28 +11,17 @@ | `lcbp3-v1.9.0-schema-01-drop.sql` | สคริปต์ลบตารางทั้งหมด (ใช้สำหรับ reset schema) | | `lcbp3-v1.9.0-schema-02-tables.sql` | สคริปต์สร้างตารางทั้งหมด (CREATE TABLE) | | `lcbp3-v1.9.0-schema-03-views-indexes.sql` | สคริปต์สร้าง Views และ Indexes | -| `lcbp3-v1.9.0-migration.sql` | สคริปต์ migration สำหรับการอัปเกรดจากเวอร์ชันก่อนหน้า | -| `lcbp3-v1.9.0-rfa-approval-schema.sql` | Schema เฉพาะสำหรับระบบ RFA Approval System | +| `lcbp3-v1.9.0-migration.sql` | สคริปต์ migration support tables สำหรับ n8n Migration Workflow (temporary - ลบได้หลัง migration เสร็จ) | ### Seed Files (ข้อมูลเริ่มต้น) | ไฟล์ | คำอธิบาย | |------|-----------| -| `lcbp3-v1.9.0-seed-basic.sql` | ข้อมูลเริ่มต้นพื้นฐาน (Organizations, Users, Roles, Permissions) | +| `lcbp3-v1.9.0-seed-basic.sql` | ข้อมูลเริ่มต้นพื้นฐาน (Organizations, Users, Roles, Permissions, Intent Classification, Workflow Definitions) | | `lcbp3-v1.9.0-seed-permissions.sql` | ข้อมูล RBAC Permissions ตาม ADR-016 | | `lcbp3-v1.9.0-seed-contractdrawing.sql` | ข้อมูล Contract Drawings ตัวอย่าง | | `lcbp3-v1.9.0-seed-shopdrawing.sql` | ข้อมูล Shop Drawings ตัวอย่าง | -### Delta Files (การเปลี่ยนแปลง Schema แบบ Incremental) - -ตั้งอยู่ใน `deltas/` - เก็บ SQL delta สำหรับการเปลี่ยนแปลง schema ตาม ADR-009 (ไม่ใช้ TypeORM migrations) - -| ไฟล์ | คำอธิบาย | -|------|-----------| -| `12-unified-ai-architecture.sql` | เพิ่มตาราง AI: migration_review_queue, ai_audit_logs (ADR-023) | -| `14-add-migration-review-queue.sql` | เพิ่มคอลัมน์ใหม่ใน migration_review_queue (ADR-023A) | -| `15-add-ai-processing-status.sql` | เพิ่ม ai_processing_status ใน attachments (ADR-023A) | - ### Documentation | ไฟล์ | คำอธิบาย | @@ -81,13 +70,11 @@ mysql < lcbp3-v1.9.0-seed-shopdrawing.sql ### การอัปเกรดจากเวอร์ชันก่อนหน้า ```bash -# รัน migration script +# รัน migration script (สำหรับ n8n Migration Workflow เท่านั้น) mysql < lcbp3-v1.9.0-migration.sql -# รัน delta files ที่ยังไม่ได้ใช้ (ตามลำดับเลข) -mysql < deltas/12-unified-ai-architecture.sql -mysql < deltas/14-add-migration-review-queue.sql -mysql < deltas/15-add-ai-processing-status.sql +# หมายเหตุ: ทุกการเปลี่ยนแปลง schema ได้ถูกรวมเข้า schema-02-tables.sql และ seed files แล้ว +# ไม่มี delta files ที่ต้องรันแยกตาม ADR-009 ``` ## 🔗 เอกสารที่เกี่ยวข้อง @@ -99,6 +86,7 @@ mysql < deltas/15-add-ai-processing-status.sql - **ADR-019**: Hybrid Identifier Strategy - UUID Strategy - **ADR-023**: Unified AI Architecture - สถาปัตยกรรม AI หลัก - **ADR-023A**: Unified AI Architecture (Model Revision) - อัปเดตโมเดล AI +- **ADR-024**: Intent Classification Strategy - Hybrid Intent Classifier (Pattern Match + LLM Fallback) ### Engineering Guidelines @@ -115,6 +103,16 @@ mysql < deltas/15-add-ai-processing-status.sql ## 📝 Change Log +- **2026-05-19**: + - เพิ่ม Intent Classification tables (ai_intent_definitions, ai_intent_patterns) ตาม ADR-024 + - รวม delta files (16-add-intent-classification.sql, 17-seed-intent-patterns.sql) เข้า schema-02-tables.sql และ seed-basic.sql + - ลบ rfa-approval-schema.sql (ตารางทั้งหมดถูกรวมเข้า schema-02-tables.sql แล้ว) + - ลบ redundant delta files (12, 14, 15) - ตารางและคอลัมน์ทั้งหมดถูกรวมเข้า schema-02-tables.sql แล้ว + - รวม delta files ที่เหลือ (13 ไฟล์) เข้า schema-02-tables.sql, seed-permissions.sql, และ seed-basic.sql: + - Schema: rag_status, rag_last_error (attachments), document_chunks table + - Seed: RAG permissions, RBAC bulk permission, CIRCULATION_FLOW_V1 workflow definition + - อัปเดต Data Dictionary ด้วย document_chunks table + - ลบ deltas/ directory ทั้งหมด (ตาม ADR-009 - รวมเข้า main schema/seed เสร็จแล้ว) - **2026-05-15**: เพิ่ม AI-related tables (migration_review_queue, ai_audit_logs) และ ai_processing_status column ตาม ADR-023A - **2026-05-14**: อัปเดต schema เป็น v1.9.0 เพื่อรองรับ RFA Approval System และ Unified AI Architecture diff --git a/specs/03-Data-and-Storage/deltas/01-add-reference-date.sql b/specs/03-Data-and-Storage/deltas/01-add-reference-date.sql deleted file mode 100644 index 98ba1b43..00000000 --- a/specs/03-Data-and-Storage/deltas/01-add-reference-date.sql +++ /dev/null @@ -1,4 +0,0 @@ -ALTER TABLE `attachments` -ADD COLUMN `reference_date` DATE NULL COMMENT 'Date used for folder structure (e.g. Issue Date) to prevent broken paths'; -ALTER TABLE `attachments` -ADD INDEX `idx_attachments_reference_date` (`reference_date`); \ No newline at end of file diff --git a/specs/03-Data-and-Storage/deltas/02-add-rbac-bulk-permission.sql b/specs/03-Data-and-Storage/deltas/02-add-rbac-bulk-permission.sql deleted file mode 100644 index 597c4459..00000000 --- a/specs/03-Data-and-Storage/deltas/02-add-rbac-bulk-permission.sql +++ /dev/null @@ -1,12 +0,0 @@ --- Add permission for Bulk RBAC Update --- Fix: Use existing 'user.manage_assignments' instead of creating new invalid permission --- This permission (ID 25) is for assigning roles/projects --- Grant to ADMIN (ID 2) and DC (ID 3) roles if not already present --- Use INSERT IGNORE to avoid duplicates -INSERT IGNORE INTO `role_permissions` (`role_id`, `permission_id`) -SELECT r.role_id, - p.permission_id -FROM `roles` r, - `permissions` p -WHERE r.role_name IN ('ADMIN', 'Org Admin', 'DC', 'Document Control') - AND p.permission_name = 'user.manage_assignments'; \ No newline at end of file diff --git a/specs/03-Data-and-Storage/deltas/03-fix-numbering-enums.sql b/specs/03-Data-and-Storage/deltas/03-fix-numbering-enums.sql deleted file mode 100644 index bb8c2ac4..00000000 --- a/specs/03-Data-and-Storage/deltas/03-fix-numbering-enums.sql +++ /dev/null @@ -1,30 +0,0 @@ --- Delta 03: Fix ENUM mismatches in document_number_audit and document_number_errors --- Issue: 'GENERATE' operation used by backend but not in DB ENUM → INSERT fails → correspondence creation blocked --- Date: 2026-03-19 --- Applies to: lcbp3-v1.8.0-schema-02-tables.sql - --- 1. Add 'VOID' and 'GENERATE' to document_number_audit.operation ENUM -ALTER TABLE document_number_audit - MODIFY COLUMN operation ENUM( - 'RESERVE', - 'CONFIRM', - 'MANUAL_OVERRIDE', - 'VOID_REPLACE', - 'CANCEL', - 'VOID', - 'GENERATE' - ) NOT NULL DEFAULT 'CONFIRM' COMMENT 'ประเภทการดำเนินการ'; - --- 2. Add missing error_type values to document_number_errors -ALTER TABLE document_number_errors - MODIFY COLUMN error_type ENUM( - 'LOCK_TIMEOUT', - 'VERSION_CONFLICT', - 'DB_ERROR', - 'REDIS_ERROR', - 'VALIDATION_ERROR', - 'SEQUENCE_EXHAUSTED', - 'RESERVATION_EXPIRED', - 'DUPLICATE_NUMBER', - 'GENERATE_ERROR' - ) NOT NULL COMMENT 'ประเภท error (9 types)'; diff --git a/specs/03-Data-and-Storage/deltas/04-add-workflow-history-id-to-attachments.sql b/specs/03-Data-and-Storage/deltas/04-add-workflow-history-id-to-attachments.sql deleted file mode 100644 index daab750d..00000000 --- a/specs/03-Data-and-Storage/deltas/04-add-workflow-history-id-to-attachments.sql +++ /dev/null @@ -1,25 +0,0 @@ --- ============================================================ --- Delta 04: ADR-021 — Step-specific Attachments --- เพิ่ม FK workflow_history_id ใน attachments table --- ============================================================ --- ข้อควรระวัง: ค่า NULL = ไฟล์แนบหลัก (Main Document) --- ค่าไม่ NULL = ไฟล์ประจำ Workflow Step นั้น - -ALTER TABLE attachments - ADD COLUMN workflow_history_id CHAR(36) NULL - COMMENT 'FK to workflow_histories.id สำหรับไฟล์แนบประจำ Step (ADR-021). NULL = ไฟล์แนบหลัก', - ADD CONSTRAINT fk_attachments_workflow_history - FOREIGN KEY (workflow_history_id) - REFERENCES workflow_histories (id) - ON DELETE SET NULL - ON UPDATE CASCADE; - --- Index สำหรับ optimize การดึงไฟล์แนบตาม Step + เรียงตามวันที่ -CREATE INDEX idx_att_wfhist_created - ON attachments (workflow_history_id, created_at); - --- ============================================================ --- Rollback: --- ALTER TABLE attachments DROP FOREIGN KEY fk_attachments_workflow_history; --- ALTER TABLE attachments DROP COLUMN workflow_history_id; --- ============================================================ diff --git a/specs/03-Data-and-Storage/deltas/05-add-circulation-deadline.sql b/specs/03-Data-and-Storage/deltas/05-add-circulation-deadline.sql deleted file mode 100644 index 7230c774..00000000 --- a/specs/03-Data-and-Storage/deltas/05-add-circulation-deadline.sql +++ /dev/null @@ -1,13 +0,0 @@ --- Delta 05: Add deadline_date to circulations (v1.8.7 — EC-CIRC-003) --- Purpose: เพิ่มคอลัมน์ deadline_date ที่ตาราง circulations --- เพื่อรองรับ EC-CIRC-003 (Overdue Badge) และการตั้งค่ากำหนดเวลา --- Applied: เพิ่มทีหลัง Schema v1.8.0 --- Author: NAP-DMS v1.8.7 - -ALTER TABLE circulations - ADD COLUMN deadline_date DATE NULL - COMMENT 'วันครบกำหนดส่งงาน (nullable — ถ้า NULL = ไม่มีกำหนด)' - AFTER closed_at; - --- Index สำหรับ query Overdue Circulations ที่ Dashboard -CREATE INDEX idx_circulations_deadline ON circulations (deadline_date); diff --git a/specs/03-Data-and-Storage/deltas/06-add-circulation-workflow-definition.sql b/specs/03-Data-and-Storage/deltas/06-add-circulation-workflow-definition.sql deleted file mode 100644 index 1a1b9c4b..00000000 --- a/specs/03-Data-and-Storage/deltas/06-add-circulation-workflow-definition.sql +++ /dev/null @@ -1,87 +0,0 @@ --- ========================================================== --- Delta 06: Add CIRCULATION_FLOW_V1 Workflow Definition --- ========================================================== --- Purpose : สร้าง Workflow Definition สำหรับใบเวียนภายใน (Circulation) --- Required : ก่อน delta นี้ ตาราง workflow_definitions ต้องมีอยู่แล้ว (ADR-001) --- Renamed : CIRCULATION_INTERNAL_V1 → CIRCULATION_FLOW_V1 (ตาม naming convention) --- States : --- DRAFT (initial) → START → ROUTING --- ROUTING → COMPLETE → COMPLETED (terminal) --- ROUTING → FORCE_CLOSE → CANCELLED (terminal) --- ========================================================== - -INSERT INTO `workflow_definitions` ( - `id`, - `workflow_code`, - `version`, - `description`, - `dsl`, - `compiled`, - `is_active`, - `created_at`, - `updated_at` - ) -VALUES ( - UUID(), - 'CIRCULATION_FLOW_V1', - 1, - 'Circulation Workflow — DRAFT → ROUTING → COMPLETED | CANCELLED', - JSON_OBJECT( - 'workflow', 'CIRCULATION_FLOW_V1', - 'version', 1, - 'states', JSON_ARRAY( - JSON_OBJECT( - 'name', 'DRAFT', - 'initial', TRUE, - 'on', JSON_OBJECT( - 'START', JSON_OBJECT('to', 'ROUTING') - ) - ), - JSON_OBJECT( - 'name', 'ROUTING', - 'on', JSON_OBJECT( - 'COMPLETE', JSON_OBJECT('to', 'COMPLETED'), - 'FORCE_CLOSE', JSON_OBJECT('to', 'CANCELLED') - ) - ), - JSON_OBJECT('name', 'COMPLETED', 'terminal', TRUE), - JSON_OBJECT('name', 'CANCELLED', 'terminal', TRUE) - ) - ), - JSON_OBJECT( - 'initialState', 'DRAFT', - 'states', JSON_OBJECT( - 'DRAFT', JSON_OBJECT( - 'initial', TRUE, - 'terminal', FALSE, - 'transitions', JSON_OBJECT( - 'START', JSON_OBJECT('to', 'ROUTING', 'events', JSON_ARRAY()) - ) - ), - 'ROUTING', JSON_OBJECT( - 'initial', FALSE, - 'terminal', FALSE, - 'transitions', JSON_OBJECT( - 'COMPLETE', JSON_OBJECT('to', 'COMPLETED', 'events', JSON_ARRAY()), - 'FORCE_CLOSE', JSON_OBJECT('to', 'CANCELLED', 'events', JSON_ARRAY()) - ) - ), - 'COMPLETED', JSON_OBJECT( - 'initial', FALSE, - 'terminal', TRUE, - 'transitions', JSON_OBJECT() - ), - 'CANCELLED', JSON_OBJECT( - 'initial', FALSE, - 'terminal', TRUE, - 'transitions', JSON_OBJECT() - ) - ) - ), - TRUE, - NOW(), - NOW() - ); - --- Verify --- SELECT workflow_code, version, is_active FROM workflow_definitions WHERE workflow_code = 'CIRCULATION_FLOW_V1'; diff --git a/specs/03-Data-and-Storage/deltas/07-add-contract-id-to-workflow-instances.sql b/specs/03-Data-and-Storage/deltas/07-add-contract-id-to-workflow-instances.sql deleted file mode 100644 index c8f71d86..00000000 --- a/specs/03-Data-and-Storage/deltas/07-add-contract-id-to-workflow-instances.sql +++ /dev/null @@ -1,22 +0,0 @@ --- ========================================================== --- Delta 07: Add contract_id to workflow_instances (C3 Contract Scoping) --- ========================================================== --- Purpose : เพิ่ม contract_id FK ใน workflow_instances เพื่อให้ Workflow Engine --- แยก scope ตาม Contract ได้ (C3 ตาม analysis ADR-021) --- Why : RFA / Correspondence / Transmittal → contract-scoped (contractId ถูกตั้ง) --- Circulation → organization-scoped (contractId = NULL, ใช้ Level 2 org check) --- Guard Level 2.5 ตรวจ contract_organizations membership เฉพาะ contractId ≠ NULL --- ADR : ADR-009 (no migrations — direct SQL only) --- ========================================================== -ALTER TABLE workflow_instances -ADD COLUMN contract_id INT NULL COMMENT 'Contract ที่ Workflow นี้เป็นส่วนหนึ่ง (NULL = global/legacy)' -AFTER definition_id, - ADD CONSTRAINT fk_wf_inst_contract FOREIGN KEY (contract_id) REFERENCES contracts (id) ON DELETE -SET NULL; - --- Index สำหรับ Guard lookup: "Instances ทั้งหมดในสัญญา X" -CREATE INDEX idx_wf_inst_contract ON workflow_instances (contract_id, entity_type, STATUS); - --- Verify --- DESCRIBE workflow_instances; --- SHOW INDEX FROM workflow_instances WHERE Key_name = 'idx_wf_inst_contract'; diff --git a/specs/03-Data-and-Storage/deltas/08-add-rag-status-to-attachments.sql b/specs/03-Data-and-Storage/deltas/08-add-rag-status-to-attachments.sql deleted file mode 100644 index e8294f9b..00000000 --- a/specs/03-Data-and-Storage/deltas/08-add-rag-status-to-attachments.sql +++ /dev/null @@ -1,11 +0,0 @@ --- Delta 08: ADR-022 RAG — เพิ่ม rag_status และ rag_last_error ในตาราง attachments --- Apply: 2026-04-19 --- Ref: specs/08-Tasks/ADR-022-Retrieval-Augmented-Generation/data-model.md §1.1 - -ALTER TABLE attachments - ADD COLUMN rag_status ENUM('PENDING', 'PROCESSING', 'INDEXED', 'FAILED') - NOT NULL DEFAULT 'PENDING' - COMMENT 'สถานะ RAG ingestion ระดับ file', - ADD COLUMN rag_last_error TEXT NULL - COMMENT 'Error message ล่าสุดเมื่อ rag_status = FAILED', - ADD INDEX idx_attachments_rag_status (rag_status); diff --git a/specs/03-Data-and-Storage/deltas/08b-create-document-chunks.sql b/specs/03-Data-and-Storage/deltas/08b-create-document-chunks.sql deleted file mode 100644 index 94a11463..00000000 --- a/specs/03-Data-and-Storage/deltas/08b-create-document-chunks.sql +++ /dev/null @@ -1,25 +0,0 @@ --- Delta 08b: ADR-022 RAG — สร้างตาราง document_chunks สำหรับเก็บ vector metadata --- Apply: 2026-04-19 --- Ref: specs/08-Tasks/ADR-022-Retrieval-Augmented-Generation/data-model.md §1.2 - -CREATE TABLE document_chunks ( - id CHAR(36) NOT NULL PRIMARY KEY COMMENT 'UUID = Qdrant point ID', - document_id CHAR(36) NOT NULL COMMENT 'FK → attachments.public_id (UUIDv7)', - chunk_index INT NOT NULL COMMENT 'ลำดับ chunk ภายใน document', - content TEXT NOT NULL COMMENT 'เนื้อหา chunk หลัง PyThaiNLP normalize', - doc_type VARCHAR(20) NOT NULL COMMENT 'CORR, RFA, DRAWING, CONTRACT, RPT, TRANS', - doc_number VARCHAR(100) NULL COMMENT 'หมายเลขเอกสาร เช่น REF-2026-001', - revision VARCHAR(20) NULL COMMENT 'Revision เช่น Rev.A', - project_code VARCHAR(50) NOT NULL COMMENT 'รหัสโครงการ (ใช้ filter)', - project_public_id CHAR(36) NOT NULL COMMENT 'UUIDv7 ของโครงการ (Qdrant tenant key)', - version VARCHAR(20) NULL COMMENT 'เวอร์ชันเอกสาร เช่น 1.0, 2.1 (ถ้ามี)', - classification ENUM('PUBLIC', 'INTERNAL', 'CONFIDENTIAL') - NOT NULL DEFAULT 'INTERNAL', - embedding_model VARCHAR(100) NOT NULL DEFAULT 'nomic-embed-text', - created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), - - INDEX idx_chunks_document_id (document_id), - INDEX idx_chunks_doc_number_rev (doc_number, revision), - INDEX idx_chunks_project (project_public_id), - FULLTEXT INDEX ft_chunks_content (content) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; diff --git a/specs/03-Data-and-Storage/deltas/08c-seed-rag-permissions.sql b/specs/03-Data-and-Storage/deltas/08c-seed-rag-permissions.sql deleted file mode 100644 index 2e0d78bf..00000000 --- a/specs/03-Data-and-Storage/deltas/08c-seed-rag-permissions.sql +++ /dev/null @@ -1,8 +0,0 @@ --- Delta 08c: ADR-022 RAG — เพิ่ม permissions สำหรับ RAG feature --- Apply: 2026-04-19 --- Ref: specs/08-Tasks/ADR-022-Retrieval-Augmented-Generation/tasks.md T014 - -INSERT IGNORE INTO permissions (permission_name, description, module, created_at, updated_at) -VALUES - ('rag.query', 'ใช้งาน RAG Q&A เพื่อค้นหาคำตอบจากเอกสาร', 'rag', NOW(), NOW()), - ('rag.manage', 'จัดการ RAG ingestion, re-index, ลบ vectors', 'rag', NOW(), NOW()); diff --git a/specs/03-Data-and-Storage/deltas/09-add-version-no-to-workflow-instances.sql b/specs/03-Data-and-Storage/deltas/09-add-version-no-to-workflow-instances.sql deleted file mode 100644 index 1af41198..00000000 --- a/specs/03-Data-and-Storage/deltas/09-add-version-no-to-workflow-instances.sql +++ /dev/null @@ -1,17 +0,0 @@ --- ============================================================ --- Delta 09: ADR-001 v1.1 — Optimistic Lock for Workflow Transitions --- เพิ่ม version_no ใน workflow_instances สำหรับ Optimistic Concurrency Control --- ============================================================ --- Feature: 003-unified-workflow-engine (FR-002) --- Date: 2026-05-03 --- ข้อควรระวัง: Existing rows จะได้ค่า DEFAULT 1 อัตโนมัติ — ไม่มี Data Loss --- Rollback: ALTER TABLE workflow_instances DROP INDEX idx_wf_inst_version; --- ALTER TABLE workflow_instances DROP COLUMN version_no; - -ALTER TABLE workflow_instances - ADD COLUMN version_no INT NOT NULL DEFAULT 1 - COMMENT 'Optimistic lock counter — incremented on every successful transition (ADR-001 v1.1 FR-002). Client sends current value; server rejects with 409 if mismatch.'; - --- Index เพื่อรองรับ CAS check: WHERE id = ? AND version_no = ? -CREATE INDEX idx_wf_inst_version - ON workflow_instances (id, version_no); diff --git a/specs/03-Data-and-Storage/deltas/10-add-action-by-user-uuid-to-workflow-histories.sql b/specs/03-Data-and-Storage/deltas/10-add-action-by-user-uuid-to-workflow-histories.sql deleted file mode 100644 index fa3a4f2a..00000000 --- a/specs/03-Data-and-Storage/deltas/10-add-action-by-user-uuid-to-workflow-histories.sql +++ /dev/null @@ -1,14 +0,0 @@ --- ============================================================ --- Delta 10: ADR-001 v1.1 / ADR-019 UUID Compliance --- เพิ่ม action_by_user_uuid ใน workflow_histories --- เพื่อ expose User identity ผ่าน API โดยไม่ต้องเปิดเผย INT PK (ADR-019) --- ============================================================ --- Feature: 003-unified-workflow-engine (FR-003) --- Date: 2026-05-03 --- ข้อควรระวัง: NULL สำหรับ Historical records ที่สร้างก่อน delta นี้ — เป็น Acceptable --- NULL ในบริบทนี้ = "System Action" หรือ "Pre-migration record" --- Rollback: ALTER TABLE workflow_histories DROP COLUMN action_by_user_uuid; - -ALTER TABLE workflow_histories - ADD COLUMN action_by_user_uuid VARCHAR(36) NULL - COMMENT 'UUID ของ User ผู้ดำเนินการ — ใช้ใน API Response แทน INT FK (ADR-019). NULL = System Action หรือ Pre-migration record'; diff --git a/specs/03-Data-and-Storage/deltas/11-add-uuid-to-roles.sql b/specs/03-Data-and-Storage/deltas/11-add-uuid-to-roles.sql deleted file mode 100644 index f706e5fc..00000000 --- a/specs/03-Data-and-Storage/deltas/11-add-uuid-to-roles.sql +++ /dev/null @@ -1,25 +0,0 @@ --- ============================================================================= --- Delta 11: เพิ่ม uuid column ให้ roles table --- ============================================================================= --- เหตุผล: roles ไม่มี uuid column ทำให้ distribution_recipients ไม่สามารถ --- อ้างอิง ROLE type ด้วย publicId ได้ตาม ADR-019 --- ใช้ใน: distribution_recipients.recipient_public_id (recipient_type = 'ROLE') --- ADR: ADR-019 (Hybrid Identifier Strategy) --- Feature: v1.9.0 RFA Approval Refactor (1-rfa-approval-refactor) --- Created: 2026-05-13 --- ============================================================================= - -ALTER TABLE `roles` - ADD COLUMN `uuid` UUID NOT NULL DEFAULT (UUID()) - COMMENT 'UUID Public Identifier (ADR-019) — ใช้ใน API Response แทน role_id' - AFTER `role_id`; - --- สร้าง Unique Index สำหรับ uuid -CREATE UNIQUE INDEX `idx_roles_uuid` ON `roles` (`uuid`); - --- ============================================================================= --- หมายเหตุ: หลัง Apply delta นี้แล้ว --- - roles ที่มีอยู่แล้วจะได้ uuid อัตโนมัติจาก DEFAULT (UUID()) --- - distribution_recipients.recipient_public_id (type=ROLE) ให้ใช้ roles.uuid --- - TypeORM Entity: เพิ่ม @Column({ unique: true }) uuid: string; ใน RoleEntity --- ============================================================================= diff --git a/specs/03-Data-and-Storage/deltas/12-unified-ai-architecture.sql b/specs/03-Data-and-Storage/deltas/12-unified-ai-architecture.sql deleted file mode 100644 index 784ba160..00000000 --- a/specs/03-Data-and-Storage/deltas/12-unified-ai-architecture.sql +++ /dev/null @@ -1,88 +0,0 @@ --- File: specs/03-Data-and-Storage/deltas/12-unified-ai-architecture.sql --- Change Log --- - 2026-05-14: เพิ่ม schema delta สำหรับ ADR-023 Unified AI Architecture. --- ADR-009: ใช้ SQL delta โดยตรง ห้ามใช้ TypeORM migration - -SET NAMES utf8mb4; - -CREATE TABLE IF NOT EXISTS migration_review_queue ( - id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'Internal PK (ห้าม expose ใน API)', - uuid UUID NOT NULL DEFAULT UUID() COMMENT 'UUID Public Identifier (ADR-019)', - batch_id VARCHAR(100) NOT NULL COMMENT 'Batch ingestion identifier', - original_file_name VARCHAR(255) NOT NULL COMMENT 'Original uploaded legacy filename', - source_attachment_public_id UUID NULL COMMENT 'Temp attachment publicId from two-phase upload', - temp_attachment_id INT NULL COMMENT 'Internal temp attachment id used during commit only', - extracted_metadata JSON NULL COMMENT 'AI extracted metadata before human validation', - confidence_score DECIMAL(4, 3) NULL COMMENT 'Overall AI confidence score 0.000-1.000', - status ENUM('PENDING', 'IMPORTED', 'REJECTED') NOT NULL DEFAULT 'PENDING', - error_reason TEXT NULL COMMENT 'Reason when AI processing rejected the record', - version INT NOT NULL DEFAULT 1 COMMENT 'Optimistic locking version', - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - UNIQUE KEY idx_migration_review_uuid (uuid), - KEY idx_migration_review_batch (batch_id), - KEY idx_migration_review_status (status) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ADR-023 AI migration review staging queue'; - -ALTER TABLE migration_review_queue - ADD COLUMN IF NOT EXISTS uuid UUID NOT NULL DEFAULT UUID() COMMENT 'UUID Public Identifier (ADR-019)', - ADD COLUMN IF NOT EXISTS batch_id VARCHAR(100) NULL COMMENT 'Batch ingestion identifier', - ADD COLUMN IF NOT EXISTS original_file_name VARCHAR(255) NULL COMMENT 'Original uploaded legacy filename', - ADD COLUMN IF NOT EXISTS source_attachment_public_id UUID NULL COMMENT 'Temp attachment publicId from two-phase upload', - ADD COLUMN IF NOT EXISTS temp_attachment_id INT NULL COMMENT 'Internal temp attachment id used during commit only', - ADD COLUMN IF NOT EXISTS extracted_metadata JSON NULL COMMENT 'AI extracted metadata before human validation', - ADD COLUMN IF NOT EXISTS confidence_score DECIMAL(4, 3) NULL COMMENT 'Overall AI confidence score 0.000-1.000', - ADD COLUMN IF NOT EXISTS error_reason TEXT NULL COMMENT 'Reason when AI processing rejected the record', - ADD COLUMN IF NOT EXISTS version INT NOT NULL DEFAULT 1 COMMENT 'Optimistic locking version', - ADD COLUMN IF NOT EXISTS updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP; - -ALTER TABLE migration_review_queue - MODIFY COLUMN status ENUM('PENDING', 'APPROVED', 'IMPORTED', 'REJECTED') NOT NULL DEFAULT 'PENDING'; - -CREATE UNIQUE INDEX IF NOT EXISTS idx_migration_review_uuid ON migration_review_queue (uuid); -CREATE INDEX IF NOT EXISTS idx_migration_review_batch ON migration_review_queue (batch_id); -CREATE INDEX IF NOT EXISTS idx_migration_review_status ON migration_review_queue (status); - -CREATE TABLE IF NOT EXISTS ai_audit_logs ( - id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'Internal PK (ห้าม expose ใน API)', - uuid UUID NOT NULL DEFAULT UUID() COMMENT 'UUID Public Identifier (ADR-019)', - document_public_id UUID NULL COMMENT 'Imported document publicId when available', - ai_model VARCHAR(50) NOT NULL DEFAULT 'gemma4' COMMENT 'Legacy AI model column used by current gateway service', - model_name VARCHAR(100) NOT NULL COMMENT 'Local model name used by ADR-023 AI pipeline', - ai_suggestion_json JSON NULL COMMENT 'AI suggested metadata', - human_override_json JSON NULL COMMENT 'Human approved or overridden metadata', - processing_time_ms INT NULL COMMENT 'Legacy processing duration field', - confidence_score DECIMAL(4, 3) NULL COMMENT 'AI confidence score 0.000-1.000', - input_hash VARCHAR(64) NULL COMMENT 'Legacy SHA-256 input hash', - output_hash VARCHAR(64) NULL COMMENT 'Legacy SHA-256 output hash', - status ENUM('SUCCESS', 'FAILED', 'TIMEOUT') NOT NULL DEFAULT 'SUCCESS' COMMENT 'Legacy processing status field', - error_message TEXT NULL COMMENT 'Legacy processing error field', - confirmed_by_user_id INT NULL COMMENT 'Internal users.user_id that confirmed the record', - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - UNIQUE KEY idx_ai_audit_logs_uuid (uuid), - KEY idx_ai_audit_document (document_public_id), - KEY idx_ai_audit_model (ai_model), - KEY idx_ai_audit_model_name (model_name), - KEY idx_ai_audit_status (status), - KEY idx_ai_audit_confirmed_by (confirmed_by_user_id), - CONSTRAINT fk_ai_audit_confirmed_by_user FOREIGN KEY (confirmed_by_user_id) REFERENCES users (user_id) ON DELETE SET NULL -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ADR-023 AI development feedback log'; - -ALTER TABLE ai_audit_logs - ADD COLUMN IF NOT EXISTS ai_model VARCHAR(50) NOT NULL DEFAULT 'gemma4' COMMENT 'Legacy AI model column used by current gateway service', - ADD COLUMN IF NOT EXISTS model_name VARCHAR(100) NULL COMMENT 'Local model name used by ADR-023 AI pipeline', - ADD COLUMN IF NOT EXISTS ai_suggestion_json JSON NULL COMMENT 'AI suggested metadata', - ADD COLUMN IF NOT EXISTS human_override_json JSON NULL COMMENT 'Human approved or overridden metadata', - ADD COLUMN IF NOT EXISTS processing_time_ms INT NULL COMMENT 'Legacy processing duration field', - ADD COLUMN IF NOT EXISTS input_hash VARCHAR(64) NULL COMMENT 'Legacy SHA-256 input hash', - ADD COLUMN IF NOT EXISTS output_hash VARCHAR(64) NULL COMMENT 'Legacy SHA-256 output hash', - ADD COLUMN IF NOT EXISTS status ENUM('SUCCESS', 'FAILED', 'TIMEOUT') NOT NULL DEFAULT 'SUCCESS' COMMENT 'Legacy processing status field', - ADD COLUMN IF NOT EXISTS error_message TEXT NULL COMMENT 'Legacy processing error field', - ADD COLUMN IF NOT EXISTS confirmed_by_user_id INT NULL COMMENT 'Internal users.user_id that confirmed the record'; - -UPDATE ai_audit_logs -SET model_name = ai_model -WHERE model_name IS NULL AND ai_model IS NOT NULL; - -CREATE INDEX IF NOT EXISTS idx_ai_audit_model_name ON ai_audit_logs (model_name); -CREATE INDEX IF NOT EXISTS idx_ai_audit_confirmed_by ON ai_audit_logs (confirmed_by_user_id); diff --git a/specs/03-Data-and-Storage/deltas/14-add-migration-review-queue.sql b/specs/03-Data-and-Storage/deltas/14-add-migration-review-queue.sql deleted file mode 100644 index f21bde4e..00000000 --- a/specs/03-Data-and-Storage/deltas/14-add-migration-review-queue.sql +++ /dev/null @@ -1,56 +0,0 @@ --- File: specs/03-Data-and-Storage/deltas/14-add-migration-review-queue.sql --- Change Log --- - 2026-05-15: เพิ่ม delta สำหรับ migration_review_queue ตาม ADR-023A โดยไม่ลบ/rename column เดิม. --- ADR-009: ใช้ SQL delta โดยตรง ห้ามใช้ TypeORM migration - -SET NAMES utf8mb4; - -CREATE TABLE IF NOT EXISTS migration_review_queue ( - id INT NOT NULL AUTO_INCREMENT COMMENT 'Internal PK (ห้าม expose ใน API)', - uuid UUID NOT NULL DEFAULT UUID() COMMENT 'UUID Public Identifier (ADR-019)', - batch_id VARCHAR(100) NOT NULL COMMENT 'n8n batch identifier', - idempotency_key VARCHAR(200) NOT NULL COMMENT 'Idempotency-Key สำหรับป้องกัน queue ซ้ำ', - original_filename VARCHAR(500) NOT NULL COMMENT 'ชื่อไฟล์ต้นฉบับจาก legacy source', - storage_temp_path VARCHAR(1000) NOT NULL COMMENT 'temp storage path ก่อน import', - ai_metadata_json JSON NOT NULL COMMENT 'AI suggestion payload เต็มสำหรับ human review', - confidence_score DECIMAL(5, 4) NOT NULL COMMENT 'AI confidence score 0.0000-1.0000', - ocr_used TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'ระบุว่าใช้ OCR path หรือไม่', - status ENUM('PENDING', 'IMPORTED', 'REJECTED') NOT NULL DEFAULT 'PENDING', - reviewed_by INT NULL COMMENT 'Internal users.user_id ของผู้ review', - reviewed_at DATETIME NULL COMMENT 'เวลาที่ review record', - rejection_reason VARCHAR(500) NULL COMMENT 'เหตุผลเมื่อ reject', - created_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - PRIMARY KEY (id), - UNIQUE KEY uq_migration_review_uuid (uuid), - UNIQUE KEY uq_migration_review_idempotency (idempotency_key), - KEY idx_migration_review_status_created (status, created_at), - KEY idx_migration_review_batch (batch_id), - KEY idx_migration_review_reviewed_by (reviewed_by) -) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ADR-023A AI migration review staging queue'; - -ALTER TABLE migration_review_queue - ADD COLUMN IF NOT EXISTS idempotency_key VARCHAR(200) NULL COMMENT 'Idempotency-Key สำหรับป้องกัน queue ซ้ำ', - ADD COLUMN IF NOT EXISTS original_filename VARCHAR(500) NULL COMMENT 'ชื่อไฟล์ต้นฉบับจาก legacy source', - ADD COLUMN IF NOT EXISTS storage_temp_path VARCHAR(1000) NULL COMMENT 'temp storage path ก่อน import', - ADD COLUMN IF NOT EXISTS ai_metadata_json JSON NULL COMMENT 'AI suggestion payload เต็มสำหรับ human review', - ADD COLUMN IF NOT EXISTS ocr_used TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'ระบุว่าใช้ OCR path หรือไม่', - ADD COLUMN IF NOT EXISTS reviewed_by INT NULL COMMENT 'Internal users.user_id ของผู้ review', - ADD COLUMN IF NOT EXISTS reviewed_at DATETIME NULL COMMENT 'เวลาที่ review record', - ADD COLUMN IF NOT EXISTS rejection_reason VARCHAR(500) NULL COMMENT 'เหตุผลเมื่อ reject'; - -UPDATE migration_review_queue -SET - idempotency_key = COALESCE(idempotency_key, CONCAT(batch_id, ':', uuid)), - original_filename = COALESCE(original_filename, original_file_name), - ai_metadata_json = COALESCE(ai_metadata_json, extracted_metadata), - rejection_reason = COALESCE(rejection_reason, error_reason) -WHERE idempotency_key IS NULL - OR original_filename IS NULL - OR ai_metadata_json IS NULL - OR rejection_reason IS NULL; - -CREATE UNIQUE INDEX IF NOT EXISTS uq_migration_review_idempotency ON migration_review_queue (idempotency_key); -CREATE INDEX IF NOT EXISTS idx_migration_review_status_created ON migration_review_queue (status, created_at); -CREATE INDEX IF NOT EXISTS idx_migration_review_batch ON migration_review_queue (batch_id); -CREATE INDEX IF NOT EXISTS idx_migration_review_reviewed_by ON migration_review_queue (reviewed_by); diff --git a/specs/03-Data-and-Storage/deltas/15-add-ai-processing-status.sql b/specs/03-Data-and-Storage/deltas/15-add-ai-processing-status.sql deleted file mode 100644 index 95651681..00000000 --- a/specs/03-Data-and-Storage/deltas/15-add-ai-processing-status.sql +++ /dev/null @@ -1,14 +0,0 @@ --- File: specs/03-Data-and-Storage/deltas/15-add-ai-processing-status.sql --- Change Log --- - 2026-05-15: เพิ่มสถานะประมวลผล AI สำหรับเอกสารตาม ADR-023A FR-018. --- ADR-009: ใช้ SQL delta โดยตรง ห้ามใช้ TypeORM migration - -SET NAMES utf8mb4; - --- หมายเหตุ: schema v1.9.0 ยังไม่มีตาราง documents กลาง จึงเพิ่มให้ตาราง attachments --- ซึ่งเป็นตารางไฟล์เอกสารรวมที่มีอยู่จริงใน canonical schema ปัจจุบัน -ALTER TABLE attachments - ADD COLUMN IF NOT EXISTS ai_processing_status ENUM('PENDING', 'PROCESSING', 'DONE', 'FAILED') - NOT NULL DEFAULT 'PENDING' COMMENT 'สถานะ AI job ของไฟล์เอกสารตาม ADR-023A'; - -CREATE INDEX IF NOT EXISTS idx_attachments_ai_status ON attachments (ai_processing_status); diff --git a/specs/03-Data-and-Storage/deltas/16-add-intent-classification.sql b/specs/03-Data-and-Storage/deltas/16-add-intent-classification.sql deleted file mode 100644 index 5c7615ab..00000000 --- a/specs/03-Data-and-Storage/deltas/16-add-intent-classification.sql +++ /dev/null @@ -1,60 +0,0 @@ --- Delta 16: Add Intent Classification Tables (ADR-024) --- Feature: 224-intent-classification --- Created: 2026-05-19 --- เพิ่มตาราง ai_intent_definitions และ ai_intent_patterns สำหรับ Hybrid Intent Classifier - --- Intent Definitions Table -CREATE TABLE IF NOT EXISTS ai_intent_definitions ( - id INT AUTO_INCREMENT PRIMARY KEY, - public_id UUID NOT NULL DEFAULT UUID(), - intent_code VARCHAR(50) NOT NULL, - description_th VARCHAR(255) NOT NULL, - description_en VARCHAR(255) NOT NULL, - category ENUM('read', 'suggest', 'utility') NOT NULL, - is_active BOOLEAN NOT NULL DEFAULT TRUE, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - UNIQUE KEY uk_intent_public_id (public_id), - UNIQUE KEY uk_intent_code (intent_code), - INDEX idx_intent_active (is_active, category) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- Intent Patterns Table -CREATE TABLE IF NOT EXISTS ai_intent_patterns ( - id INT AUTO_INCREMENT PRIMARY KEY, - public_id UUID NOT NULL DEFAULT UUID(), - intent_code VARCHAR(50) NOT NULL, - language ENUM('th', 'en', 'any') NOT NULL DEFAULT 'any', - pattern_type ENUM('keyword', 'regex') NOT NULL DEFAULT 'keyword', - pattern_value VARCHAR(255) NOT NULL, - priority INT NOT NULL DEFAULT 100, - is_active BOOLEAN NOT NULL DEFAULT TRUE, - created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP, - updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, - - UNIQUE KEY uk_pattern_public_id (public_id), - INDEX idx_pattern_intent_code (intent_code), - INDEX idx_pattern_active_priority (is_active, priority ASC), - CONSTRAINT fk_intent_pattern_definition - FOREIGN KEY (intent_code) REFERENCES ai_intent_definitions(intent_code) - ON UPDATE CASCADE ON DELETE RESTRICT -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- Seed Intent Definitions (v1) — 12 รายการตาม ADR-024 -INSERT IGNORE INTO ai_intent_definitions (intent_code, description_th, description_en, category) VALUES --- Read Intents -('RAG_QUERY', 'ถามคำถามธรรมชาติ ตอบจาก vector + doc context', 'Natural language query from vector DB + document context', 'read'), -('GET_RFA', 'ดึง RFA ตาม filter', 'Get RFA by filters', 'read'), -('GET_DRAWING', 'ดึง Drawing revision', 'Get Drawing revision', 'read'), -('GET_TRANSMITTAL', 'ดึง Transmittal', 'Get Transmittal', 'read'), -('GET_CORRESPONDENCE','ดึง Correspondence ทั่วไป', 'Get Correspondence', 'read'), -('GET_CIRCULATION', 'ดึง Circulation', 'Get Circulation', 'read'), -('GET_RFA_DRAWINGS', 'ดึง Drawings ที่ผูกกับ RFA', 'Get Drawings linked to RFA', 'read'), -('SUMMARIZE_DOCUMENT','สรุปเอกสารที่เปิดอยู่', 'Summarize current document', 'read'), -('LIST_OVERDUE', 'รายการ cross-entity ที่เกินกำหนด', 'List overdue items across entities', 'read'), --- Suggest Intents -('SUGGEST_METADATA', 'แนะนำ metadata สำหรับเอกสารที่อัปโหลด', 'Suggest metadata for uploaded document', 'suggest'), -('SUGGEST_ACTION', 'แจ้งเตือนว่าควรทำอะไรต่อ', 'Suggest next actions', 'suggest'), --- Utility Intents -('FALLBACK', 'ไม่เข้า intent ไหน / ไม่เกี่ยวกับระบบ', 'No matching intent / unrelated to system', 'utility'); diff --git a/specs/03-Data-and-Storage/deltas/17-seed-intent-patterns.sql b/specs/03-Data-and-Storage/deltas/17-seed-intent-patterns.sql deleted file mode 100644 index 16f348fa..00000000 --- a/specs/03-Data-and-Storage/deltas/17-seed-intent-patterns.sql +++ /dev/null @@ -1,89 +0,0 @@ --- Delta 17: Seed Intent Patterns (v1) for ADR-024 Intent Classification --- Feature: 224-intent-classification --- Created: 2026-05-19 --- เพิ่ม patterns เริ่มต้นสำหรับ 12 Intent Definitions (keyword + regex) - --- RAG_QUERY patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('RAG_QUERY', 'th', 'keyword', 'ค้นหา', 10), -('RAG_QUERY', 'th', 'keyword', 'หาข้อมูล', 10), -('RAG_QUERY', 'en', 'keyword', 'search', 10), -('RAG_QUERY', 'en', 'keyword', 'find', 10), -('RAG_QUERY', 'any', 'regex', '(?i)(what|where|who|when|how|why).*\\?', 50); - --- GET_RFA patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('GET_RFA', 'th', 'keyword', 'rfa', 10), -('GET_RFA', 'th', 'keyword', 'อาร์เอฟเอ', 10), -('GET_RFA', 'en', 'keyword', 'request for approval', 15), -('GET_RFA', 'any', 'regex', '(?i)rfa[- ]?\\d+', 5); - --- GET_DRAWING patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('GET_DRAWING', 'th', 'keyword', 'แบบ', 20), -('GET_DRAWING', 'th', 'keyword', 'drawing', 10), -('GET_DRAWING', 'en', 'keyword', 'drawing', 10), -('GET_DRAWING', 'en', 'keyword', 'revision', 20), -('GET_DRAWING', 'any', 'regex', '(?i)(shop.?draw|dwg|rev\\.?\\s*\\d)', 5); - --- GET_TRANSMITTAL patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('GET_TRANSMITTAL', 'th', 'keyword', 'transmittal', 10), -('GET_TRANSMITTAL', 'th', 'keyword', 'ทรานส์มิตทอล', 10), -('GET_TRANSMITTAL', 'en', 'keyword', 'transmittal', 10), -('GET_TRANSMITTAL', 'any', 'regex', '(?i)tr[- ]?\\d+', 5); - --- GET_CORRESPONDENCE patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('GET_CORRESPONDENCE', 'th', 'keyword', 'จดหมาย', 10), -('GET_CORRESPONDENCE', 'th', 'keyword', 'หนังสือ', 15), -('GET_CORRESPONDENCE', 'en', 'keyword', 'correspondence', 10), -('GET_CORRESPONDENCE', 'en', 'keyword', 'letter', 15); - --- GET_CIRCULATION patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('GET_CIRCULATION', 'th', 'keyword', 'เวียน', 10), -('GET_CIRCULATION', 'th', 'keyword', 'circulation', 10), -('GET_CIRCULATION', 'en', 'keyword', 'circulation', 10), -('GET_CIRCULATION', 'en', 'keyword', 'distribute', 15); - --- GET_RFA_DRAWINGS patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('GET_RFA_DRAWINGS', 'th', 'keyword', 'แบบใน rfa', 5), -('GET_RFA_DRAWINGS', 'en', 'keyword', 'drawings in rfa', 5), -('GET_RFA_DRAWINGS', 'any', 'regex', '(?i)(draw|แบบ).*(rfa|อาร์เอฟเอ)', 5); - --- SUMMARIZE_DOCUMENT patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('SUMMARIZE_DOCUMENT', 'th', 'keyword', 'สรุป', 10), -('SUMMARIZE_DOCUMENT', 'th', 'keyword', 'สรุปเอกสาร', 5), -('SUMMARIZE_DOCUMENT', 'en', 'keyword', 'summarize', 10), -('SUMMARIZE_DOCUMENT', 'en', 'keyword', 'summary', 10), -('SUMMARIZE_DOCUMENT', 'any', 'regex', '(?i)(สรุป|summar|tldr|tl;dr)', 5); - --- LIST_OVERDUE patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('LIST_OVERDUE', 'th', 'keyword', 'เกินกำหนด', 10), -('LIST_OVERDUE', 'th', 'keyword', 'ค้าง', 15), -('LIST_OVERDUE', 'th', 'keyword', 'overdue', 10), -('LIST_OVERDUE', 'en', 'keyword', 'overdue', 10), -('LIST_OVERDUE', 'en', 'keyword', 'late', 20), -('LIST_OVERDUE', 'any', 'regex', '(?i)(overdue|เกินกำหนด|ล่าช้า)', 5); - --- SUGGEST_METADATA patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('SUGGEST_METADATA', 'th', 'keyword', 'แนะนำ metadata', 5), -('SUGGEST_METADATA', 'th', 'keyword', 'แท็ก', 15), -('SUGGEST_METADATA', 'en', 'keyword', 'suggest metadata', 5), -('SUGGEST_METADATA', 'en', 'keyword', 'tag', 15), -('SUGGEST_METADATA', 'any', 'regex', '(?i)(suggest|แนะนำ).*(tag|meta|ประเภท)', 5); - --- SUGGEST_ACTION patterns -INSERT IGNORE INTO ai_intent_patterns (intent_code, language, pattern_type, pattern_value, priority) VALUES -('SUGGEST_ACTION', 'th', 'keyword', 'ทำอะไรต่อ', 10), -('SUGGEST_ACTION', 'th', 'keyword', 'แนะนำ', 20), -('SUGGEST_ACTION', 'en', 'keyword', 'what should i do', 10), -('SUGGEST_ACTION', 'en', 'keyword', 'next step', 10), -('SUGGEST_ACTION', 'any', 'regex', '(?i)(next.?step|ทำอะไร|ควรทำ|what.*do)', 10); - --- FALLBACK: ไม่ต้อง seed pattern — ใช้เป็น default เมื่อไม่ match อะไรเลย diff --git a/specs/03-Data-and-Storage/lcbp3-v1.9.0-rfa-approval-schema.sql b/specs/03-Data-and-Storage/lcbp3-v1.9.0-rfa-approval-schema.sql deleted file mode 100644 index 4924aa4f..00000000 --- a/specs/03-Data-and-Storage/lcbp3-v1.9.0-rfa-approval-schema.sql +++ /dev/null @@ -1,211 +0,0 @@ --- ============================================================================= --- LCBP3-DMS v1.9.0 — RFA Approval System Refactor Schema --- Feature Branch: 204-rfa-approval-refactor --- ADR-009: No TypeORM migrations — edit SQL schema directly --- Created: 2026-05-13 --- ============================================================================= - --- ----------------------------------------------------------------------------- --- 1. review_teams — ทีมตรวจสอบแยกตาม Discipline --- ----------------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `review_teams` ( - `id` INT NOT NULL AUTO_INCREMENT, - `uuid` UUID NOT NULL DEFAULT (UUID()), - `project_id` INT NOT NULL, - `name` VARCHAR(100) NOT NULL, - `description` VARCHAR(255) NULL, - `default_for_rfa_types` TEXT NULL COMMENT 'Comma-separated RFA type codes e.g. SDW,DDW', - `is_active` TINYINT(1) NOT NULL DEFAULT 1, - `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), - `updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), - PRIMARY KEY (`id`), - UNIQUE KEY `uq_review_teams_uuid` (`uuid`), - KEY `idx_review_teams_project` (`project_id`, `is_active`), - CONSTRAINT `fk_review_teams_project` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- ----------------------------------------------------------------------------- --- 2. review_team_members — สมาชิกในทีมแยกตาม Discipline --- ----------------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `review_team_members` ( - `id` INT NOT NULL AUTO_INCREMENT, - `uuid` UUID NOT NULL DEFAULT (UUID()), - `team_id` INT NOT NULL, - `user_id` INT NOT NULL, - `discipline_id` INT NOT NULL, - `role` ENUM('REVIEWER','LEAD','MANAGER') NOT NULL DEFAULT 'REVIEWER', - `priority_order` INT NOT NULL DEFAULT 0, - `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), - PRIMARY KEY (`id`), - UNIQUE KEY `uq_review_team_members_uuid` (`uuid`), - UNIQUE KEY `uq_team_user_discipline` (`team_id`, `user_id`, `discipline_id`), - KEY `idx_rtm_team` (`team_id`), - KEY `idx_rtm_user` (`user_id`), - CONSTRAINT `fk_rtm_team` FOREIGN KEY (`team_id`) REFERENCES `review_teams` (`id`) ON DELETE CASCADE, - CONSTRAINT `fk_rtm_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`) ON DELETE CASCADE, - CONSTRAINT `fk_rtm_discipline` FOREIGN KEY (`discipline_id`) REFERENCES `disciplines` (`id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- ----------------------------------------------------------------------------- --- 3. response_codes — รหัสตอบกลับมาตรฐาน (Master Approval Matrix) --- ----------------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `response_codes` ( - `id` INT NOT NULL AUTO_INCREMENT, - `uuid` UUID NOT NULL DEFAULT (UUID()), - `code` VARCHAR(10) NOT NULL COMMENT '1A, 1B, 1C, 1D, 1E, 1F, 1G, 2, 3, 4', - `sub_status` VARCHAR(10) NULL, - `category` ENUM('ENGINEERING','MATERIAL','CONTRACT','TESTING','ESG') NOT NULL, - `description_th` TEXT NOT NULL, - `description_en` TEXT NOT NULL, - `implications` JSON NULL COMMENT '{"affectsSchedule":bool,"affectsCost":bool,"requiresContractReview":bool}', - `notify_roles` TEXT NULL COMMENT 'Comma-separated roles e.g. CONTRACT_MANAGER,QS_MANAGER', - `is_active` TINYINT(1) NOT NULL DEFAULT 1, - `is_system` TINYINT(1) NOT NULL DEFAULT 0 COMMENT 'System default — cannot delete', - `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), - PRIMARY KEY (`id`), - UNIQUE KEY `uq_response_codes_uuid` (`uuid`), - UNIQUE KEY `uq_response_code_category` (`code`, `category`), - KEY `idx_rc_category_active` (`category`, `is_active`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- ----------------------------------------------------------------------------- --- 4. response_code_rules — กฎการใช้รหัสต่อโครงการ/ประเภทเอกสาร --- ----------------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `response_code_rules` ( - `id` INT NOT NULL AUTO_INCREMENT, - `uuid` UUID NOT NULL DEFAULT (UUID()), - `project_id` INT NULL COMMENT 'NULL = global default', - `document_type_id` INT NOT NULL, - `response_code_id` INT NOT NULL, - `is_enabled` TINYINT(1) NOT NULL DEFAULT 1, - `requires_comments` TINYINT(1) NOT NULL DEFAULT 0, - `triggers_notification` TINYINT(1) NOT NULL DEFAULT 0, - `parent_rule_id` INT NULL COMMENT 'For inheritance tracking', - `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), - `updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), - PRIMARY KEY (`id`), - UNIQUE KEY `uq_response_code_rules_uuid` (`uuid`), - UNIQUE KEY `uq_rule_per_project_doctype_code` (`project_id`, `document_type_id`, `response_code_id`), - KEY `idx_response_rules_lookup` (`project_id`, `document_type_id`, `is_enabled`), - CONSTRAINT `fk_rcr_response_code` FOREIGN KEY (`response_code_id`) REFERENCES `response_codes` (`id`), - CONSTRAINT `fk_rcr_parent` FOREIGN KEY (`parent_rule_id`) REFERENCES `response_code_rules` (`id`) ON DELETE SET NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- ----------------------------------------------------------------------------- --- 5. review_tasks — งานตรวจสอบสำหรับแต่ละ Discipline (Parallel Review) --- ----------------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `review_tasks` ( - `id` INT NOT NULL AUTO_INCREMENT, - `uuid` UUID NOT NULL DEFAULT (UUID()), - `rfa_revision_id` INT NOT NULL, - `team_id` INT NOT NULL, - `discipline_id` INT NOT NULL, - `assigned_to_user_id` INT NULL COMMENT 'NULL = auto-assign by discipline', - `status` ENUM('PENDING','IN_PROGRESS','COMPLETED','DELEGATED','EXPIRED','CANCELLED') NOT NULL DEFAULT 'PENDING', - `due_date` DATE NULL, - `response_code_id` INT NULL, - `comments` TEXT NULL, - `attachments` JSON NULL COMMENT 'Array of attachment publicIds', - `delegated_from_user_id` INT NULL COMMENT 'Original assignee when delegated', - `completed_at` TIMESTAMP NULL, - `version` INT NOT NULL DEFAULT 1 COMMENT 'Optimistic locking (ADR-002)', - `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), - `updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), - PRIMARY KEY (`id`), - UNIQUE KEY `uq_review_tasks_uuid` (`uuid`), - UNIQUE KEY `uq_review_task_per_revision_discipline` (`rfa_revision_id`, `team_id`, `discipline_id`), - KEY `idx_review_tasks_rfa_revision` (`rfa_revision_id`), - KEY `idx_review_tasks_status` (`status`), - KEY `idx_review_tasks_assigned` (`assigned_to_user_id`, `status`), - CONSTRAINT `fk_rt_rfa_revision` FOREIGN KEY (`rfa_revision_id`) REFERENCES `rfa_revisions` (`id`) ON DELETE CASCADE, - CONSTRAINT `fk_rt_team` FOREIGN KEY (`team_id`) REFERENCES `review_teams` (`id`), - CONSTRAINT `fk_rt_discipline` FOREIGN KEY (`discipline_id`) REFERENCES `disciplines` (`id`), - CONSTRAINT `fk_rt_user` FOREIGN KEY (`assigned_to_user_id`) REFERENCES `users` (`user_id`) ON DELETE SET NULL, - CONSTRAINT `fk_rt_response_code` FOREIGN KEY (`response_code_id`) REFERENCES `response_codes` (`id`) ON DELETE SET NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- ----------------------------------------------------------------------------- --- 6. delegations — การมอบหมายงาน --- ----------------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `delegations` ( - `id` INT NOT NULL AUTO_INCREMENT, - `uuid` UUID NOT NULL DEFAULT (UUID()), - `delegator_user_id` INT NOT NULL COMMENT 'ผู้มอบหมาย (FK → users.user_id)', - `delegate_user_id` INT NOT NULL COMMENT 'ผู้รับมอบหมาย (FK → users.user_id)', - `start_date` DATE NOT NULL, - `end_date` DATE NULL COMMENT 'BullMQ job flips is_active=0 when end_date < NOW() (ADR-008)', - `scope` ENUM('ALL','RFA_ONLY','CORRESPONDENCE_ONLY','SPECIFIC_TYPES') NOT NULL DEFAULT 'ALL', - `document_types` TEXT NULL COMMENT 'Comma-separated doc type codes when scope=SPECIFIC_TYPES', - `is_active` TINYINT(1) NOT NULL DEFAULT 1 COMMENT 'Managed by BullMQ scheduler — do not flip manually', - `reason` TEXT NULL, - `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), - `updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), - PRIMARY KEY (`id`), - UNIQUE KEY `uq_delegations_uuid` (`uuid`), - KEY `idx_delegations_active` (`delegator_user_id`, `is_active`, `start_date`, `end_date`), - KEY `idx_delegations_delegate` (`delegate_user_id`, `is_active`), - CONSTRAINT `fk_del_delegator` FOREIGN KEY (`delegator_user_id`) REFERENCES `users` (`user_id`), - CONSTRAINT `fk_del_delegate` FOREIGN KEY (`delegate_user_id`) REFERENCES `users` (`user_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- ----------------------------------------------------------------------------- --- 7. reminder_rules — กฎการแจ้งเตือน --- ----------------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `reminder_rules` ( - `id` INT NOT NULL AUTO_INCREMENT, - `uuid` UUID NOT NULL DEFAULT (UUID()), - `name` VARCHAR(100) NOT NULL, - `project_id` INT NULL COMMENT 'NULL = global', - `document_type_id` INT NULL COMMENT 'NULL = all types', - `trigger_days_before_due` INT NOT NULL DEFAULT 2, - `escalation_days_after_due` INT NOT NULL DEFAULT 1, - `reminder_type` ENUM('DUE_SOON','ON_DUE','OVERDUE','ESCALATION_L1','ESCALATION_L2') NOT NULL, - `recipients` TEXT NOT NULL COMMENT 'Comma-separated: ASSIGNEE,MANAGER,PROJECT_MANAGER', - `message_template_th` TEXT NOT NULL, - `message_template_en` TEXT NOT NULL, - `is_active` TINYINT(1) NOT NULL DEFAULT 1, - `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), - `updated_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), - PRIMARY KEY (`id`), - UNIQUE KEY `uq_reminder_rules_uuid` (`uuid`), - KEY `idx_reminder_rules_active` (`is_active`, `project_id`) -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- ----------------------------------------------------------------------------- --- 8. distribution_matrices — ตารางกระจายเอกสาร --- ----------------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `distribution_matrices` ( - `id` INT NOT NULL AUTO_INCREMENT, - `uuid` UUID NOT NULL DEFAULT (UUID()), - `name` VARCHAR(100) NOT NULL, - `project_id` INT NULL COMMENT 'NULL = global', - `document_type_id` INT NOT NULL, - `response_code_id` INT NULL COMMENT 'NULL = applies to all codes', - `conditions` JSON NULL COMMENT '{"codes":["1A","1B"],"excludeCodes":["3","4"]}', - `is_active` TINYINT(1) NOT NULL DEFAULT 1, - `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), - PRIMARY KEY (`id`), - UNIQUE KEY `uq_distribution_matrices_uuid` (`uuid`), - KEY `idx_distribution_lookup` (`document_type_id`, `response_code_id`, `is_active`), - CONSTRAINT `fk_dm_response_code` FOREIGN KEY (`response_code_id`) REFERENCES `response_codes` (`id`) ON DELETE SET NULL -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci; - --- ----------------------------------------------------------------------------- --- 9. distribution_recipients — ผู้รับเอกสารใน Distribution Matrix --- ----------------------------------------------------------------------------- -CREATE TABLE IF NOT EXISTS `distribution_recipients` ( - `id` INT NOT NULL AUTO_INCREMENT, - `uuid` UUID NOT NULL DEFAULT (UUID()) COMMENT 'UUID Public Identifier (ADR-019)', - `matrix_id` INT NOT NULL, - `recipient_type` ENUM('USER','ORGANIZATION','TEAM','ROLE') NOT NULL, - `recipient_public_id` UUID NOT NULL COMMENT 'publicId of target: USER=users.uuid | ORGANIZATION=organizations.uuid | TEAM=review_teams.uuid | ROLE=roles.uuid', - `delivery_method` ENUM('EMAIL','IN_APP','BOTH') NOT NULL DEFAULT 'BOTH', - `sequence` INT NULL COMMENT 'For ordered delivery', - `created_at` DATETIME(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6), - PRIMARY KEY (`id`), - UNIQUE KEY `uq_distribution_recipients_uuid` (`uuid`), - KEY `idx_dr_matrix` (`matrix_id`), - KEY `idx_dr_type_recipient` (`recipient_type`, `recipient_public_id`), - CONSTRAINT `fk_dr_matrix` FOREIGN KEY (`matrix_id`) REFERENCES `distribution_matrices` (`id`) ON DELETE CASCADE -) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci - COMMENT='Polymorphic recipients — no FK on recipient_public_id by design.'; diff --git a/specs/03-Data-and-Storage/lcbp3-v1.9.0-schema-02-tables.sql b/specs/03-Data-and-Storage/lcbp3-v1.9.0-schema-02-tables.sql index 9867ea7b..c4e6e830 100644 --- a/specs/03-Data-and-Storage/lcbp3-v1.9.0-schema-02-tables.sql +++ b/specs/03-Data-and-Storage/lcbp3-v1.9.0-schema-02-tables.sql @@ -872,15 +872,42 @@ CREATE TABLE attachments ( reference_date DATE NULL COMMENT 'Date used for folder structure (e.g. Issue Date) to prevent broken paths', workflow_history_id CHAR(36) NULL COMMENT 'FK to workflow_histories.id for step-specific attachments (ADR-021). NULL = main document', ai_processing_status ENUM('PENDING', 'PROCESSING', 'DONE', 'FAILED') NOT NULL DEFAULT 'PENDING' COMMENT 'สถานะ AI job ของไฟล์เอกสารตาม ADR-023A', + rag_status ENUM('PENDING', 'PROCESSING', 'INDEXED', 'FAILED') NOT NULL DEFAULT 'PENDING' COMMENT 'สถานะ RAG ingestion ระดับ file (ADR-022)', + rag_last_error TEXT NULL COMMENT 'Error message ล่าสุดเมื่อ rag_status = FAILED', FOREIGN KEY (uploaded_by_user_id) REFERENCES users (user_id) ON DELETE CASCADE, FOREIGN KEY (workflow_history_id) REFERENCES workflow_histories (id) ON DELETE SET NULL ON UPDATE CASCADE, INDEX idx_attachments_reference_date (reference_date), INDEX idx_att_wfhist_created (workflow_history_id, created_at), INDEX idx_attachments_ai_status (ai_processing_status), + INDEX idx_attachments_rag_status (rag_status), UNIQUE INDEX idx_attachments_uuid (uuid) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ตาราง "กลาง" เก็บไฟล์แนบทั้งหมดของระบบ'; +-- ===================================================== +-- 14. 📄 Document Chunks (ADR-022 RAG) +-- ===================================================== +-- ตารางเก็บ vector metadata สำหรับ RAG ingestion +CREATE TABLE document_chunks ( + id CHAR(36) NOT NULL PRIMARY KEY COMMENT 'UUID = Qdrant point ID', + document_id CHAR(36) NOT NULL COMMENT 'FK → attachments.public_id (UUIDv7)', + chunk_index INT NOT NULL COMMENT 'ลำดับ chunk ภายใน document', + content TEXT NOT NULL COMMENT 'เนื้อหา chunk หลัง PyThaiNLP normalize', + doc_type VARCHAR(20) NOT NULL COMMENT 'CORR, RFA, DRAWING, CONTRACT, RPT, TRANS', + doc_number VARCHAR(100) NULL COMMENT 'หมายเลขเอกสาร เช่น REF-2026-001', + revision VARCHAR(20) NULL COMMENT 'Revision เช่น Rev.A', + project_code VARCHAR(50) NOT NULL COMMENT 'รหัสโครงการ (ใช้ filter)', + project_public_id CHAR(36) NOT NULL COMMENT 'UUIDv7 ของโครงการ (Qdrant tenant key)', + version VARCHAR(20) NULL COMMENT 'เวอร์ชันเอกสาร เช่น 1.0, 2.1 (ถ้ามี)', + classification ENUM('PUBLIC', 'INTERNAL', 'CONFIDENTIAL') NOT NULL DEFAULT 'INTERNAL', + embedding_model VARCHAR(100) NOT NULL DEFAULT 'nomic-embed-text', + created_at DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3), + INDEX idx_chunks_document_id (document_id), + INDEX idx_chunks_doc_number_rev (doc_number, revision), + INDEX idx_chunks_project (project_public_id), + FULLTEXT INDEX ft_chunks_content (content) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ตาราง Document Chunks สำหรับ RAG (ADR-022)'; + -- ตารางเชื่อม correspondence_revisions กับ attachments (M:N) -- [FIX] FK เปลี่ยนจาก correspondences.id → correspondence_revisions.id -- เหตุผล: ไฟล์แนบผูกกับ revision ไม่ใช่ correspondence master (แต่ละ revision มีไฟล์ต่างกัน) @@ -1365,9 +1392,6 @@ CREATE TABLE workflow_definitions ( UNIQUE KEY uq_workflow_version (workflow_code, version) ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ตารางเก็บนิยามกฎการเดินเอกสาร (Workflow DSL)'; --- สร้าง Index สำหรับการค้นหา Workflow ที่ Active ล่าสุดได้เร็วขึ้น -CREATE INDEX idx_workflow_active ON workflow_definitions (workflow_code, is_active, version); - -- 2. ตารางเก็บ Workflow Instance (สถานะเอกสารจริง) CREATE TABLE workflow_instances ( id CHAR(36) NOT NULL PRIMARY KEY COMMENT 'UUID ของ Instance', @@ -1392,15 +1416,6 @@ CREATE TABLE workflow_instances ( SET NULL -- [delta-07] ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ตารางเก็บสถานะการเดินเรื่องของเอกสาร'; -CREATE INDEX idx_wf_inst_entity ON workflow_instances (entity_type, entity_id); - -CREATE INDEX idx_wf_inst_contract ON workflow_instances (contract_id, entity_type, STATUS); - -CREATE INDEX idx_wf_inst_state ON workflow_instances (current_state); - --- Index เพื่อรองรับ CAS check: WHERE id = ? AND version_no = ? -CREATE INDEX idx_wf_inst_version ON workflow_instances (id, version_no); - -- 3. ตารางเก็บประวัติ (Audit Log / History) CREATE TABLE workflow_histories ( id CHAR(36) NOT NULL PRIMARY KEY COMMENT 'UUID', @@ -1416,10 +1431,6 @@ CREATE TABLE workflow_histories ( CONSTRAINT fk_wf_hist_inst FOREIGN KEY (instance_id) REFERENCES workflow_instances (id) ON DELETE CASCADE ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ตารางประวัติการเปลี่ยนสถานะ Workflow'; -CREATE INDEX idx_wf_hist_instance ON workflow_histories (instance_id); - -CREATE INDEX idx_wf_hist_user ON workflow_histories (action_by_user_id); - -- ===================================================== -- 11. 🤖 AI Gateway (ตาราง AI Integration - ADR-018, ADR-020) -- ===================================================== @@ -1507,6 +1518,43 @@ CREATE TABLE ai_audit_logs ( SET NULL ) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ADR-023 AI development feedback log'; +-- ===================================================== +-- 13. 🤖 Intent Classification (ADR-024) +-- ===================================================== +-- Intent Definitions Table +CREATE TABLE IF NOT EXISTS ai_intent_definitions ( + id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'Internal PK (ห้าม expose ใน API)', + public_id UUID NOT NULL DEFAULT UUID() COMMENT 'UUID Public Identifier (ADR-019)', + intent_code VARCHAR(50) NOT NULL COMMENT 'รหัส Intent เช่น RAG_QUERY, GET_RFA', + description_th VARCHAR(255) NOT NULL COMMENT 'คำอธิบายภาษาไทย', + description_en VARCHAR(255) NOT NULL COMMENT 'คำอธิบายภาษาอังกฤษ', + category ENUM('read', 'suggest', 'utility') NOT NULL COMMENT 'ประเภท Intent', + is_active BOOLEAN NOT NULL DEFAULT TRUE COMMENT 'สถานะการใช้งาน', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้าง', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'วันที่แก้ไขล่าสุด', + UNIQUE KEY uk_intent_public_id (public_id), + UNIQUE KEY uk_intent_code (intent_code), + INDEX idx_intent_active (is_active, category) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ตาราง Intent Definitions สำหรับ Hybrid Intent Classifier (ADR-024)'; + +-- Intent Patterns Table +CREATE TABLE IF NOT EXISTS ai_intent_patterns ( + id INT AUTO_INCREMENT PRIMARY KEY COMMENT 'Internal PK (ห้าม expose ใน API)', + public_id UUID NOT NULL DEFAULT UUID() COMMENT 'UUID Public Identifier (ADR-019)', + intent_code VARCHAR(50) NOT NULL COMMENT 'รหัส Intent (FK to ai_intent_definitions)', + language ENUM('th', 'en', 'any') NOT NULL DEFAULT 'any' COMMENT 'ภาษาของ pattern', + pattern_type ENUM('keyword', 'regex') NOT NULL DEFAULT 'keyword' COMMENT 'ประเภท pattern', + pattern_value VARCHAR(255) NOT NULL COMMENT 'ค่า pattern (keyword หรือ regex)', + priority INT NOT NULL DEFAULT 100 COMMENT 'ลำดับความสำคัญ (ยิ่งน้อยยิ่งสำคัญ)', + is_active BOOLEAN NOT NULL DEFAULT TRUE COMMENT 'สถานะการใช้งาน', + created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้าง', + updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'วันที่แก้ไขล่าสุด', + UNIQUE KEY uk_pattern_public_id (public_id), + INDEX idx_pattern_intent_code (intent_code), + INDEX idx_pattern_active_priority (is_active, priority ASC), + CONSTRAINT fk_intent_pattern_definition FOREIGN KEY (intent_code) REFERENCES ai_intent_definitions(intent_code) ON UPDATE CASCADE ON DELETE RESTRICT +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'ตาราง Intent Patterns สำหรับ Hybrid Intent Classifier (ADR-024)'; + -- ============================================================================= -- 20. RFA Approval System (v1.9.0) -- ============================================================================= diff --git a/specs/03-Data-and-Storage/lcbp3-v1.9.0-schema-03-views-indexes.sql b/specs/03-Data-and-Storage/lcbp3-v1.9.0-schema-03-views-indexes.sql index 2e80f940..1d7408f6 100644 --- a/specs/03-Data-and-Storage/lcbp3-v1.9.0-schema-03-views-indexes.sql +++ b/specs/03-Data-and-Storage/lcbp3-v1.9.0-schema-03-views-indexes.sql @@ -93,6 +93,23 @@ CREATE INDEX idx_backup_logs_started_at ON backup_logs (started_at); CREATE INDEX idx_backup_logs_completed_at ON backup_logs (completed_at); +-- Indexes for workflow_definitions (ADR-001 Unified Workflow Engine) +CREATE INDEX idx_workflow_active ON workflow_definitions (workflow_code, is_active, version); + +-- Indexes for workflow_instances (ADR-001 Unified Workflow Engine) +CREATE INDEX idx_wf_inst_entity ON workflow_instances (entity_type, entity_id); + +CREATE INDEX idx_wf_inst_contract ON workflow_instances (contract_id, entity_type, STATUS); + +CREATE INDEX idx_wf_inst_state ON workflow_instances (current_state); + +CREATE INDEX idx_wf_inst_version ON workflow_instances (id, version_no); + +-- Indexes for workflow_histories (ADR-001 Unified Workflow Engine) +CREATE INDEX idx_wf_hist_instance ON workflow_histories (instance_id); + +CREATE INDEX idx_wf_hist_user ON workflow_histories (action_by_user_id); + -- ===================================================== -- Additional Composite Indexes for Performance -- ===================================================== diff --git a/specs/03-Data-and-Storage/lcbp3-v1.9.0-seed-basic.sql b/specs/03-Data-and-Storage/lcbp3-v1.9.0-seed-basic.sql index 2d5e7a9c..bd702b42 100644 --- a/specs/03-Data-and-Storage/lcbp3-v1.9.0-seed-basic.sql +++ b/specs/03-Data-and-Storage/lcbp3-v1.9.0-seed-basic.sql @@ -2197,3 +2197,530 @@ VALUES ( '2025-12-16 09:34:10', '2025-12-16 09:34:10' ); + +-- ===================================================== +-- Intent Classification Seed (ADR-024) +-- ===================================================== +-- Intent Definitions (v1) — 12 รายการ +INSERT IGNORE INTO ai_intent_definitions ( + intent_code, + description_th, + description_en, + category + ) +VALUES -- Read Intents + ( + 'RAG_QUERY', + 'ถามคำถามธรรมชาติ ตอบจาก vector + doc context', + 'Natural language query from vector DB + document context', + 'read' + ), + ( + 'GET_RFA', + 'ดึง RFA ตาม filter', + 'Get RFA by filters', + 'read' + ), + ( + 'GET_DRAWING', + 'ดึง Drawing revision', + 'Get Drawing revision', + 'read' + ), + ( + 'GET_TRANSMITTAL', + 'ดึง Transmittal', + 'Get Transmittal', + 'read' + ), + ( + 'GET_CORRESPONDENCE', + 'ดึง Correspondence ทั่วไป', + 'Get Correspondence', + 'read' + ), + ( + 'GET_CIRCULATION', + 'ดึง Circulation', + 'Get Circulation', + 'read' + ), + ( + 'GET_RFA_DRAWINGS', + 'ดึง Drawings ที่ผูกกับ RFA', + 'Get Drawings linked to RFA', + 'read' + ), + ( + 'SUMMARIZE_DOCUMENT', + 'สรุปเอกสารที่เปิดอยู่', + 'Summarize current document', + 'read' + ), + ( + 'LIST_OVERDUE', + 'รายการ cross-entity ที่เกินกำหนด', + 'List overdue items across entities', + 'read' + ), + -- Suggest Intents + ( + 'SUGGEST_METADATA', + 'แนะนำ metadata สำหรับเอกสารที่อัปโหลด', + 'Suggest metadata for uploaded document', + 'suggest' + ), + ( + 'SUGGEST_ACTION', + 'แจ้งเตือนว่าควรทำอะไรต่อ', + 'Suggest next actions', + 'suggest' + ), + -- Utility Intents + ( + 'FALLBACK', + 'ไม่เข้า intent ไหน / ไม่เกี่ยวกับระบบ', + 'No matching intent / unrelated to system', + 'utility' + ); + +-- Intent Patterns Seed (ADR-024) +-- ===================================================== +-- RAG_QUERY patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ('RAG_QUERY', 'th', 'keyword', 'ค้นหา', 10), + ('RAG_QUERY', 'th', 'keyword', 'หาข้อมูล', 10), + ('RAG_QUERY', 'en', 'keyword', 'search', 10), + ('RAG_QUERY', 'en', 'keyword', 'find', 10), + ( + 'RAG_QUERY', + 'any', + 'regex', + '(?i)(what|where|who|when|how|why).*\\?', + 50 + ); + +-- GET_RFA patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ('GET_RFA', 'th', 'keyword', 'rfa', 10), + ('GET_RFA', 'th', 'keyword', 'อาร์เอฟเอ', 10), + ( + 'GET_RFA', + 'en', + 'keyword', + 'request for approval', + 15 + ), + ('GET_RFA', 'any', 'regex', '(?i)rfa[- ]?\\d+', 5); + +-- GET_DRAWING patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ('GET_DRAWING', 'th', 'keyword', 'แบบ', 20), + ('GET_DRAWING', 'th', 'keyword', 'drawing', 10), + ('GET_DRAWING', 'en', 'keyword', 'drawing', 10), + ('GET_DRAWING', 'en', 'keyword', 'revision', 20), + ( + 'GET_DRAWING', + 'any', + 'regex', + '(?i)(shop.?draw|dwg|rev\\.?\\s*\\d)', + 5 + ); + +-- GET_TRANSMITTAL patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ( + 'GET_TRANSMITTAL', + 'th', + 'keyword', + 'transmittal', + 10 + ), + ( + 'GET_TRANSMITTAL', + 'th', + 'keyword', + 'ทรานส์มิตทอล', + 10 + ), + ( + 'GET_TRANSMITTAL', + 'en', + 'keyword', + 'transmittal', + 10 + ), + ( + 'GET_TRANSMITTAL', + 'any', + 'regex', + '(?i)tr[- ]?\\d+', + 5 + ); + +-- GET_CORRESPONDENCE patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ( + 'GET_CORRESPONDENCE', + 'th', + 'keyword', + 'จดหมาย', + 10 + ), + ( + 'GET_CORRESPONDENCE', + 'th', + 'keyword', + 'หนังสือ', + 15 + ), + ( + 'GET_CORRESPONDENCE', + 'en', + 'keyword', + 'correspondence', + 10 + ), + ( + 'GET_CORRESPONDENCE', + 'en', + 'keyword', + 'letter', + 15 + ); + +-- GET_CIRCULATION patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ('GET_CIRCULATION', 'th', 'keyword', 'เวียน', 10), + ( + 'GET_CIRCULATION', + 'th', + 'keyword', + 'circulation', + 10 + ), + ( + 'GET_CIRCULATION', + 'en', + 'keyword', + 'circulation', + 10 + ), + ( + 'GET_CIRCULATION', + 'en', + 'keyword', + 'distribute', + 15 + ); + +-- GET_RFA_DRAWINGS patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ( + 'GET_RFA_DRAWINGS', + 'th', + 'keyword', + 'แบบใน rfa', + 5 + ), + ( + 'GET_RFA_DRAWINGS', + 'en', + 'keyword', + 'drawings in rfa', + 5 + ), + ( + 'GET_RFA_DRAWINGS', + 'any', + 'regex', + '(?i)(draw|แบบ).*(rfa|อาร์เอฟเอ)', + 5 + ); + +-- SUMMARIZE_DOCUMENT patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ( + 'SUMMARIZE_DOCUMENT', + 'th', + 'keyword', + 'สรุป', + 10 + ), + ( + 'SUMMARIZE_DOCUMENT', + 'th', + 'keyword', + 'สรุปเอกสาร', + 5 + ), + ( + 'SUMMARIZE_DOCUMENT', + 'en', + 'keyword', + 'summarize', + 10 + ), + ( + 'SUMMARIZE_DOCUMENT', + 'en', + 'keyword', + 'summary', + 10 + ), + ( + 'SUMMARIZE_DOCUMENT', + 'any', + 'regex', + '(?i)(สรุป|summar|tldr|tl;dr)', + 5 + ); + +-- LIST_OVERDUE patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ('LIST_OVERDUE', 'th', 'keyword', 'เกินกำหนด', 10), + ('LIST_OVERDUE', 'th', 'keyword', 'ค้าง', 15), + ('LIST_OVERDUE', 'th', 'keyword', 'overdue', 10), + ('LIST_OVERDUE', 'en', 'keyword', 'overdue', 10), + ('LIST_OVERDUE', 'en', 'keyword', 'late', 20), + ( + 'LIST_OVERDUE', + 'any', + 'regex', + '(?i)(overdue|เกินกำหนด|ล่าช้า)', + 5 + ); + +-- SUGGEST_METADATA patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ( + 'SUGGEST_METADATA', + 'th', + 'keyword', + 'แนะนำ metadata', + 5 + ), + ('SUGGEST_METADATA', 'th', 'keyword', 'แท็ก', 15), + ( + 'SUGGEST_METADATA', + 'en', + 'keyword', + 'suggest metadata', + 5 + ), + ('SUGGEST_METADATA', 'en', 'keyword', 'tag', 15), + ( + 'SUGGEST_METADATA', + 'any', + 'regex', + '(?i)(suggest|แนะนำ).*(tag|meta|ประเภท)', + 5 + ); + +-- SUGGEST_ACTION patterns +INSERT IGNORE INTO ai_intent_patterns ( + intent_code, + language, + pattern_type, + pattern_value, + priority + ) +VALUES ( + 'SUGGEST_ACTION', + 'th', + 'keyword', + 'ทำอะไรต่อ', + 10 + ), + ('SUGGEST_ACTION', 'th', 'keyword', 'แนะนำ', 20), + ( + 'SUGGEST_ACTION', + 'en', + 'keyword', + 'what should i do', + 10 + ), + ( + 'SUGGEST_ACTION', + 'en', + 'keyword', + 'next step', + 10 + ), + ( + 'SUGGEST_ACTION', + 'any', + 'regex', + '(?i)(next.?step|ทำอะไร|ควรทำ|what.*do)', + 10 + ); + +-- FALLBACK: ไม่ต้อง seed pattern — ใช้เป็น default เมื่อไม่ match อะไรเลย +-- ===================================================== +-- Workflow Definitions Seed (ADR-001) +-- ===================================================== +-- CIRCULATION_FLOW_V1 Workflow Definition +INSERT IGNORE INTO workflow_definitions ( + id, + workflow_code, + version, + description, + dsl, + compiled, + is_active, + created_at, + updated_at + ) +VALUES ( + UUID(), + 'CIRCULATION_FLOW_V1', + 1, + 'Circulation Workflow — DRAFT → ROUTING → COMPLETED | CANCELLED', + JSON_OBJECT( + 'workflow', + 'CIRCULATION_FLOW_V1', + 'version', + 1, + 'states', + JSON_ARRAY( + JSON_OBJECT( + 'name', + 'DRAFT', + 'initial', + TRUE, + 'on', + JSON_OBJECT( + 'START', + JSON_OBJECT('to', 'ROUTING') + ) + ), + JSON_OBJECT( + 'name', + 'ROUTING', + 'on', + JSON_OBJECT( + 'COMPLETE', + JSON_OBJECT('to', 'COMPLETED'), + 'FORCE_CLOSE', + JSON_OBJECT('to', 'CANCELLED') + ) + ), + JSON_OBJECT('name', 'COMPLETED', 'terminal', TRUE), + JSON_OBJECT('name', 'CANCELLED', 'terminal', TRUE) + ) + ), + JSON_OBJECT( + 'initialState', + 'DRAFT', + 'states', + JSON_OBJECT( + 'DRAFT', + JSON_OBJECT( + 'initial', + TRUE, + 'terminal', + FALSE, + 'transitions', + JSON_OBJECT( + 'START', + JSON_OBJECT('to', 'ROUTING', 'events', JSON_ARRAY()) + ) + ), + 'ROUTING', + JSON_OBJECT( + 'initial', + FALSE, + 'terminal', + FALSE, + 'transitions', + JSON_OBJECT( + 'COMPLETE', + JSON_OBJECT('to', 'COMPLETED', 'events', JSON_ARRAY()), + 'FORCE_CLOSE', + JSON_OBJECT('to', 'CANCELLED', 'events', JSON_ARRAY()) + ) + ), + 'COMPLETED', + JSON_OBJECT( + 'initial', + FALSE, + 'terminal', + TRUE, + 'transitions', + JSON_OBJECT() + ), + 'CANCELLED', + JSON_OBJECT( + 'initial', + FALSE, + 'terminal', + TRUE, + 'transitions', + JSON_OBJECT() + ) + ) + ), + TRUE, + NOW(), + NOW() + ); diff --git a/specs/03-Data-and-Storage/lcbp3-v1.9.0-seed-permissions.sql b/specs/03-Data-and-Storage/lcbp3-v1.9.0-seed-permissions.sql index c81099bd..b141a4a2 100644 --- a/specs/03-Data-and-Storage/lcbp3-v1.9.0-seed-permissions.sql +++ b/specs/03-Data-and-Storage/lcbp3-v1.9.0-seed-permissions.sql @@ -1155,10 +1155,24 @@ VALUES ( 'ลบ AiAuditLog เดี่ยวโดย publicId (Superadmin Only)', 'ai', 1 + ), + ( + 187, + 'rag.query', + 'ใช้งาน RAG Q&A เพื่อค้นหาคำตอบจากเอกสาร', + 'rag', + 1 + ), + ( + 188, + 'rag.manage', + 'จัดการ RAG ingestion, re-index, ลบ vectors', + 'rag', + 1 ); -- Role 1: Superadmin — ได้รับทุก permission โดยอัตโนมัติผ่าน SELECT-all pattern (บรรทัด 825-829) --- Role 2: Org Admin — ai.suggest, ai.rag_query, ai.migration_manage, ai.read_analytics +-- Role 2: Org Admin — ai.suggest, ai.rag_query, ai.migration_manage, ai.read_analytics, rag.query INSERT IGNORE INTO role_permissions (role_id, permission_id) VALUES (2, 181), -- ai.suggest @@ -1166,10 +1180,12 @@ VALUES (2, 181), -- ai.rag_query (2, 183), -- ai.migration_manage - (2, 185); + (2, 185), + -- ai.read_analytics + (2, 187); --- ai.read_analytics --- Role 3: Document Control — ai.suggest, ai.rag_query, ai.migration_manage, ai.read_analytics +-- rag.query +-- Role 3: Document Control — ai.suggest, ai.rag_query, ai.migration_manage, ai.read_analytics, rag.query INSERT IGNORE INTO role_permissions (role_id, permission_id) VALUES (3, 181), -- ai.suggest @@ -1177,8 +1193,22 @@ VALUES (3, 181), -- ai.rag_query (3, 183), -- ai.migration_manage - (3, 185); + (3, 185), + -- ai.read_analytics + (3, 187); --- ai.read_analytics +-- rag.query +-- rag.manage (188) — Superadmin เท่านั้น, ไม่ grant ให้ Role อื่น -- ai.migration_manage -- ai.audit_log_delete (184) — Superadmin เท่านั้น, ไม่ grant ให้ Role อื่น +-- ========================================================== +-- 19. RBAC Bulk Permission (Delta 02) +-- ========================================================== +-- Grant user.manage_assignments to ADMIN, Org Admin, DC, Document Control roles +INSERT IGNORE INTO role_permissions (role_id, permission_id) +SELECT r.role_id, + p.permission_id +FROM roles r, + permissions p +WHERE r.role_name IN ('ADMIN', 'Org Admin', 'DC', 'Document Control') + AND p.permission_name = 'user.manage_assignments'; diff --git a/specs/06-Decision-Records/README.md b/specs/06-Decision-Records/README.md index 9ab02ce5..0b8234d5 100644 --- a/specs/06-Decision-Records/README.md +++ b/specs/06-Decision-Records/README.md @@ -1,7 +1,7 @@ # Architecture Decision Records (ADRs) -**Version:** 1.9.1 -**Last Updated:** 2026-05-14 +**Version:** 1.9.5 +**Last Updated:** 2026-05-18 **Project:** LCBP3-DMS (Laem Chabang Port Phase 3 - Document Management System) --- @@ -95,6 +95,7 @@ Architecture Decision Records (ADRs) เป็นเอกสารที่บ | [ADR-020](./ADR-020-ai-intelligence-integration.md) | AI Intelligence Integration Architecture | ❌ Superseded | 2026-04-03 | ถูกแทนที่โดย ADR-023: Unified AI Architecture | | [ADR-022](./ADR-022-retrieval-augmented-generation.md) | Retrieval-Augmented Generation (RAG) | ❌ Superseded | 2026-04-20 | ถูกแทนที่โดย ADR-023: Unified AI Architecture | | [ADR-023](./ADR-023-unified-ai-architecture.md) | Unified AI Architecture | ✅ Accepted | 2026-05-14 | สถาปัตยกรรม AI หลักแบบรวมศูนย์ (Boundary, RAG, Workflows และ Isolation) | +| [ADR-023A](./ADR-023A-unified-ai-architecture.md) | AI Model Revision | ✅ Accepted | 2026-05-15 | 2-Model Stack (gemma4:e4b Q8_0 + nomic-embed-text), BullMQ 2-Queue, RAG embed scope, OCR auto-detect | --- @@ -146,16 +147,12 @@ Architecture Decision Records (ADRs) เป็นเอกสารที่บ ### 9. AI & Data Integration -- **ADR-017:** Ollama Data Migration - (Superseded by ADR-023) -- **ADR-017B:** Smart Document Digitization - (Superseded by ADR-023) -- **ADR-018:** AI Boundary Policy - (Superseded by ADR-023) -- **ADR-020:** AI Intelligence Integration - (Superseded by ADR-023) -- **ADR-022:** Retrieval-Augmented Generation - (Superseded by ADR-023) - **ADR-023:** Unified AI Architecture - สถาปัตยกรรม AI หลักของระบบ ครอบคลุม Boundary, Workflows, RAG และ Hardware Isolation +- **ADR-023A:** AI Model Revision - 2-Model Stack (gemma4:e4b Q8_0 + nomic-embed-text), BullMQ 2-Queue, OCR auto-detect --- -## 📖 How to Read ADRs +## How to Read ADRs ### ADR Structure @@ -379,8 +376,8 @@ graph TB --- -**Version:** 1.9.1 (Consolidated AI ADRs into ADR-023) -**Last Review:** 2026-05-14 +**Version:** 1.9.5 (Added ADR-023A AI Model Revision) +**Last Review:** 2026-05-18 **Next Review:** 2026-10-10 --- diff --git a/specs/200-fullstacks/README.md b/specs/200-fullstacks/README.md index 0c9599dd..f03088ef 100644 --- a/specs/200-fullstacks/README.md +++ b/specs/200-fullstacks/README.md @@ -16,7 +16,12 @@ ## ตัวอย่างงานที่อยู่ในโฟลเดอร์นี้ - `201-transmittals-circulation` - Transmittals + Circulation Integration +- `202-adr-021-integrated-workflow-conte` - ADR-021 Integrated Workflow Context - `203-unified-workflow-engine` - Unified Workflow Engine +- `204-rfa-approval-refactor` - RFA Approval Refactor +- `224-intent-classification` - AI Intent Classification +- `225-ai-tool-layer-architecture` - AI Tool Layer Architecture +- `226-document-chat-ui-pattern` - Document Chat UI Pattern ## การตั้งชื่อโฟลเดอร์ diff --git a/specs/README.md b/specs/README.md index a4235ff9..80ff55fd 100644 --- a/specs/README.md +++ b/specs/README.md @@ -1,7 +1,7 @@ # 📚 LCBP3-DMS Specifications Directory -**Version:** 1.9.0 (Global Standards & Agent Sync) -**Last Updated:** 2026-05-13 +**Version:** 1.9.2 (AI Model Revision & Hybrid Staging) +**Last Updated:** 2026-05-18 **Project:** LCBP3-DMS (Laem Chabang Port Phase 3 - Document Management System) **Status:** ✅ Production Ready — 10/10 Documentation Gaps Closed • Hybrid Specs Structure Applied @@ -80,10 +80,12 @@ specs/ │ ├── 05-07-hybrid-uuid-implementation-plan.md # ADR-019 Implementation Guide │ └── README.md # ภาพรวมเป้าหมายงาน Engineering │ -├── 06-Decision-Records/ # Architecture Decision Records (17 + Patch + ADR-019) +├── 06-Decision-Records/ # Architecture Decision Records (23 ADRs) │ ├── ADR-001 to ADR-017... # ไฟล์อธิบายสถาปัตยกรรม (ADR) -│ ├── ADR-018-ai-boundary.md # ★ Patch 1.8.1: AI/Ollama Isolation Policy +│ ├── ADR-018-ai-boundary.md # ★ Patch 1.8.1: AI/Ollama Isolation Policy (Superseded by ADR-023) │ ├── ADR-019-hybrid-identifier-strategy.md # ★ Hybrid ID: INT PK + UUIDv7 Public API +│ ├── ADR-023-unified-ai-architecture.md # ★ Unified AI Architecture (Consolidates ADR-017/017B/018/020/022) +│ ├── ADR-023A-unified-ai-architecture.md # ★ AI Model Revision: 2-Model Stack + BullMQ 2-Queue │ └── README.md # รายชื่อ ADR ทั้งหมดพร้อมสถานะและวันที่ │ ├── 100-Infrastructures/ # Feature Work: Infrastructure (Deployment, Monitoring, Docker Compose, Network)