260310:1705 20260310:1700 Refactor rfas
Build and Deploy / deploy (push) Successful in 5m42s

This commit is contained in:
admin
2026-03-10 17:05:30 +07:00
parent b6dc83d54a
commit 15b447ceeb
22 changed files with 3086 additions and 380 deletions
+45
View File
@@ -0,0 +1,45 @@
const fs = require('fs');
const config = $('Set Configuration').first().json.config;
// Check file mount and inputs
try {
if (!fs.existsSync(config.EXCEL_FILE)) {
throw new Error(`Excel file not found at: ${config.EXCEL_FILE}`);
}
if (!fs.existsSync(config.SOURCE_PDF_DIR)) {
throw new Error(`PDF Source directory not found at: ${config.SOURCE_PDF_DIR}`);
}
const files = fs.readdirSync(config.SOURCE_PDF_DIR);
// Check write permission to log path
fs.writeFileSync(`${config.LOG_PATH}/.preflight_ok`, new Date().toISOString());
// Grab categories out of the previous node (Fetch Categories) if available
// otherwise use fallback array
let categories = ['Correspondence','RFA','Drawing','Transmittal','Report','Other'];
try {
const upstreamData = $('Fetch Categories').first()?.json?.data;
if (upstreamData && Array.isArray(upstreamData)) {
categories = upstreamData.map(c => c.name || c.type || c); // very loose mapping depending on API response
}
} catch(e) {}
// Grab existing tags from Fetch Tags node
let existingTags = [];
try {
const tagData = $('Fetch Tags').first()?.json?.data || [];
existingTags = Array.isArray(tagData) ? tagData.map(t => t.tag_name || t.name || '').filter(Boolean) : [];
} catch(e) {}
return [{ json: {
preflight_ok: true,
pdf_count_in_source: files.length,
excel_target: config.EXCEL_FILE,
system_categories: categories,
existing_tags: existingTags,
timestamp: new Date().toISOString()
}}];
} catch (err) {
throw new Error(`Pre-flight check failed: ${err.message}`);
}
@@ -622,47 +622,28 @@ SET NULL - INDEX (is_active) - INDEX (email) ** Relationships **: - Parent: orga
**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 |
| Column Name | Data Type | Constraints | Description |
| ------------------- | --------- | --------------------------------- | ----------------------------------------------------------- |
| id | INT | PK, FK | Master Revision ID (Shared with correspondence_revisions) |
| rfa_status_code_id | INT | NOT NULL, FK | Current RFA status |
| rfa_approve_code_id | INT | NULL, FK | Approval result code |
| 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 (id) REFERENCES correspondence_revisions(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
* Parent: correspondence_revisions, rfas, rfa_status_codes, rfa_approve_codes
* Children: rfa_items
---
+142
View File
@@ -0,0 +1,142 @@
const config = $('Set Configuration').first().json.config;
const fallbackState = $('Check Fallback State').first()?.json || { is_fallback_active: false, recent_error_count: 0 };
const isFallback = fallbackState.is_fallback_active || false;
const model = isFallback ? config.OLLAMA_MODEL_FALLBACK : config.OLLAMA_MODEL_PRIMARY;
// Read DB Context
const dbContext = $('Fetch DB Context').all().map(i => i.json);
const dbProjects = dbContext.filter(d => d.type === 'projects').map(d => ({id: d.id, code: d.text1, name: d.text2}));
const dbDisciplines = dbContext.filter(d => d.type === 'disciplines').map(d => ({id: d.id, th: d.text1, en: d.text2}));
const dbOrgs = dbContext.filter(d => d.type === 'organizations').map(d => ({id: d.id, name: d.text1, code: d.text2}));
const dbTags = dbContext.filter(d => d.type === 'tags').map(d => ({id: d.id, name: d.text1}));
const dbCorrTypes = dbContext.filter(d => d.type === 'correspondence_types').map(d => ({id: d.id, code: d.text1, name: d.text2}));
let systemCategories = ['Correspondence','RFA','Drawing','Transmittal','Report','Other'];
try { systemCategories = $('File Mount Check').first().json.system_categories || systemCategories; } catch (e) {}
const pdfItems = $('Extract PDF Text').all();
// File Validator passes all original Excel JSON fields through (sender, receiver, project_code, etc.)
// Read PDF File overwrites the JSON with binary data, so we must go back one step
const metaItems = $('File Validator').all();
return pdfItems.map((pdfItem, i) => {
const item = metaItems[i] || pdfItem;
const docNum = String(item.json.document_number || '');
const title = String(item.json.title || '');
const legacyNum = String(item.json.legacy_number || '');
const issuedDate = String(item.json.issued_date || '');
const receivedDate = String(item.json.received_date || '');
const corrType = String(item.json.correspondence_type || '');
const senderCode = String(item.json.sender || '');
const receiverCode = String(item.json.receiver || '');
const projectCode = String(item.json.project_code || '');
// JavaScript pre-mapping
const findOrgId = (code) => {
if (!code) return null;
const match = dbOrgs.find(o => o.code === code || o.name === code);
return match ? match.id : null;
};
const findProjectId = (code) => {
if (!code) return config.PROJECT_ID; // Fallback to config
const match = dbProjects.find(p => p.code === code || p.name === code);
return match ? match.id : config.PROJECT_ID;
};
const senderId = findOrgId(senderCode);
const receiverId = findOrgId(receiverCode);
const projectId = findProjectId(projectCode);
// Excel corrType is likely already the ID based on requirements, but fallback matching to ID if needed
const corrMatch = dbCorrTypes.find(c => String(c.id) === corrType || c.code === corrType || c.name === corrType);
const corrTypeId = corrMatch ? corrMatch.id : (isNaN(parseInt(corrType)) ? null : parseInt(corrType));
const isRFA = docNum.includes('-RFA-') || title.toLowerCase().includes('rfa');
const systemPrompt = `You are an expert Document Controller for a construction project (LCBP3) in Thailand.
The documents are primarily in THAI and ENGLISH.
Your task is to classify documents and extract metadata from OCR text.
Respond ONLY with valid JSON.`;
// Use pdfItem for the OCR extracted data, NOT the metaItem
const pdfText = String(pdfItem.json.data || '').substring(0, 3500).replace(/[^a-zA-Z0-9ก-๙\s\.\/\-:\[\]\(\)]/g, ' ');
const userPrompt = `Analyze this document:
[EXCEL METADATA]
Document Number: ${docNum || 'Not provided'}
Title: ${title || 'Not provided'}
Issued Date: ${issuedDate || 'Not provided'}
Received Date: ${receivedDate || 'Not provided'}
[DATABASE REFERENCES]
Disciplines: ${JSON.stringify(dbDisciplines)}
Tags: ${JSON.stringify(dbTags)}
[OCR TEXT EXTRACTION]
${pdfText}
Rules:
1. Category: Must be one of ${JSON.stringify(systemCategories)}. If Document Number contains "-RFA-", category MUST be "RFA".
2. Respond with EXACTLY 8 fields in JSON format:
- "discipline_id": Find 'id' from Disciplines array analyzing text to match 'th' or 'en'. If no match, use ID=64 (from contract LCBP3-C2).
- "subject": Document subject. If OCR is close to EXCEL METADATA Title, use EXCEL METADATA.
- "issued_date": Verify from OCR text if it matches ${issuedDate}, format YYYY-MM-DD.
- "received_date": Verify from OCR text. If empty, default to issued_date.
- "status": Extract status (e.g., For Information, Approve, Reject, Resubmit). This will be exported as "remark".
- "summary": 4-5 lines of Thai summary from OCR. This will be exported as "body".
- "tags": REQUIRED. Identify 2-5 main topics/themes from the document (from Title, subject matter, and OCR text). For each topic, return an object with:
* "tag_name": short topic name in Thai (2-5 words), e.g. "คอนกรีตผสม", "ทดสอบวัสดุ"
* "description": one sentence in Thai describing this topic (use key point details). e.g. "การทดสอบค่า slump ของคอนกรีตผสมที่หน้างาน"
Return as: [{"tag_name": "...", "description": "..."}, ...]
- "key_points": Array of 3-5 string key points extracted from the document (in Thai).
3. IMPORTANT: You MUST REPLACE the 'null' values in the template below with the actual Integer IDs or text you found. DO NOT reply with literal 'null' if you found a match!
Respond ONLY with this EXACT JSON structure:
{
"discipline_id": 64,
"subject": "${title}",
"issued_date": "${issuedDate}",
"received_date": "${receivedDate || issuedDate}",
"status": null,
"summary": "สรุปเนื้อหา 4-5 บรรทัด...",
"tags": [{"tag_name": "ชื่อหัวข้อ", "description": "คำอธิบาย key point ของหัวข้อนี้"}],
"key_points": ["จุดสำคัญที่ 1", "จุดสำคัญที่ 2", "จุดสำคัญที่ 3"],
"category": "${isRFA ? 'RFA' : 'Correspondence'}",
"confidence": 0.95
}`;
return {
json: {
...item.json,
active_model: model,
is_fallback: isFallback,
system_categories: systemCategories,
pre_mapped: {
project_id: projectId,
sender_id: senderId,
receiver_id: receiverId,
correspondence_type_id: corrTypeId
},
_debug_mapping: {
excel_project_code: projectCode,
excel_sender: senderCode,
excel_receiver: receiverCode,
excel_corr_type: corrType,
matched_project: dbProjects.find(p => p.code === projectCode || p.name === projectCode) || null,
first_org_sample: dbOrgs[0] || null
},
ollama_payload: {
model: model,
prompt: `${systemPrompt}\n\n${userPrompt}`,
stream: false,
format: 'json',
options: {
temperature: 0.1,
num_ctx: 8192
}
}
}
};
});
File diff suppressed because it is too large Load Diff
+61
View File
@@ -0,0 +1,61 @@
Organizations: [
{
id: 1,
organization_name: 'การท่าเรือแห่งประเทศไทย',
organization_code: 'กทท.'
},
{
id: 10,
organization_name: 'โครงการพัฒนาท่าเรือแหลมฉบัง ระยะที่ 3',
organization_code: 'สคฉ.3'
},
{
id: 11,
organization_name: 'ตรวจรับพัสดุ ที่ปรึกษาควบคุมงาน',
organization_code: 'สคฉ.3-01'
},
{
id: 12,
organization_name: 'ตรวจรับพัสดุ งานทางทะเล',
organization_code: 'สคฉ.3-02'
},
{
id: 13,
organization_name: 'ตรวจรับพัสดุ อาคารและระบบสาธารณูปโภค',
organization_code: 'สคฉ.3-03'
}
]
Projects: [
{
id: 1,
project_code: 'LCBP3',
project_name: 'โครงการพัฒนาท่าเรือแหลมฉบัง ระยะที่ 3 (ส่วนที่ 1-4)'
},
{
id: 2,
project_code: 'LCBP3-C1',
project_name: 'โครงการพัฒนาท่าเรือแหลมฉบัง ระยะที่ 3 (ส่วนที่ 1) งานก่อสร้างงานทางทะเล'
},
{
id: 3,
project_code: 'LCBP3-C2',
project_name: 'โครงการพัฒนาท่าเรือแหลมฉบัง ระยะที่ 3 (ส่วนที่ 2) งานก่อสร้างอาคาร ท่าเทียบเรือ ระบบถนน และระบบสาธารณูปโภค'
},
{
id: 4,
project_code: 'LCBP3-C3',
project_name: 'โครงการพัฒนาท่าเรือแหลมฉบัง ระยะที่ 3 (ส่วนที่ 3) งานก่อสร้าง'
},
{
id: 5,
project_code: 'LCBP3-C4',
project_name: 'โครงการพัฒนาท่าเรือแหลมฉบัง ระยะที่ 3 (ส่วนที่ 4) งานก่อสร้าง'
}
]
Correspondence Types: [
{ id: 1, type_code: 'RFA', type_name: 'Request for Approval' },
{ id: 2, type_code: 'RFI', type_name: 'Request for Information' },
{ id: 3, type_code: 'TRANSMITTAL', type_name: 'Transmittal' },
{ id: 4, type_code: 'EMAIL', type_name: 'Email' },
{ id: 5, type_code: 'INSTRUCTION', type_name: 'Instruction' }
]
+9
View File
@@ -0,0 +1,9 @@
SELECT 'projects' as type, id, project_code as text1, project_name as text2 FROM projects
UNION ALL
SELECT 'disciplines' as type, id, code_name_th as text1, code_name_en as text2 FROM disciplines
UNION ALL
SELECT 'organizations' as type, id, organization_name as text1, organization_code as text2 FROM organizations
UNION ALL
SELECT 'tags' as type, id, tag_name as text1, description as text2 FROM tags
UNION ALL
SELECT 'correspondence_types' as type, id, type_code as text1, type_name as text2 FROM correspondence_types
@@ -440,47 +440,22 @@ CREATE TABLE rfas (
-- ตาราง "ลูก" เก็บประวัติ (Revisions) ของ rfas (1:N)
CREATE TABLE rfa_revisions (
id INT PRIMARY KEY AUTO_INCREMENT COMMENT 'ID ของ Revision',
rfa_id INT NOT NULL COMMENT 'Master ID ของ RFA',
revision_number INT NOT NULL COMMENT 'หมายเลข Revision (0, 1, 2...)',
revision_label VARCHAR(10) COMMENT 'Revision ที่แสดง (เช่น A, B, 1.1)',
is_current BOOLEAN DEFAULT FALSE COMMENT '(1 = Revision ปัจจุบัน)',
-- ข้อมูลเฉพาะของ RFA Revision ที่ซับซ้อน
id INT PRIMARY KEY COMMENT 'ID (แชร์กับ correspondence_revisions)',
rfa_status_code_id INT NOT NULL COMMENT 'สถานะ RFA',
rfa_approve_code_id INT COMMENT 'ผลการอนุมัติ',
subject VARCHAR(500) NOT NULL COMMENT 'หัวข้อเรื่อง',
description TEXT COMMENT 'คำอธิบายการแก้ไขใน Revision นี้',
body TEXT NULL COMMENT 'เนื้อความ (ถ้ามี)',
remarks TEXT COMMENT 'หมายเหตุ',
document_date DATE COMMENT 'วันที่ในเอกสาร',
issued_date DATE COMMENT 'วันที่ส่งขออนุมัติ',
received_date DATETIME COMMENT 'วันที่ลงรับเอกสาร',
due_date DATETIME COMMENT 'วันที่ครบกำหนด',
approved_date DATE COMMENT 'วันที่อนุมัติ',
-- Standard Meta Columns
created_at DATETIME DEFAULT CURRENT_TIMESTAMP COMMENT 'วันที่สร้างเอกสาร',
created_by INT COMMENT 'ผู้สร้าง',
updated_by INT COMMENT 'ผู้แก้ไขล่าสุด',
-- ส่วนของ JSON และ Schema Version
details JSON NULL COMMENT 'RFA Specific Details',
schema_version INT DEFAULT 1 COMMENT 'Version ของ JSON Schema',
-- Generated Virtual Columns (ดึงค่าจาก JSON โดยอัตโนมัติ)
v_ref_drawing_count INT GENERATED ALWAYS AS (
JSON_UNQUOTE(
JSON_EXTRACT(details, '$.drawingCount')
)
) VIRTUAL,
FOREIGN KEY (rfa_id) REFERENCES rfas (id) ON DELETE CASCADE,
FOREIGN KEY (id) REFERENCES correspondence_revisions (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 uq_rr_rev_number (rfa_id, revision_number),
UNIQUE KEY uq_rr_current (rfa_id, is_current)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตาราง "ลูก" เก็บประวัติ (Revisions) ของ rfas (1 :N)';
SET NULL
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = 'ตารางขยายของ correspondence_revisions สำหรับ RFA (1:1)';
-- ตารางเชื่อมระหว่าง rfa_revisions (ที่เป็นประเภท DWG) กับ shop_drawing_revisions (M:N)
CREATE TABLE rfa_items (
@@ -3,6 +3,7 @@
-- รัน: หลังจาก 02-schema-tables.sql เสร็จ
-- ==========================================================
SET NAMES utf8mb4;
SET time_zone = '+07:00';
-- ============================================================
@@ -176,12 +177,12 @@ SELECT r.id AS rfa_id,
c.originator_id,
org.organization_name AS originator_name,
rr.id AS revision_id,
rr.revision_number,
rr.revision_label,
rr.subject,
rr.document_date,
rr.issued_date,
rr.received_date,
cr.revision_number,
cr.revision_label,
cr.subject,
cr.document_date,
cr.issued_date,
cr.received_date,
rr.approved_date,
rr.rfa_status_code_id,
rsc.status_code AS rfa_status_code,
@@ -189,21 +190,22 @@ SELECT r.id AS rfa_id,
rr.rfa_approve_code_id,
rac.approve_code AS rfa_approve_code,
rac.approve_name AS rfa_approve_name,
rr.created_by,
cr.created_by,
u.username AS created_by_username,
rr.created_at AS revision_created_at
cr.created_at AS revision_created_at
FROM rfas r
INNER JOIN rfa_types rt ON r.rfa_type_id = rt.id
INNER JOIN rfa_revisions rr ON r.id = rr.rfa_id -- RFA uses shared primary key with correspondences (1:1)
INNER JOIN correspondences c ON r.id = c.id -- [FIX 1] เพิ่มการ Join ตาราง disciplines
INNER JOIN correspondences c ON r.id = c.id
INNER JOIN correspondence_revisions cr ON c.id = cr.correspondence_id
INNER JOIN rfa_revisions rr ON cr.id = rr.id -- RFA uses shared primary key with correspondence_revisions (1:1)
-- [FIX 1] เพิ่มการ Join ตาราง disciplines
LEFT JOIN disciplines d ON c.discipline_id = d.id
INNER JOIN projects p ON c.project_id = p.id
INNER JOIN organizations org ON c.originator_id = org.id
INNER JOIN rfa_status_codes rsc ON rr.rfa_status_code_id = rsc.id
LEFT JOIN rfa_approve_codes rac ON rr.rfa_approve_code_id = rac.id
LEFT JOIN users u ON rr.created_by = u.user_id
WHERE rr.is_current = TRUE
AND r.deleted_at IS NULL
LEFT JOIN users u ON cr.created_by = u.user_id
WHERE cr.is_current = TRUE
AND c.deleted_at IS NULL;
-- View แสดงความสัมพันธ์ทั้งหมดระหว่าง Contract, Project, และ Organization
@@ -249,7 +251,7 @@ SELECT -- 1. Workflow Instance Info
ELSE 'N/A'
END AS document_number,
CASE
WHEN wi.entity_type = 'rfa_revision' THEN rfa_rev.subject
WHEN wi.entity_type = 'rfa_revision' THEN rfa_corr_rev.subject
WHEN wi.entity_type = 'circulation' THEN circ.circulation_subject
WHEN wi.entity_type = 'correspondence_revision' THEN corr_rev.subject
ELSE 'Unknown Document'
@@ -262,7 +264,8 @@ FROM workflow_instances wi
JOIN workflow_definitions wd ON wi.definition_id = wd.id -- 5. Joins for RFA (ซับซ้อนหน่อยเพราะ RFA ผูกกับ Correspondence อีกที)
LEFT JOIN rfa_revisions rfa_rev ON wi.entity_type = 'rfa_revision'
AND wi.entity_id = CAST(rfa_rev.id AS CHAR)
LEFT JOIN correspondences rfa_corr ON rfa_rev.id = rfa_corr.id -- 6. Joins for Circulation
LEFT JOIN correspondence_revisions rfa_corr_rev ON rfa_rev.id = rfa_corr_rev.id
LEFT JOIN correspondences rfa_corr ON rfa_corr_rev.correspondence_id = rfa_corr.id -- 6. Joins for Circulation
LEFT JOIN circulations circ ON wi.entity_type = 'circulation'
AND wi.entity_id = CAST(circ.id AS CHAR) -- 7. Joins for Correspondence
LEFT JOIN correspondence_revisions corr_rev ON wi.entity_type = 'correspondence_revision'
@@ -497,9 +500,7 @@ CREATE INDEX idx_corr_revisions_current_status ON correspondence_revisions (is_c
CREATE INDEX idx_corr_revisions_correspondence_current ON correspondence_revisions (correspondence_id, is_current);
-- Indexes for v_current_rfas performance
CREATE INDEX idx_rfa_revisions_current_status ON rfa_revisions (is_current, rfa_status_code_id);
CREATE INDEX idx_rfa_revisions_rfa_current ON rfa_revisions (rfa_id, is_current);
CREATE INDEX idx_rfa_revisions_status ON rfa_revisions (rfa_status_code_id);
-- Indexes for document statistics performance
CREATE INDEX idx_correspondences_project_type ON correspondences (project_id, correspondence_type_id);
@@ -513,4 +514,3 @@ CREATE INDEX IDX_AUDIT_STATUS ON document_number_audit (STATUS);
CREATE INDEX IDX_AUDIT_OPERATION ON document_number_audit (operation);
SET FOREIGN_KEY_CHECKS = 1;
@@ -1924,56 +1924,6 @@ VALUES (
NULL
);
INSERT INTO `rfas` (
`id`,
`rfa_type_id`,
`created_at`,
`created_by`,
`deleted_at`
)
VALUES (2, 68, '2025-12-06 05:40:02', 1, NULL);
INSERT INTO `rfa_revisions` (
`id`,
`rfa_id`,
`revision_number`,
`revision_label`,
`is_current`,
`rfa_status_code_id`,
`rfa_approve_code_id`,
`subject`,
`document_date`,
`issued_date`,
`received_date`,
`approved_date`,
`description`,
`details`,
`schema_version`,
`created_at`,
`created_by`,
`updated_by`
)
VALUES (
1,
2,
1,
'A',
0,
2,
NULL,
'ขออนุมัติผลการทดสอบเสาเข็มแบบ Dynamic Load Test สำหรับงานเสาเข็มตอกของอาคารสถานีไฟฟ้าย่อย 22 kV. No. 6',
'2025-12-03',
'2025-12-04',
'2025-12-04 12:40:19',
NULL,
NULL,
NULL,
1,
'2025-12-06 05:41:25',
NULL,
NULL
);
-- ==========================================================
-- 20. Workflow Definitions (Unified Workflow Engine)
-- ==========================================================
File diff suppressed because one or more lines are too long
+16
View File
@@ -0,0 +1,16 @@
{
"name": "03-data-and-storage",
"version": "1.0.0",
"description": "",
"main": ".mountcheck.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"type": "commonjs",
"dependencies": {
"mysql2": "^3.19.1"
}
}
+28
View File
@@ -0,0 +1,28 @@
const mysql = require('mysql2/promise');
async function test() {
const connection = await mysql.createConnection({
host: '192.168.10.8',
port: 3306,
user: 'migration_bot',
password: 'Center2025',
database: 'lcbp3'
});
try {
const [orgs] = await connection.execute('SELECT id, organization_name, organization_code FROM organizations');
console.log('Organizations:', orgs.slice(0, 5));
const [projects] = await connection.execute('SELECT id, project_code, project_name FROM projects');
console.log('Projects:', projects.slice(0, 5));
const [corrTypes] = await connection.execute('SELECT id, type_code, type_name FROM correspondence_types');
console.log('Correspondence Types:', corrTypes.slice(0, 5));
} catch (err) {
console.error(err);
} finally {
await connection.end();
}
}
test();