260322:1648 Correct Coresspondence / Doing RFA / Correct CI
This commit is contained in:
@@ -306,6 +306,7 @@
|
||||
- ต้อง encrypt sensitive data ใน JSON fields
|
||||
|
||||
### **3.12 ข้อกำหนดพิเศษ**
|
||||
|
||||
- **ผู้ใช้งานที่มีสิทธิ์ระดับสูง (Global) หรือผู้ได้รับอนุญาตเป็นกรณีพิเศษ**
|
||||
- สามารถเลือก **สร้างในนามองค์กร (Create on behalf of)** ได้ เพื่อให้สามารถออกเลขที่เอกสาร (Running Number) ขององค์กรอื่นได้โดยไม่ต้องล็อกอินใหม่
|
||||
- สามารถทำงานแทนผู้ใช้งานอื่นได้ Routing & Workflow ของ Correspondence, RFA, Circulation Sheet
|
||||
@@ -327,15 +328,15 @@
|
||||
|
||||
### **4.3. การกำหนดบทบาท (Roles) และขอบเขต (Scope)**
|
||||
|
||||
| บทบาท (Role) | ขอบเขต (Scope) | คำอธิบาย | สิทธิ์หลัก (Key Permissions) |
|
||||
| :------------------- | :------------- | :------------------ | :----------------------------------------------------------------------------- |
|
||||
| **Superadmin** | Global | ผู้ดูแลระบบสูงสุด | ทำทุกอย่างในระบบ, จัดการองค์กร, จัดการข้อมูลหลักระดับ Global |
|
||||
| **Org Admin** | Organization | ผู้ดูแลองค์กร | จัดการผู้ใช้ในองค์กร, จัดการบทบาท/สิทธิ์ภายในองค์กร, ดูรายงานขององค์กร |
|
||||
| **Document Control** | Organization | ควบคุมเอกสารขององค์กร | เพิ่ม/แก้ไข/ลบเอกสาร, กำหนดสิทธิ์เอกสารภายในองค์กร |
|
||||
| **Editor** | Organization | ผู้แก้ไขเอกสารขององค์กร | เพิ่ม/แก้ไขเอกสารที่ได้รับมอบหมาย |
|
||||
| **Viewer** | Organization | ผู้ดูเอกสารขององค์กร | ดูเอกสารที่มีสิทธิ์เข้าถึง |
|
||||
| **Project Manager** | Project | ผู้จัดการโครงการ | จัดการสมาชิกในโครงการ (เพิ่ม/ลบ/มอบบทบาท), สร้าง/จัดการสัญญาในโครงการ, ดูรายงานโครงการ |
|
||||
| **Contract Admin** | Contract | ผู้ดูแลสัญญา | จัดการสมาชิกในสัญญา, สร้าง/จัดการข้อมูลหลักเฉพาะสัญญา (ถ้ามี), อนุมัติเอกสารในสัญญา |
|
||||
| บทบาท (Role) | ขอบเขต (Scope) | คำอธิบาย | สิทธิ์หลัก (Key Permissions) |
|
||||
| :------------------- | :------------- | :---------------------- | :------------------------------------------------------------------------------------- |
|
||||
| **Superadmin** | Global | ผู้ดูแลระบบสูงสุด | ทำทุกอย่างในระบบ, จัดการองค์กร, จัดการข้อมูลหลักระดับ Global |
|
||||
| **Org Admin** | Organization | ผู้ดูแลองค์กร | จัดการผู้ใช้ในองค์กร, จัดการบทบาท/สิทธิ์ภายในองค์กร, ดูรายงานขององค์กร |
|
||||
| **Document Control** | Organization | ควบคุมเอกสารขององค์กร | เพิ่ม/แก้ไข/ลบเอกสาร, กำหนดสิทธิ์เอกสารภายในองค์กร |
|
||||
| **Editor** | Organization | ผู้แก้ไขเอกสารขององค์กร | เพิ่ม/แก้ไขเอกสารที่ได้รับมอบหมาย |
|
||||
| **Viewer** | Organization | ผู้ดูเอกสารขององค์กร | ดูเอกสารที่มีสิทธิ์เข้าถึง |
|
||||
| **Project Manager** | Project | ผู้จัดการโครงการ | จัดการสมาชิกในโครงการ (เพิ่ม/ลบ/มอบบทบาท), สร้าง/จัดการสัญญาในโครงการ, ดูรายงานโครงการ |
|
||||
| **Contract Admin** | Contract | ผู้ดูแลสัญญา | จัดการสมาชิกในสัญญา, สร้าง/จัดการข้อมูลหลักเฉพาะสัญญา (ถ้ามี), อนุมัติเอกสารในสัญญา |
|
||||
|
||||
### **4.4. Token Management (ปรับปรุง)**
|
||||
|
||||
@@ -363,14 +364,14 @@
|
||||
|
||||
### **4.6. การจัดการข้อมูลหลัก (Master Data Management) ที่แบ่งตามระดับ**
|
||||
|
||||
| ข้อมูลหลัก | ผู้มีสิทธิ์จัดการ | ระดับ |
|
||||
| :---------------------------------- | :------------------------------ | :------------------------------ |
|
||||
| ประเภทเอกสาร (Correspondence, RFA) | **Superadmin** | Global |
|
||||
| สถานะเอกสาร (Draft, Approved, etc.) | **Superadmin** | Global |
|
||||
| หมวดหมู่แบบ (Shop Drawing) | **Project Manager** | Project (สร้างใหม่ได้ภายในโครงการ) |
|
||||
| Tags | **Org Admin / Project Manager** | Organization / Project |
|
||||
| บทบาทและสิทธิ์ (Custom Roles) | **Superadmin / Org Admin** | Global / Organization |
|
||||
| Document Numbering Formats | **Superadmin / Admin** | Global / Organization |
|
||||
| ข้อมูลหลัก | ผู้มีสิทธิ์จัดการ | ระดับ |
|
||||
| :---------------------------------- | :------------------------------ | :--------------------------------- |
|
||||
| ประเภทเอกสาร (Correspondence, RFA) | **Superadmin** | Global |
|
||||
| สถานะเอกสาร (Draft, Approved, etc.) | **Superadmin** | Global |
|
||||
| หมวดหมู่แบบ (Shop Drawing) | **Project Manager** | Project (สร้างใหม่ได้ภายในโครงการ) |
|
||||
| Tags | **Org Admin / Project Manager** | Organization / Project |
|
||||
| บทบาทและสิทธิ์ (Custom Roles) | **Superadmin / Org Admin** | Global / Organization |
|
||||
| Document Numbering Formats | **Superadmin / Admin** | Global / Organization |
|
||||
|
||||
## **👥 5. ข้อกำหนดด้านผู้ใช้งาน (User Interface & Experience)**
|
||||
|
||||
|
||||
@@ -50,14 +50,12 @@
|
||||
### **2.3 Core Services:**
|
||||
|
||||
- **Code Hosting:** Gitea (Self-hosted on QNAP)
|
||||
|
||||
- Application name: git
|
||||
- Service name: gitea
|
||||
- Domain: `git.np-dms.work`
|
||||
- หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
|
||||
|
||||
- **Backend / Data Platform:** NestJS
|
||||
|
||||
- Application name: lcbp3-backend
|
||||
- Service name: backend
|
||||
- Domain: `backend.np-dms.work`
|
||||
@@ -65,7 +63,6 @@
|
||||
- หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
|
||||
|
||||
- **Database:** MariaDB 10.11
|
||||
|
||||
- Application name: lcbp3-db
|
||||
- Service name: mariadb
|
||||
- Domain: `db.np-dms.work`
|
||||
@@ -73,7 +70,6 @@
|
||||
- Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
|
||||
|
||||
- **Database Management:** phpMyAdmin
|
||||
|
||||
- Application name: lcbp3-db
|
||||
- Service: phpmyadmin:5-apache
|
||||
- Service name: pma
|
||||
@@ -81,7 +77,6 @@
|
||||
- หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
|
||||
|
||||
- **Frontend:** Next.js
|
||||
|
||||
- Application name: lcbp3-frontend
|
||||
- Service name: frontend
|
||||
- Domain: `lcbp3.np-dms.work`
|
||||
@@ -91,7 +86,6 @@
|
||||
- หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
|
||||
|
||||
- **Workflow Automation:** n8n
|
||||
|
||||
- Application name: lcbp3-n8n
|
||||
- Service: n8nio/n8n:latest
|
||||
- Service name: n8n
|
||||
@@ -99,7 +93,6 @@
|
||||
- หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
|
||||
|
||||
- **Reverse Proxy:** Nginx Proxy Manager
|
||||
|
||||
- Application name: lcbp3-npm
|
||||
- Service: Nginx Proxy Manager (nginx-proxy-manage: latest)
|
||||
- Service name: npm
|
||||
@@ -200,18 +193,15 @@
|
||||
### **3.5. การจัดการ Workflow (Unified Workflow)**
|
||||
|
||||
- 3.5.1 Workflow Definition:
|
||||
|
||||
- Admin ต้องสามารถสร้าง/แก้ไข Workflow Rule ได้ผ่านหน้าจอ UI (DSL Editor) ร
|
||||
- องรับการกำหนด State, Transition, Required Role, Condition (JS Expression)
|
||||
|
||||
- 3.5.2 Workflow Execution:
|
||||
|
||||
- ระบบต้องรองรับการสร้าง Instance ของ Workflow ผูกกับเอกสาร (Polymorphic)
|
||||
- รองรับการเปลี่ยนสถานะ (Action) เช่น Approve, Reject, Comment, Return
|
||||
- Auto-Action: รองรับการเปลี่ยนสถานะอัตโนมัติเมื่อครบเงื่อนไข (เช่น Review ครบทุกคน)
|
||||
|
||||
- 3.5.3 Flexibility:
|
||||
|
||||
- รองรับ Parallel Review (ส่งให้หลายคนตรวจพร้อมกัน)
|
||||
- รองรับ Conditional Flow (เช่น ถ้ายอดเงิน > X ให้เพิ่มผู้อนุมัติ)
|
||||
|
||||
@@ -248,13 +238,11 @@
|
||||
### **3.9. การจัดเก็บไฟล์ (File Handling - ปรับปรุงใหญ่)**
|
||||
|
||||
- **3.9.1 Two-Phase Storage Strategy:**
|
||||
|
||||
1. **Phase 1 (Upload):** ไฟล์ถูกอัปโหลดเข้าโฟลเดอร์ `temp/` และได้รับ `temp_id`
|
||||
2. **Phase 2 (Commit):** เมื่อ User กด Submit ฟอร์มสำเร็จ ระบบจะย้ายไฟล์จาก `temp/` ไปยัง `permanent/{YYYY}/{MM}/` และบันทึกลง Database ภายใน Transaction เดียวกัน
|
||||
3. **Cleanup:** มี Cron Job ลบไฟล์ใน `temp/` ที่ค้างเกิน 24 ชม. (Orphan Files)
|
||||
|
||||
- **3.9.2 Security:**
|
||||
|
||||
- Virus Scan (ClamAV) ก่อนย้ายเข้า Permanent
|
||||
- Whitelist File Types: PDF, DWG, DOCX, XLSX, ZIP
|
||||
- Max Size: 50MB
|
||||
@@ -284,14 +272,12 @@
|
||||
### **3.11 การจัดการ JSON Details (JSON & Performance - ปรับปรุง)**
|
||||
|
||||
- **3.11.1 วัตถุประสงค์**
|
||||
|
||||
- จัดเก็บข้อมูลแบบไดนามิกที่เฉพาะเจาะจงกับแต่ละประเภทของเอกสาร
|
||||
- รองรับการขยายตัวของระบบโดยไม่ต้องเปลี่ยนแปลง database schema
|
||||
- จัดการ metadata และข้อมูลประกอบสำหรับ correspondence, routing, และ workflows
|
||||
|
||||
- **3.11.2 โครงสร้าง JSON Schema**
|
||||
ระบบต้องมี predefined JSON schemas สำหรับประเภทเอกสารต่างๆ:
|
||||
|
||||
- **3.11.2.1 Correspondence Types**
|
||||
- **GENERIC**: ข้อมูลพื้นฐานสำหรับเอกสารทั่วไป
|
||||
- **RFI**: รายละเอียดคำถามและข้อมูลทางเทคนิค
|
||||
@@ -310,14 +296,12 @@
|
||||
- **3.11.3 Virtual Columns (ใหม่):** สำหรับ Field ใน JSON ที่ต้องใช้ในการค้นหา (Search) หรือจัดเรียง (Sort) บ่อยๆ **ต้องสร้าง Generated Column (Virtual Column)** ใน Database และทำ Index ไว้ เพื่อประสิทธิภาพสูงสุด
|
||||
|
||||
- **3.11.4 Validation Rules**
|
||||
|
||||
- ต้องมี JSON schema validation สำหรับแต่ละประเภท
|
||||
- ต้องรองรับ versioning ของ schema
|
||||
- ต้องมี default values สำหรับ field ที่ไม่บังคับ
|
||||
- ต้องตรวจสอบ data types และ format ให้ถูกต้อง
|
||||
|
||||
- **3.11.5 Performance Requirements**
|
||||
|
||||
- JSON field ต้องมีขนาดไม่เกิน 50KB
|
||||
- ต้องรองรับ indexing สำหรับ field ที่ใช้ค้นหาบ่อย
|
||||
- ต้องมี compression สำหรับ JSON ขนาดใหญ่
|
||||
@@ -454,7 +438,6 @@
|
||||
### **6.1. การบันทึกการกระทำ (Audit Log):** ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน audit_logs เพื่อการตรวจสอบย้อนหลัง
|
||||
|
||||
- **6.1.1 ขอบเขตการบันทึก Audit Log:**
|
||||
|
||||
- ทุกการสร้าง/แก้ไข/ลบ ข้อมูลสำคัญ (correspondences, RFAs, drawings, users, permissions)
|
||||
- ทุกการเข้าถึงข้อมูล sensitive (user data, financial information)
|
||||
- ทุกการเปลี่ยนสถานะ workflow (status transitions)
|
||||
@@ -486,7 +469,6 @@
|
||||
### **6.5. ประสิทธิภาพ (Performance):** มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
|
||||
- **6.5.1 ตัวชี้วัดประสิทธิภาพ:**
|
||||
|
||||
- **API Response Time:** < 200ms (90th percentile) สำหรับ operation ทั่วไป
|
||||
- **Search Query Performance:** < 500ms สำหรับการค้นหาขั้นสูง
|
||||
- **File Upload Performance:** < 30 seconds สำหรับไฟล์ขนาด 50MB
|
||||
@@ -514,7 +496,6 @@
|
||||
- การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด
|
||||
|
||||
- **6.6.1 Rate Limiting Strategy:**
|
||||
|
||||
- **Anonymous Endpoints:** 100 requests/hour ต่อ IP address
|
||||
- **Authenticated Endpoints:**
|
||||
- Viewer: 500 requests/hour
|
||||
@@ -528,14 +509,12 @@
|
||||
- ต้องบันทึก log เมื่อมีการ trigger rate limiting
|
||||
|
||||
- **6.6.2 Error Handling และ Resilience:**
|
||||
|
||||
- ต้องมี circuit breaker pattern สำหรับ external service calls
|
||||
- ต้องมี retry mechanism ด้วย exponential backoff
|
||||
- ต้องมี graceful degradation เมื่อบริการภายนอกล้มเหลว
|
||||
- Error messages ต้องไม่เปิดเผยข้อมูล sensitive
|
||||
|
||||
- **6.6.3 Input Validation:**
|
||||
|
||||
- ต้องมี input validation ทั้งฝั่ง client และ server (defense in depth)
|
||||
- ต้องป้องกัน OWASP Top 10 vulnerabilities:
|
||||
- SQL Injection (ใช้ parameterized queries ผ่าน ORM)
|
||||
@@ -589,7 +568,6 @@
|
||||
### **6.8. กลยุทธ์การแจ้งเตือน (Notification Strategy - ปรับปรุง):**
|
||||
|
||||
- **6.8.1 ระบบจะส่งการแจ้งเตือน (ผ่าน Email หรือ Line [cite: 2.7]) เมื่อมีการกระทำที่สำคัญ** ดังนี้:
|
||||
|
||||
1. เมื่อมีเอกสารใหม่ (Correspondence, RFA) ถูกส่งมาถึงองค์กรณ์ของเรา
|
||||
2. เมื่อมีใบเวียน (Circulation) ใหม่ มอบหมายงานมาที่เรา
|
||||
3. (ทางเลือก) เมื่อเอกสารที่เราส่งไป ถูกดำเนินการ (เช่น อนุมัติ/ปฏิเสธ)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,5 @@
|
||||
# “Phase 6A + Technical Design Document : Workflow DSL (Mini-Language)”**
|
||||
# “Phase 6A + Technical Design Document : Workflow DSL (Mini-Language)”\*\*
|
||||
|
||||
ออกแบบสำหรับระบบ Workflow Engine กลางของโครงการ
|
||||
**ไม่มีโค้ดผูกกับ Framework** เพื่อให้สามารถนำไป Implement ใน NestJS หรือ Microservice ใด ๆ ได้
|
||||
|
||||
@@ -10,20 +11,19 @@
|
||||
|
||||
ใน Phase นี้ จะเริ่มสร้าง “Workflow DSL (Domain-Specific Language)” สำหรับนิยามกฎการเดินงาน (Workflow Transition Rules) ให้สามารถ:
|
||||
|
||||
* แยก **Business Workflow Logic** ออกจาก Source Code
|
||||
* แก้ไขกฎ Workflow ได้โดย **ไม่ต้องแก้โค้ดและไม่ต้อง Deploy ใหม่**
|
||||
* รองรับ Document หลายประเภท เช่น
|
||||
- แยก **Business Workflow Logic** ออกจาก Source Code
|
||||
- แก้ไขกฎ Workflow ได้โดย **ไม่ต้องแก้โค้ดและไม่ต้อง Deploy ใหม่**
|
||||
- รองรับ Document หลายประเภท เช่น
|
||||
- Correspondence
|
||||
- RFA
|
||||
- Internal Circulation
|
||||
- Document Transmittal
|
||||
|
||||
* Correspondence
|
||||
* RFA
|
||||
* Internal Circulation
|
||||
* Document Transmittal
|
||||
* รองรับ Multi-step routing, skip, reject, rollback, parallel assignments
|
||||
* สามารถนำไปใช้งานทั้งใน
|
||||
|
||||
* Backend (NestJS)
|
||||
* Frontend (UI Driven)
|
||||
* External Microservices
|
||||
- รองรับ Multi-step routing, skip, reject, rollback, parallel assignments
|
||||
- สามารถนำไปใช้งานทั้งใน
|
||||
- Backend (NestJS)
|
||||
- Frontend (UI Driven)
|
||||
- External Microservices
|
||||
|
||||
---
|
||||
|
||||
@@ -35,12 +35,12 @@
|
||||
|
||||
### 🧩 Output ของ Phase 6A
|
||||
|
||||
* DSL Specification (Grammar)
|
||||
* JSON Schema for Workflow Definition
|
||||
* Workflow Rule Interpreter (Parser + Executor)
|
||||
* Validation Engine (Compile-time and Runtime)
|
||||
* Storage (DB Table / Registry)
|
||||
* Execution API:
|
||||
- DSL Specification (Grammar)
|
||||
- JSON Schema for Workflow Definition
|
||||
- Workflow Rule Interpreter (Parser + Executor)
|
||||
- Validation Engine (Compile-time and Runtime)
|
||||
- Storage (DB Table / Registry)
|
||||
- Execution API:
|
||||
|
||||
| Action | Description |
|
||||
| -------------------------------- | ------------------------------- |
|
||||
@@ -59,22 +59,22 @@
|
||||
|
||||
#### Functional Requirements
|
||||
|
||||
* นิยาม Workflow เป็นภาษาคล้าย State Machine
|
||||
* แต่ละเอกสารมี **State, Actions, Entry/Exit Events**
|
||||
* สามารถมี:
|
||||
|
||||
* Required approvals
|
||||
* Conditional transition
|
||||
* Auto-transition
|
||||
* Parallel approval
|
||||
* Return/rollback
|
||||
- นิยาม Workflow เป็นภาษาคล้าย State Machine
|
||||
- แต่ละเอกสารมี **State, Actions, Entry/Exit Events**
|
||||
- สามารถมี:
|
||||
- Required approvals
|
||||
- Conditional transition
|
||||
- Auto-transition
|
||||
- Parallel approval
|
||||
- Return/rollback
|
||||
|
||||
####
|
||||
* Running time: < 20ms ต่อคำสั่ง
|
||||
* Hot reload ไม่ต้อง Compile ใหม่ทั้ง Backend
|
||||
* DSL ต้อง Debug ได้ง่าย
|
||||
* ต้อง Versioned
|
||||
* ต้องรองรับ Audit 100%
|
||||
|
||||
- Running time: < 20ms ต่อคำสั่ง
|
||||
- Hot reload ไม่ต้อง Compile ใหม่ทั้ง Backend
|
||||
- DSL ต้อง Debug ได้ง่าย
|
||||
- ต้อง Versioned
|
||||
- ต้องรองรับ Audit 100%
|
||||
|
||||
---
|
||||
|
||||
@@ -122,12 +122,8 @@ states:
|
||||
"transitions": {
|
||||
"SUBMIT": {
|
||||
"to": "IN_REVIEW",
|
||||
"requirements": [
|
||||
{ "role": "ENGINEER" }
|
||||
],
|
||||
"events": [
|
||||
{ "type": "notify", "target": "reviewer" }
|
||||
]
|
||||
"requirements": [{ "role": "ENGINEER" }],
|
||||
"events": [{ "type": "notify", "target": "reviewer" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -136,9 +132,7 @@ states:
|
||||
"APPROVE": { "to": "APPROVED" },
|
||||
"REJECT": {
|
||||
"to": "DRAFT",
|
||||
"events": [
|
||||
{ "type": "notify", "target": "creator" }
|
||||
]
|
||||
"events": [{ "type": "notify", "target": "creator" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -162,14 +156,14 @@ version = "version" ":" number ;
|
||||
states = "states:" state_list ;
|
||||
state_list = { state } ;
|
||||
|
||||
state = "- name:" identifier
|
||||
[ "initial:" boolean ]
|
||||
state = "- name:" identifier
|
||||
[ "initial:" boolean ]
|
||||
[ "terminal:" boolean ]
|
||||
[ "on:" transition_list ] ;
|
||||
|
||||
transition_list = { transition } ;
|
||||
|
||||
transition = action ":"
|
||||
transition = action ":"
|
||||
indent "to:" identifier
|
||||
[ indent "require:" requirements ]
|
||||
[ indent "events:" event_list ] ;
|
||||
@@ -186,23 +180,23 @@ event = "- notify:" identifier ;
|
||||
|
||||
#### 5.1 State Rules
|
||||
|
||||
* ต้องมีอย่างน้อย 1 state ที่ `initial: true`
|
||||
* หาก `terminal: true` → ต้องไม่มี transition ต่อไป
|
||||
- ต้องมีอย่างน้อย 1 state ที่ `initial: true`
|
||||
- หาก `terminal: true` → ต้องไม่มี transition ต่อไป
|
||||
|
||||
#### 5.2 Transition Rules
|
||||
|
||||
ตรวจสอบว่า:
|
||||
|
||||
* `to` ชี้ไปยัง state ที่มีอยู่
|
||||
* `require.role` ต้องเป็น role ที่ระบบรู้จัก
|
||||
* Action name ต้องเป็น **UPPER_CASE**
|
||||
- `to` ชี้ไปยัง state ที่มีอยู่
|
||||
- `require.role` ต้องเป็น role ที่ระบบรู้จัก
|
||||
- Action name ต้องเป็น **UPPER_CASE**
|
||||
|
||||
#### 5.3 Version Safety
|
||||
|
||||
* ทุกชุด Workflow DSL ต้องขึ้นกับ version
|
||||
* แก้ไขต้องสร้าง version ใหม่
|
||||
* ไม่ overwrite version เก่า
|
||||
* “Document ที่กำลังอยู่ใน step เดิมยังต้องใช้กฎเดิมได้”
|
||||
- ทุกชุด Workflow DSL ต้องขึ้นกับ version
|
||||
- แก้ไขต้องสร้าง version ใหม่
|
||||
- ไม่ overwrite version เก่า
|
||||
- “Document ที่กำลังอยู่ใน step เดิมยังต้องใช้กฎเดิมได้”
|
||||
|
||||
---
|
||||
|
||||
@@ -240,14 +234,13 @@ interface WorkflowContext {
|
||||
|
||||
```ts
|
||||
class WorkflowEngine {
|
||||
|
||||
load(dsl: string | object): CompiledWorkflow
|
||||
load(dsl: string | object): CompiledWorkflow;
|
||||
|
||||
compile(dsl: string | object): CompiledWorkflow
|
||||
compile(dsl: string | object): CompiledWorkflow;
|
||||
|
||||
evaluate(state: string, action: string, context: WorkflowContext): EvalResult
|
||||
evaluate(state: string, action: string, context: WorkflowContext): EvalResult;
|
||||
|
||||
getAvailableActions(state: string, context: WorkflowContext): string[]
|
||||
getAvailableActions(state: string, context: WorkflowContext): string[];
|
||||
}
|
||||
```
|
||||
|
||||
@@ -328,21 +321,21 @@ flowchart TD
|
||||
|
||||
#### Unit Tests
|
||||
|
||||
* Parse DSL → JSON
|
||||
* Invalid syntax → throw error
|
||||
* Invalid transitions → throw error
|
||||
- Parse DSL → JSON
|
||||
- Invalid syntax → throw error
|
||||
- Invalid transitions → throw error
|
||||
|
||||
#### Integration Tests
|
||||
|
||||
* Evaluate() ผ่าน 20+ cases
|
||||
* RFA ย้อนกลับ
|
||||
* Approve chain
|
||||
* Parallel review
|
||||
- Evaluate() ผ่าน 20+ cases
|
||||
- RFA ย้อนกลับ
|
||||
- Approve chain
|
||||
- Parallel review
|
||||
|
||||
#### Load Tests
|
||||
|
||||
* 1,000 documents running workflow
|
||||
* Evaluate < 20ms ต่อ action
|
||||
- 1,000 documents running workflow
|
||||
- Evaluate < 20ms ต่อ action
|
||||
|
||||
---
|
||||
|
||||
@@ -350,9 +343,9 @@ flowchart TD
|
||||
|
||||
#### Hot Reload Options
|
||||
|
||||
* DSL stored in DB
|
||||
* Cache in Redis
|
||||
* Touched timestamp triggers:
|
||||
- DSL stored in DB
|
||||
- Cache in Redis
|
||||
- Touched timestamp triggers:
|
||||
|
||||
```
|
||||
invalidate cache → recompile
|
||||
@@ -366,9 +359,9 @@ invalidate cache → recompile
|
||||
|
||||
DSL Engine แยกเป็น:
|
||||
|
||||
* `workflow-engine-core` → Pure JS library
|
||||
* `workflow-service` → NestJS module
|
||||
* API public:
|
||||
- `workflow-engine-core` → Pure JS library
|
||||
- `workflow-service` → NestJS module
|
||||
- API public:
|
||||
|
||||
```
|
||||
POST /workflow/evaluate
|
||||
@@ -378,9 +371,9 @@ POST /workflow/compile
|
||||
|
||||
ภายหลังสามารถนำไปวางบน:
|
||||
|
||||
* Kubernetes
|
||||
* Worker Node
|
||||
* API Gateway
|
||||
- Kubernetes
|
||||
- Worker Node
|
||||
- API Gateway
|
||||
|
||||
---
|
||||
|
||||
@@ -394,4 +387,3 @@ POST /workflow/compile
|
||||
✔ Execution API สำหรับ Backend และ Frontend
|
||||
✔ รองรับ Business Workflow ซับซ้อนทั้งหมด
|
||||
✔ Ready สำหรับ Microservice model ในอนาคต
|
||||
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
**อ้างอิง:** Requirements v1.4.3 & FullStackJS Guidelines v1.4.3
|
||||
**Classification:** Internal Technical Documentation
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🎯 **ภาพรวมโครงการ**
|
||||
|
||||
พัฒนา Backend สำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System) ที่มีความปลอดภัยสูง รองรับการทำงานพร้อมกัน (Concurrency) ได้อย่างถูกต้องแม่นยำ มีสถาปัตยกรรมที่ยืดหยุ่นต่อการขยายตัว และรองรับการจัดการเอกสารที่ซับซ้อน มีระบบ Workflow การอนุมัติ และการควบคุมสิทธิ์แบบ RBAC 4 ระดับ พร้อมมาตรการความปลอดภัยที่ทันสมัย
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 📐 **สถาปัตยกรรมระบบ**
|
||||
|
||||
@@ -69,11 +69,11 @@ src/
|
||||
└── database/ # Migrations & Seeds
|
||||
```
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🗓️ **แผนการพัฒนาแบบ Phase-Based**
|
||||
|
||||
- *(Dependency Diagram ถูกละไว้เพื่อประหยัดพื้นที่ เนื่องจากมีการอ้างอิงจากแผนเดิม)*
|
||||
- _(Dependency Diagram ถูกละไว้เพื่อประหยัดพื้นที่ เนื่องจากมีการอ้างอิงจากแผนเดิม)_
|
||||
|
||||
## **Phase 0: Infrastructure & Configuration (สัปดาห์ที่ 1)**
|
||||
|
||||
@@ -82,7 +82,6 @@ src/
|
||||
### **Phase 0: Tasks**
|
||||
|
||||
- **[ ] T0.1 Secure Configuration Setup**
|
||||
|
||||
- [ ] ปรับปรุง `ConfigModule` ให้รองรับการอ่านค่าจาก Environment Variables
|
||||
- [ ] สร้าง Template `docker-compose.override.yml.example` สำหรับ Dev
|
||||
- [ ] Validate Config ด้วย Joi/Zod ตอน Start App (Throw error ถ้าขาด Secrets)
|
||||
@@ -91,7 +90,6 @@ src/
|
||||
- [ ] **Dependencies:** None (Task เริ่มต้น)
|
||||
|
||||
- **[ ] T0.2 Redis & Queue Infrastructure**
|
||||
|
||||
- [ ] Setup Redis Container
|
||||
- [ ] Setup BullMQ Module ใน NestJS สำหรับจัดการ Background Jobs
|
||||
- [ ] Setup Redis Client สำหรับ Distributed Lock (Redlock)
|
||||
@@ -100,7 +98,6 @@ src/
|
||||
- [ ] **Dependencies:** T0.1
|
||||
|
||||
- **[ ] T0.3 Setup Database Connection**
|
||||
|
||||
- [ ] Import SQL Schema v1.4.2 เข้า MariaDB
|
||||
- [ ] Run Seed Data (organizations, users, roles, permissions)
|
||||
- [ ] Configure TypeORM ใน AppModule
|
||||
@@ -110,14 +107,13 @@ src/
|
||||
- [ ] **Dependencies:** T0.1
|
||||
|
||||
- **[ ] T0.4 Setup Git Repository**
|
||||
|
||||
- [ ] สร้าง Repository ใน Gitea (git.np-dms.work)
|
||||
- [ ] Setup .gitignore, README.md, SECURITY.md
|
||||
- [ ] Commit Initial Project
|
||||
- [ ] **Deliverable:** Code อยู่ใน Version Control
|
||||
- [ ] **Dependencies:** T0.1, T0.2, T0.3
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## **Phase 1: Core Foundation & Security (สัปดาห์ที่ 2-3)**
|
||||
|
||||
@@ -126,7 +122,6 @@ src/
|
||||
### **Phase 1: Tasks**
|
||||
|
||||
- **[ ] T1.1 CommonModule - Base Infrastructure**
|
||||
|
||||
- [ ] สร้าง Base Entity (id, created_at, updated_at, deleted_at)
|
||||
- [ ] สร้าง Global Exception Filter (ไม่เปิดเผย sensitive information)
|
||||
- [ ] สร้าง Response Transform Interceptor
|
||||
@@ -141,7 +136,6 @@ src/
|
||||
- [ ] **Dependencies:** T0.2, T0.3
|
||||
|
||||
- **[ ] T1.2 AuthModule - JWT Authentication**
|
||||
|
||||
- [ ] สร้าง Entity: User
|
||||
- [ ] สร้าง AuthService:
|
||||
- [ ] login(username, password) → JWT Token
|
||||
@@ -160,7 +154,6 @@ src/
|
||||
- [ ] **Dependencies:** T1.1, T0.3
|
||||
|
||||
- **[ ] T1.3 UserModule - User Management**
|
||||
|
||||
- [ ] สร้าง Entities: User, Role, Permission, UserRole, UserAssignment, **UserPreference**
|
||||
- [ ] สร้าง UserService CRUD (พร้อม soft delete)
|
||||
- [ ] สร้าง RoleService CRUD
|
||||
@@ -181,7 +174,6 @@ src/
|
||||
- [ ] **Dependencies:** T1.1, T1.2
|
||||
|
||||
- **[ ] T1.4 RBAC Guard - 4-Level Authorization**
|
||||
|
||||
- [ ] สร้าง @RequirePermission() Decorator
|
||||
- [ ] สร้าง RbacGuard ที่ตรวจสอบ 4 ระดับ:
|
||||
- [ ] Global Permissions
|
||||
@@ -195,7 +187,6 @@ src/
|
||||
- [ ] **Dependencies:** T1.1, T1.3
|
||||
|
||||
- **[ ] T1.5 ProjectModule - Base Structures**
|
||||
|
||||
- [ ] สร้าง Entities:
|
||||
- [ ] Organization
|
||||
- [ ] Project
|
||||
@@ -211,7 +202,7 @@ src/
|
||||
- [ ] **Deliverable:** จัดการโครงสร้างโปรเจกต์ได้
|
||||
- [ ] **Dependencies:** T1.1, T1.2, T0.3
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## **Phase 2: High-Integrity Data & File Management (สัปดาห์ที่ 4)**
|
||||
|
||||
@@ -220,7 +211,6 @@ src/
|
||||
### **Phase 2: Tasks**
|
||||
|
||||
- **[ ] T2.1 Virtual Columns for JSON**
|
||||
|
||||
- [ ] ออกแบบ Migration Script สำหรับตารางที่มี JSON Details
|
||||
- [ ] เพิ่ม **Generated Columns (Virtual)** สำหรับฟิลด์ที่ใช้ Search บ่อยๆ (เช่น `project_id`, `type`) พร้อม Index
|
||||
- [ ] **Security:** Implement admin-only access สำหรับ master data
|
||||
@@ -228,7 +218,6 @@ src/
|
||||
- [ ] **Dependencies:** T0.3, T1.1, T1.5
|
||||
|
||||
- **[ ] T2.2 FileStorageService - Two-Phase Storage**
|
||||
|
||||
- [ ] สร้าง Attachment Entity
|
||||
- [ ] สร้าง FileStorageService:
|
||||
- [ ] **Phase 1 (Upload):** API รับไฟล์ → Scan Virus → Save ลง `temp/` → Return `temp_id`
|
||||
@@ -246,18 +235,12 @@ src/
|
||||
- [ ] **Dependencies:** T1.1, T1.4
|
||||
|
||||
- **[ ] T2.3 DocumentNumberingModule - Double-Lock Mechanism**
|
||||
|
||||
- [ ] สร้าง Entities:
|
||||
- [ ] DocumentNumberFormat
|
||||
- [ ] DocumentNumberCounter
|
||||
- [ ] สร้าง DocumentNumberingService:
|
||||
- [ ] generateNextNumber(projectId, orgId, typeId, year) → string
|
||||
- [ ] ใช้ **Double-Lock Mechanism**:
|
||||
1. Acquire **Redis Lock** (Key: `doc_num:{project}:{type}`)
|
||||
2. Read DB & Calculate Next Number
|
||||
3. Update DB with **Optimistic Lock** Check (ใช้ `@VersionColumn()`)
|
||||
4. Release Redis Lock
|
||||
5. Retry on Failure ด้วย exponential backoff
|
||||
- [ ] ใช้ **Double-Lock Mechanism**: 1. Acquire **Redis Lock** (Key: `doc_num:{project}:{type}`) 2. Read DB & Calculate Next Number 3. Update DB with **Optimistic Lock** Check (ใช้ `@VersionColumn()`) 4. Release Redis Lock 5. Retry on Failure ด้วย exponential backoff
|
||||
- [ ] Fallback mechanism เมื่อการขอเลขล้มเหลว
|
||||
- [ ] Format ตาม Template: {ORG_CODE}-{TYPE_CODE}-{YEAR_SHORT}-{SEQ:4}
|
||||
- **ไม่มี Controller** (Internal Service เท่านั้น)
|
||||
@@ -266,7 +249,6 @@ src/
|
||||
- [ ] **Dependencies:** T1.1, T0.3
|
||||
|
||||
- **[ ] T2.4 SecurityModule - Enhanced Security**
|
||||
|
||||
- [ ] สร้าง Input Validation Service:
|
||||
- [ ] XSS Prevention
|
||||
- [ ] SQL Injection Prevention
|
||||
@@ -280,14 +262,13 @@ src/
|
||||
- [ ] **Dependencies:** T1.1
|
||||
|
||||
- **[ ] T2.5 JSON Details & Schema Management**
|
||||
|
||||
- [ ] T2.5.1 JsonSchemaModule - Schema Management: สร้าง Service สำหรับ Validate, get, register JSON schemas
|
||||
- [ ] T2.5.2 DetailsService - Data Processing: สร้าง Service สำหรับ sanitize, transform, compress/decompress JSON
|
||||
- [ ] T2.5.3 JSON Security & Validation: Implement security checks และ validation rules
|
||||
- [ ] **Deliverable:** JSON schema system ทำงานได้
|
||||
- [ ] **Dependencies:** T1.1
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## **Phase 3: Unified Workflow Engine (สัปดาห์ที่ 5-6)**
|
||||
|
||||
@@ -296,7 +277,6 @@ src/
|
||||
### **Phase 3: Tasks**
|
||||
|
||||
- **[ ] T3.1 WorkflowEngineModule (New)**
|
||||
|
||||
- [ ] ออกแบบ Generic Schema สำหรับ Workflow State Machine
|
||||
- [ ] Implement Service: `initializeWorkflow()`, `processAction()`, `getNextStep()`
|
||||
- [ ] รองรับ Logic การ "ข้ามขั้นตอน" และ "ส่งกลับ" ภายใน Engine เดียว
|
||||
@@ -305,7 +285,6 @@ src/
|
||||
- [ ] **Dependencies:** T1.1
|
||||
|
||||
- **[ ] T3.2 CorrespondenceModule - Basic CRUD**
|
||||
|
||||
- [ ] สร้าง Entities (Correspondence, Revision, Recipient, Tag, Reference, Attachment)
|
||||
- [ ] สร้าง CorrespondenceService (Create with Document Numbering, Update with new Revision, Soft Delete)
|
||||
- [ ] สร้าง Controllers (POST/GET/PUT/DELETE /correspondences)
|
||||
@@ -315,7 +294,6 @@ src/
|
||||
- [ ] **Dependencies:** T1.1, T1.2, T1.3, T1.4, T1.5, T2.3, T2.2, T2.5
|
||||
|
||||
- **[ ] T3.3 CorrespondenceModule - Advanced Features**
|
||||
|
||||
- [ ] Implement Status Transitions (DRAFT → SUBMITTED)
|
||||
- [ ] Implement References (Link Documents)
|
||||
- [ ] Implement Search (Basic)
|
||||
@@ -324,7 +302,6 @@ src/
|
||||
- [ ] **Dependencies:** T3.2
|
||||
|
||||
- **[ ] T3.4 Correspondence Integration with Workflow**
|
||||
|
||||
- [ ] เชื่อมต่อ `CorrespondenceService` เข้ากับ `WorkflowEngineModule`
|
||||
- [ ] ย้าย Logic การ Routing เดิมมาใช้ Engine ใหม่
|
||||
- [ ] สร้าง API endpoints สำหรับ Frontend (Templates, Pending Tasks, Bulk Action)
|
||||
@@ -332,7 +309,7 @@ src/
|
||||
- [ ] **Deliverable:** ระบบส่งต่อเอกสารทำงานได้สมบูรณ์ด้วย Unified Engine
|
||||
- [ ] **Dependencies:** T3.1, T3.2
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## **Phase 4: Drawing & Advanced Workflows (สัปดาห์ที่ 7-8)**
|
||||
|
||||
@@ -341,7 +318,6 @@ src/
|
||||
### **Phase 4: Tasks**
|
||||
|
||||
- **[ ] T4.1 DrawingModule - Contract Drawings**
|
||||
|
||||
- [ ] สร้าง Entities (ContractDrawing, Volume, Category, SubCategory, Attachment)
|
||||
- [ ] สร้าง ContractDrawingService CRUD
|
||||
- [ ] สร้าง Controllers (GET/POST /drawings/contract)
|
||||
@@ -350,7 +326,6 @@ src/
|
||||
- [ ] **Dependencies:** T1.1, T1.2, T1.4, T1.5, T2.2
|
||||
|
||||
- **[ ] T4.2 DrawingModule - Shop Drawings**
|
||||
|
||||
- [ ] สร้าง Entities (ShopDrawing, Revision, Main/SubCategory, ContractRef, RevisionAttachment)
|
||||
- [ ] สร้าง ShopDrawingService CRUD (รวมการสร้าง Revision)
|
||||
- [ ] สร้าง Controllers (GET/POST /drawings/shop, /drawings/shop/:id/revisions)
|
||||
@@ -360,7 +335,6 @@ src/
|
||||
- [ ] **Dependencies:** T4.1
|
||||
|
||||
- **[ ] T5.1 RfaModule with Unified Workflow**
|
||||
|
||||
- [ ] สร้าง Entities (Rfa, RfaRevision, RfaItem, RfaWorkflowTemplate/Step)
|
||||
- [ ] สร้าง RfaService (Create RFA, Link Shop Drawings)
|
||||
- [ ] Implement RFA Workflow โดยใช้ Configuration ของ `WorkflowEngineModule`
|
||||
@@ -369,7 +343,7 @@ src/
|
||||
- [ ] **Deliverable:** RFA Workflow ทำงานได้ด้วย Unified Engine
|
||||
- [ ] **Dependencies:** T3.2, T4.2, T2.5, T6.2
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## **Phase 5: Workflow Systems & Resilience (สัปดาห์ที่ 8-9)**
|
||||
|
||||
@@ -378,7 +352,6 @@ src/
|
||||
### **Phase 5: Tasks**
|
||||
|
||||
- **[ ] T5.2 CirculationModule - Internal Routing**
|
||||
|
||||
- [ ] สร้าง Entities (Circulation, Template, Routing, Attachment)
|
||||
- [ ] สร้าง CirculationService (Create 1:1 with Correspondence, Assign User, Complete/Close Step)
|
||||
- [ ] สร้าง Controllers (POST/GET /circulations, POST /circulations/:id/steps/...)
|
||||
@@ -387,7 +360,6 @@ src/
|
||||
- [ ] **Dependencies:** T3.2, T2.5, T6.2
|
||||
|
||||
- **[ ] T5.3 TransmittalModule - Document Forwarding**
|
||||
|
||||
- [ ] สร้าง Entities (Transmittal, TransmittalItem)
|
||||
- [ ] สร้าง TransmittalService (Create Correspondence + Transmittal, Link Multiple Correspondences)
|
||||
- [ ] สร้าง Controllers (POST/GET /transmittals)
|
||||
@@ -395,7 +367,7 @@ src/
|
||||
- [ ] **Deliverable:** สร้าง Transmittal ได้
|
||||
- [ ] **Dependencies:** T3.2
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## **Phase 6: Notification & Resilience (สัปดาห์ที่ 9)**
|
||||
|
||||
@@ -404,7 +376,6 @@ src/
|
||||
### **Phase 6: Tasks**
|
||||
|
||||
- **[ ] T6.1 SearchModule - Elasticsearch Integration**
|
||||
|
||||
- [ ] Setup Elasticsearch Container
|
||||
- [ ] สร้าง SearchService (index/update/delete documents, search)
|
||||
- [ ] Index ทุก Document Type
|
||||
@@ -414,7 +385,6 @@ src/
|
||||
- [ ] **Dependencies:** T3.2, T5.1, T4.2, T5.2, T5.3
|
||||
|
||||
- **[ ] T6.2 Notification Queue & Digest**
|
||||
|
||||
- [ ] สร้าง NotificationService (sendEmail/Line/System)
|
||||
- [ ] **Producer:** Push Event ลง BullMQ Queue
|
||||
- [ ] **Consumer:** จัดกลุ่ม Notification (Digest Message) และส่งผ่าน Email/Line
|
||||
@@ -425,7 +395,6 @@ src/
|
||||
- [ ] **Dependencies:** T1.1, T6.4
|
||||
|
||||
- **[ ] T6.3 MonitoringModule - Observability**
|
||||
|
||||
- [ ] สร้าง Health Check Controller (GET /health)
|
||||
- [ ] สร้าง Metrics Service (API response times, Error rates)
|
||||
- [ ] สร้าง Performance Interceptor (Track request duration)
|
||||
@@ -434,7 +403,6 @@ src/
|
||||
- [ ] **Dependencies:** T1.1
|
||||
|
||||
- **[ ] T6.4 ResilienceModule - Circuit Breaker & Retry**
|
||||
|
||||
- [ ] สร้าง Circuit Breaker Service (@CircuitBreaker() decorator)
|
||||
- [ ] สร้าง Retry Service (@Retry() decorator)
|
||||
- [ ] สร้าง Fallback Strategies
|
||||
@@ -443,13 +411,12 @@ src/
|
||||
- [ ] **Dependencies:** T1.1
|
||||
|
||||
- **[ ] T6.5 Data Partitioning Strategy**
|
||||
|
||||
- [ ] ออกแบบ Table Partitioning สำหรับ `audit_logs` และ `notifications` (แบ่งตาม Range: Year)
|
||||
- [ ] เขียน Raw SQL Migration สำหรับสร้าง Partition Table
|
||||
- [ ] **Deliverable:** Database Performance และ Scalability ดีขึ้น
|
||||
- [ ] **Dependencies:** T0.3
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## **Phase 7: Testing & Hardening (สัปดาห์ที่ 10-12)**
|
||||
|
||||
@@ -458,21 +425,18 @@ src/
|
||||
### **Phase 7: Tasks**
|
||||
|
||||
- **[ ] T7.1 Concurrency Testing**
|
||||
|
||||
- [ ] เขียน Test Scenarios ยิง Request ขอเลขที่เอกสารพร้อมกัน 100 Request (ต้องไม่ซ้ำและไม่ข้าม)
|
||||
- [ ] ทดสอบ Optimistic Lock ทำงานถูกต้องเมื่อ Redis ถูกปิด
|
||||
- [ ] ทดสอบ File Upload พร้อมกันหลายไฟล์
|
||||
- [ ] **Deliverable:** ระบบทนทานต่อ Concurrency Issues
|
||||
|
||||
- **[ ] T7.2 Transaction Integrity Testing**
|
||||
|
||||
- [ ] ทดสอบ Upload ไฟล์แล้ว Kill Process ก่อน Commit
|
||||
- [ ] ทดสอบ Two-Phase File Storage ทำงานถูกต้อง
|
||||
- [ ] ทดสอบ Database Transaction Rollback Scenarios
|
||||
- [ ] **Deliverable:** Data Integrity รับประกันได้
|
||||
|
||||
- **[ ] T7.3 Security & Idempotency Test**
|
||||
|
||||
- [ ] ทดสอบ Replay Attack โดยใช้ `Idempotency-Key` ซ้ำ
|
||||
- [ ] ทดสอบ Maintenance Mode Block API ได้จริง
|
||||
- [ ] ทดสอบ RBAC 4-Level ทำงานถูกต้อง 100%
|
||||
@@ -485,7 +449,6 @@ src/
|
||||
- **[ ] T7.6 E2E Testing**
|
||||
|
||||
- **[ ] T7.7 Performance Testing**
|
||||
|
||||
- [ ] Load Testing: 100 concurrent users
|
||||
- [ ] **(สำคัญ)** การจูนและทดสอบ Load Test จะต้องทำในสภาพแวดล้อมที่จำลอง Spec ของ QNAP Server (TS-473A, AMD Ryzen V1500B) เพื่อให้ได้ค่า Response Time และ Connection Pool ที่เที่ยงตรง
|
||||
- [ ] Stress Testing
|
||||
@@ -493,19 +456,17 @@ src/
|
||||
- [ ] **Deliverable:** Performance targets บรรลุ
|
||||
|
||||
- **[ ] T7.8 Security Testing**
|
||||
|
||||
- [ ] Penetration Testing (OWASP Top 10)
|
||||
- [ ] Security Audit (Code review, Dependency scanning)
|
||||
- [ ] File Upload Security Testing
|
||||
- [ ] **Deliverable:** Security tests ผ่าน
|
||||
|
||||
- **[ ] T7.9 Performance Optimization**
|
||||
|
||||
- [ ] Implement Caching (Master Data, User Permissions, Search Results)
|
||||
- [ ] Database Optimization (Review Indexes, Query Optimization, Pagination)
|
||||
- [ ] **Deliverable:** Response Time < 200ms (90th percentile)
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## **Phase 8: Documentation & Deployment (สัปดาห์ที่ 14)**
|
||||
|
||||
@@ -520,12 +481,12 @@ src/
|
||||
- **[ ] T8.5 Production Deployment**
|
||||
- **[ ] T8.6 Handover to Frontend Team**
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 📊 **สรุป Timeline**
|
||||
|
||||
| Phase | ระยะเวลา | จำนวนงาน | Output หลัก |
|
||||
| :------ | :----------- | :----------- | :--------------------------------------------- |
|
||||
| Phase | ระยะเวลา | จำนวนงาน | Output หลัก |
|
||||
| :------ | :------------- | :----------- | :--------------------------------------------- |
|
||||
| Phase 0 | 1 สัปดาห์ | 4 | Infrastructure Ready + Security Base |
|
||||
| Phase 1 | 2 สัปดาห์ | 5 | Auth & User Management + RBAC + Idempotency |
|
||||
| Phase 2 | 1 สัปดาห์ | 5 | High-Integrity Data & File Management |
|
||||
@@ -547,6 +508,6 @@ src/
|
||||
- **Classification:** Internal Technical Documentation
|
||||
- **Approved By:** Nattanin
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
`End of Backend Development Plan v1.4.3`
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# “Phase 6A + Technical Design Document : Workflow DSL (Mini-Language)”**
|
||||
# “Phase 6A + Technical Design Document : Workflow DSL (Mini-Language)”\*\*
|
||||
|
||||
ออกแบบสำหรับระบบ Workflow Engine กลางของโครงการ
|
||||
**ไม่มีโค้ดผูกกับ Framework** เพื่อให้สามารถนำไป Implement ใน NestJS หรือ Microservice ใด ๆ ได้
|
||||
|
||||
@@ -10,20 +11,19 @@
|
||||
|
||||
ใน Phase นี้ จะเริ่มสร้าง “Workflow DSL (Domain-Specific Language)” สำหรับนิยามกฎการเดินงาน (Workflow Transition Rules) ให้สามารถ:
|
||||
|
||||
* แยก **Business Workflow Logic** ออกจาก Source Code
|
||||
* แก้ไขกฎ Workflow ได้โดย **ไม่ต้องแก้โค้ดและไม่ต้อง Deploy ใหม่**
|
||||
* รองรับ Document หลายประเภท เช่น
|
||||
- แยก **Business Workflow Logic** ออกจาก Source Code
|
||||
- แก้ไขกฎ Workflow ได้โดย **ไม่ต้องแก้โค้ดและไม่ต้อง Deploy ใหม่**
|
||||
- รองรับ Document หลายประเภท เช่น
|
||||
- Correspondence
|
||||
- RFA
|
||||
- Internal Circulation
|
||||
- Document Transmittal
|
||||
|
||||
* Correspondence
|
||||
* RFA
|
||||
* Internal Circulation
|
||||
* Document Transmittal
|
||||
* รองรับ Multi-step routing, skip, reject, rollback, parallel assignments
|
||||
* สามารถนำไปใช้งานทั้งใน
|
||||
|
||||
* Backend (NestJS)
|
||||
* Frontend (UI Driven)
|
||||
* External Microservices
|
||||
- รองรับ Multi-step routing, skip, reject, rollback, parallel assignments
|
||||
- สามารถนำไปใช้งานทั้งใน
|
||||
- Backend (NestJS)
|
||||
- Frontend (UI Driven)
|
||||
- External Microservices
|
||||
|
||||
---
|
||||
|
||||
@@ -35,12 +35,12 @@
|
||||
|
||||
### 🧩 Output ของ Phase 6A
|
||||
|
||||
* DSL Specification (Grammar)
|
||||
* JSON Schema for Workflow Definition
|
||||
* Workflow Rule Interpreter (Parser + Executor)
|
||||
* Validation Engine (Compile-time and Runtime)
|
||||
* Storage (DB Table / Registry)
|
||||
* Execution API:
|
||||
- DSL Specification (Grammar)
|
||||
- JSON Schema for Workflow Definition
|
||||
- Workflow Rule Interpreter (Parser + Executor)
|
||||
- Validation Engine (Compile-time and Runtime)
|
||||
- Storage (DB Table / Registry)
|
||||
- Execution API:
|
||||
|
||||
| Action | Description |
|
||||
| -------------------------------- | ------------------------------- |
|
||||
@@ -59,22 +59,22 @@
|
||||
|
||||
#### Functional Requirements
|
||||
|
||||
* นิยาม Workflow เป็นภาษาคล้าย State Machine
|
||||
* แต่ละเอกสารมี **State, Actions, Entry/Exit Events**
|
||||
* สามารถมี:
|
||||
|
||||
* Required approvals
|
||||
* Conditional transition
|
||||
* Auto-transition
|
||||
* Parallel approval
|
||||
* Return/rollback
|
||||
- นิยาม Workflow เป็นภาษาคล้าย State Machine
|
||||
- แต่ละเอกสารมี **State, Actions, Entry/Exit Events**
|
||||
- สามารถมี:
|
||||
- Required approvals
|
||||
- Conditional transition
|
||||
- Auto-transition
|
||||
- Parallel approval
|
||||
- Return/rollback
|
||||
|
||||
####
|
||||
* Running time: < 20ms ต่อคำสั่ง
|
||||
* Hot reload ไม่ต้อง Compile ใหม่ทั้ง Backend
|
||||
* DSL ต้อง Debug ได้ง่าย
|
||||
* ต้อง Versioned
|
||||
* ต้องรองรับ Audit 100%
|
||||
|
||||
- Running time: < 20ms ต่อคำสั่ง
|
||||
- Hot reload ไม่ต้อง Compile ใหม่ทั้ง Backend
|
||||
- DSL ต้อง Debug ได้ง่าย
|
||||
- ต้อง Versioned
|
||||
- ต้องรองรับ Audit 100%
|
||||
|
||||
---
|
||||
|
||||
@@ -122,12 +122,8 @@ states:
|
||||
"transitions": {
|
||||
"SUBMIT": {
|
||||
"to": "IN_REVIEW",
|
||||
"requirements": [
|
||||
{ "role": "ENGINEER" }
|
||||
],
|
||||
"events": [
|
||||
{ "type": "notify", "target": "reviewer" }
|
||||
]
|
||||
"requirements": [{ "role": "ENGINEER" }],
|
||||
"events": [{ "type": "notify", "target": "reviewer" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -136,9 +132,7 @@ states:
|
||||
"APPROVE": { "to": "APPROVED" },
|
||||
"REJECT": {
|
||||
"to": "DRAFT",
|
||||
"events": [
|
||||
{ "type": "notify", "target": "creator" }
|
||||
]
|
||||
"events": [{ "type": "notify", "target": "creator" }]
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -162,14 +156,14 @@ version = "version" ":" number ;
|
||||
states = "states:" state_list ;
|
||||
state_list = { state } ;
|
||||
|
||||
state = "- name:" identifier
|
||||
[ "initial:" boolean ]
|
||||
state = "- name:" identifier
|
||||
[ "initial:" boolean ]
|
||||
[ "terminal:" boolean ]
|
||||
[ "on:" transition_list ] ;
|
||||
|
||||
transition_list = { transition } ;
|
||||
|
||||
transition = action ":"
|
||||
transition = action ":"
|
||||
indent "to:" identifier
|
||||
[ indent "require:" requirements ]
|
||||
[ indent "events:" event_list ] ;
|
||||
@@ -186,23 +180,23 @@ event = "- notify:" identifier ;
|
||||
|
||||
#### 5.1 State Rules
|
||||
|
||||
* ต้องมีอย่างน้อย 1 state ที่ `initial: true`
|
||||
* หาก `terminal: true` → ต้องไม่มี transition ต่อไป
|
||||
- ต้องมีอย่างน้อย 1 state ที่ `initial: true`
|
||||
- หาก `terminal: true` → ต้องไม่มี transition ต่อไป
|
||||
|
||||
#### 5.2 Transition Rules
|
||||
|
||||
ตรวจสอบว่า:
|
||||
|
||||
* `to` ชี้ไปยัง state ที่มีอยู่
|
||||
* `require.role` ต้องเป็น role ที่ระบบรู้จัก
|
||||
* Action name ต้องเป็น **UPPER_CASE**
|
||||
- `to` ชี้ไปยัง state ที่มีอยู่
|
||||
- `require.role` ต้องเป็น role ที่ระบบรู้จัก
|
||||
- Action name ต้องเป็น **UPPER_CASE**
|
||||
|
||||
#### 5.3 Version Safety
|
||||
|
||||
* ทุกชุด Workflow DSL ต้องขึ้นกับ version
|
||||
* แก้ไขต้องสร้าง version ใหม่
|
||||
* ไม่ overwrite version เก่า
|
||||
* “Document ที่กำลังอยู่ใน step เดิมยังต้องใช้กฎเดิมได้”
|
||||
- ทุกชุด Workflow DSL ต้องขึ้นกับ version
|
||||
- แก้ไขต้องสร้าง version ใหม่
|
||||
- ไม่ overwrite version เก่า
|
||||
- “Document ที่กำลังอยู่ใน step เดิมยังต้องใช้กฎเดิมได้”
|
||||
|
||||
---
|
||||
|
||||
@@ -240,14 +234,13 @@ interface WorkflowContext {
|
||||
|
||||
```ts
|
||||
class WorkflowEngine {
|
||||
|
||||
load(dsl: string | object): CompiledWorkflow
|
||||
load(dsl: string | object): CompiledWorkflow;
|
||||
|
||||
compile(dsl: string | object): CompiledWorkflow
|
||||
compile(dsl: string | object): CompiledWorkflow;
|
||||
|
||||
evaluate(state: string, action: string, context: WorkflowContext): EvalResult
|
||||
evaluate(state: string, action: string, context: WorkflowContext): EvalResult;
|
||||
|
||||
getAvailableActions(state: string, context: WorkflowContext): string[]
|
||||
getAvailableActions(state: string, context: WorkflowContext): string[];
|
||||
}
|
||||
```
|
||||
|
||||
@@ -328,21 +321,21 @@ flowchart TD
|
||||
|
||||
#### Unit Tests
|
||||
|
||||
* Parse DSL → JSON
|
||||
* Invalid syntax → throw error
|
||||
* Invalid transitions → throw error
|
||||
- Parse DSL → JSON
|
||||
- Invalid syntax → throw error
|
||||
- Invalid transitions → throw error
|
||||
|
||||
#### Integration Tests
|
||||
|
||||
* Evaluate() ผ่าน 20+ cases
|
||||
* RFA ย้อนกลับ
|
||||
* Approve chain
|
||||
* Parallel review
|
||||
- Evaluate() ผ่าน 20+ cases
|
||||
- RFA ย้อนกลับ
|
||||
- Approve chain
|
||||
- Parallel review
|
||||
|
||||
#### Load Tests
|
||||
|
||||
* 1,000 documents running workflow
|
||||
* Evaluate < 20ms ต่อ action
|
||||
- 1,000 documents running workflow
|
||||
- Evaluate < 20ms ต่อ action
|
||||
|
||||
---
|
||||
|
||||
@@ -350,9 +343,9 @@ flowchart TD
|
||||
|
||||
#### Hot Reload Options
|
||||
|
||||
* DSL stored in DB
|
||||
* Cache in Redis
|
||||
* Touched timestamp triggers:
|
||||
- DSL stored in DB
|
||||
- Cache in Redis
|
||||
- Touched timestamp triggers:
|
||||
|
||||
```
|
||||
invalidate cache → recompile
|
||||
@@ -366,9 +359,9 @@ invalidate cache → recompile
|
||||
|
||||
DSL Engine แยกเป็น:
|
||||
|
||||
* `workflow-engine-core` → Pure JS library
|
||||
* `workflow-service` → NestJS module
|
||||
* API public:
|
||||
- `workflow-engine-core` → Pure JS library
|
||||
- `workflow-service` → NestJS module
|
||||
- API public:
|
||||
|
||||
```
|
||||
POST /workflow/evaluate
|
||||
@@ -378,9 +371,9 @@ POST /workflow/compile
|
||||
|
||||
ภายหลังสามารถนำไปวางบน:
|
||||
|
||||
* Kubernetes
|
||||
* Worker Node
|
||||
* API Gateway
|
||||
- Kubernetes
|
||||
- Worker Node
|
||||
- API Gateway
|
||||
|
||||
---
|
||||
|
||||
@@ -394,4 +387,3 @@ POST /workflow/compile
|
||||
✔ Execution API สำหรับ Backend และ Frontend
|
||||
✔ รองรับ Business Workflow ซับซ้อนทั้งหมด
|
||||
✔ Ready สำหรับ Microservice model ในอนาคต
|
||||
|
||||
|
||||
@@ -353,7 +353,6 @@
|
||||
### **Phase 0: Tasks**
|
||||
|
||||
- **[ ] T0.1 Secure Configuration Setup**
|
||||
|
||||
- [ ] ปรับปรุง `ConfigModule` ให้รองรับการอ่านค่าจาก Environment Variables
|
||||
- [ ] สร้าง Template `docker-compose.override.yml.example` สำหรับ Dev
|
||||
- [ ] Validate Config ด้วย Joi/Zod ตอน Start App (Throw error ถ้าขาด Secrets)
|
||||
@@ -362,7 +361,6 @@
|
||||
- [ ] **Dependencies:** None (Task เริ่มต้น)
|
||||
|
||||
- **[ ] T0.2 Redis & Queue Infrastructure**
|
||||
|
||||
- [ ] Setup Redis Container
|
||||
- [ ] Setup BullMQ Module ใน NestJS สำหรับจัดการ Background Jobs
|
||||
- [ ] Setup Redis Client สำหรับ Distributed Lock (Redlock)
|
||||
@@ -371,7 +369,6 @@
|
||||
- [ ] **Dependencies:** T0.1
|
||||
|
||||
- **[ ] T0.3 Setup Database Connection**
|
||||
|
||||
- [ ] Import SQL Schema v1.4.2 เข้า MariaDB
|
||||
- [ ] Run Seed Data (organizations, users, roles, permissions)
|
||||
- [ ] Configure TypeORM ใน AppModule
|
||||
@@ -381,7 +378,6 @@
|
||||
- [ ] **Dependencies:** T0.1
|
||||
|
||||
- **[ ] T0.4 Setup Git Repository**
|
||||
|
||||
- [ ] สร้าง Repository ใน Gitea (git.np-dms.work)
|
||||
- [ ] Setup .gitignore, README.md, SECURITY.md
|
||||
- [ ] Commit Initial Project
|
||||
@@ -397,7 +393,6 @@
|
||||
### **Phase 1: Tasks**
|
||||
|
||||
- **[ ] T1.1 CommonModule - Base Infrastructure**
|
||||
|
||||
- [ ] สร้าง Base Entity (id, created_at, updated_at, deleted_at)
|
||||
- [ ] สร้าง Global Exception Filter (ไม่เปิดเผย sensitive information)
|
||||
- [ ] สร้าง Response Transform Interceptor
|
||||
@@ -412,7 +407,6 @@
|
||||
- [ ] **Dependencies:** T0.2, T0.3
|
||||
|
||||
- **[ ] T1.2 AuthModule - JWT Authentication**
|
||||
|
||||
- [ ] สร้าง Entity: User
|
||||
- [ ] สร้าง AuthService:
|
||||
- [ ] login(username, password) → JWT Token
|
||||
@@ -431,7 +425,6 @@
|
||||
- [ ] **Dependencies:** T1.1, T0.3
|
||||
|
||||
- **[ ] T1.3 UserModule - User Management**
|
||||
|
||||
- [ ] สร้าง Entities: User, Role, Permission, UserRole, UserAssignment, **UserPreference**
|
||||
- [ ] สร้าง UserService CRUD (พร้อม soft delete)
|
||||
- [ ] สร้าง RoleService CRUD
|
||||
@@ -452,7 +445,6 @@
|
||||
- [ ] **Dependencies:** T1.1, T1.2
|
||||
|
||||
- **[ ] T1.4 RBAC Guard - 4-Level Authorization**
|
||||
|
||||
- [ ] สร้าง @RequirePermission() Decorator
|
||||
- [ ] สร้าง RbacGuard ที่ตรวจสอบ 4 ระดับ:
|
||||
- [ ] Global Permissions
|
||||
@@ -466,7 +458,6 @@
|
||||
- [ ] **Dependencies:** T1.1, T1.3
|
||||
|
||||
- **[ ] T1.5 ProjectModule - Base Structures**
|
||||
|
||||
- [ ] สร้าง Entities:
|
||||
- [ ] Organization
|
||||
- [ ] Project
|
||||
@@ -491,7 +482,6 @@
|
||||
### **Phase 2: Tasks**
|
||||
|
||||
- **[ ] T2.1 Virtual Columns for JSON**
|
||||
|
||||
- [ ] ออกแบบ Migration Script สำหรับตารางที่มี JSON Details
|
||||
- [ ] เพิ่ม **Generated Columns (Virtual)** สำหรับฟิลด์ที่ใช้ Search บ่อยๆ (เช่น `project_id`, `type`) พร้อม Index
|
||||
- [ ] **Security:** Implement admin-only access สำหรับ master data
|
||||
@@ -499,7 +489,6 @@
|
||||
- [ ] **Dependencies:** T0.3, T1.1, T1.5
|
||||
|
||||
- **[ ] T2.2 FileStorageService - Two-Phase Storage**
|
||||
|
||||
- [ ] สร้าง Attachment Entity
|
||||
- [ ] สร้าง FileStorageService:
|
||||
- [ ] **Phase 1 (Upload):** API รับไฟล์ → Scan Virus → Save ลง `temp/` → Return `temp_id`
|
||||
@@ -517,7 +506,6 @@
|
||||
- [ ] **Dependencies:** T1.1, T1.4
|
||||
|
||||
- **[ ] T2.3 DocumentNumberingModule - Double-Lock Mechanism**
|
||||
|
||||
- [ ] สร้าง Entities:
|
||||
- [ ] DocumentNumberFormat
|
||||
- [ ] DocumentNumberCounter
|
||||
@@ -538,7 +526,6 @@
|
||||
- [ ] **Deliverable:** Flexible Numbering System
|
||||
|
||||
- **[ ] T2.4 SecurityModule - Enhanced Security**
|
||||
|
||||
- [ ] สร้าง Input Validation Service:
|
||||
- [ ] XSS Prevention
|
||||
- [ ] SQL Injection Prevention
|
||||
@@ -552,7 +539,6 @@
|
||||
- [ ] **Dependencies:** T1.1
|
||||
|
||||
- **[ ] T2.5 JSON Details & Schema Management**
|
||||
|
||||
- [ ] T2.5.1 JsonSchemaModule - Schema Management: สร้าง Service สำหรับ Validate, get, register JSON schemas
|
||||
- [ ] T2.5.2 DetailsService - Data Processing: สร้าง Service สำหรับ sanitize, transform, compress/decompress JSON
|
||||
- [ ] T2.5.3 JSON Security & Validation: Implement security checks และ validation rules
|
||||
@@ -654,11 +640,7 @@ export class JsonSchemaService {
|
||||
this.registerCustomValidators();
|
||||
}
|
||||
|
||||
async validateData(
|
||||
schemaName: string,
|
||||
data: any,
|
||||
options: ValidationOptions = {}
|
||||
): Promise<ValidationResult> {
|
||||
async validateData(schemaName: string, data: any, options: ValidationOptions = {}): Promise<ValidationResult> {
|
||||
const schema = await this.getSchema(schemaName);
|
||||
const validate = this.ajv.compile(schema);
|
||||
|
||||
@@ -682,11 +664,7 @@ export class JsonSchemaService {
|
||||
};
|
||||
}
|
||||
|
||||
private async sanitizeData(
|
||||
data: any,
|
||||
schema: any,
|
||||
options: ValidationOptions
|
||||
): Promise<any> {
|
||||
private async sanitizeData(data: any, schema: any, options: ValidationOptions): Promise<any> {
|
||||
const sanitized = { ...data };
|
||||
|
||||
// Remove unknown properties if not allowed
|
||||
@@ -745,10 +723,7 @@ export class VirtualColumnService {
|
||||
private configService: ConfigService
|
||||
) {}
|
||||
|
||||
async setupVirtualColumns(
|
||||
tableName: string,
|
||||
schemaConfig: VirtualColumnConfig[]
|
||||
): Promise<void> {
|
||||
async setupVirtualColumns(tableName: string, schemaConfig: VirtualColumnConfig[]): Promise<void> {
|
||||
const connection = this.dataSource.manager.connection;
|
||||
|
||||
for (const config of schemaConfig) {
|
||||
@@ -756,10 +731,7 @@ export class VirtualColumnService {
|
||||
}
|
||||
}
|
||||
|
||||
private async createVirtualColumn(
|
||||
tableName: string,
|
||||
config: VirtualColumnConfig
|
||||
): Promise<void> {
|
||||
private async createVirtualColumn(tableName: string, config: VirtualColumnConfig): Promise<void> {
|
||||
const columnDefinition = this.generateColumnDefinition(config);
|
||||
|
||||
const sql = `
|
||||
@@ -782,10 +754,7 @@ export class VirtualColumnService {
|
||||
return `${dataType} GENERATED ALWAYS AS (JSON_UNQUOTE(JSON_EXTRACT(details, '${jsonPath}'))) VIRTUAL`;
|
||||
}
|
||||
|
||||
private async createIndex(
|
||||
tableName: string,
|
||||
config: VirtualColumnConfig
|
||||
): Promise<void> {
|
||||
private async createIndex(tableName: string, config: VirtualColumnConfig): Promise<void> {
|
||||
const indexName = `idx_${tableName}_${config.column_name}`;
|
||||
const sql = `
|
||||
CREATE ${config.index_type} INDEX ${indexName}
|
||||
@@ -902,13 +871,7 @@ const rfaDwgSchema: UiSchema = {
|
||||
widget: 'select',
|
||||
title: 'Discipline',
|
||||
enum: ['CIVIL', 'STRUCTURAL', 'MECHANICAL', 'ELECTRICAL', 'PLUMBING'],
|
||||
enumNames: [
|
||||
'Civil',
|
||||
'Structural',
|
||||
'Mechanical',
|
||||
'Electrical',
|
||||
'Plumbing',
|
||||
],
|
||||
enumNames: ['Civil', 'Structural', 'Mechanical', 'Electrical', 'Plumbing'],
|
||||
},
|
||||
drawingReferences: {
|
||||
type: 'array',
|
||||
@@ -941,21 +904,11 @@ const rfaDwgSchema: UiSchema = {
|
||||
```typescript
|
||||
@Injectable()
|
||||
export class SchemaMigrationService {
|
||||
async migrateData(
|
||||
entityType: string,
|
||||
entityId: string,
|
||||
targetVersion: number
|
||||
): Promise<MigrationResult> {
|
||||
async migrateData(entityType: string, entityId: string, targetVersion: number): Promise<MigrationResult> {
|
||||
const currentData = await this.getCurrentData(entityType, entityId);
|
||||
const currentVersion = await this.getCurrentSchemaVersion(
|
||||
entityType,
|
||||
entityId
|
||||
);
|
||||
const currentVersion = await this.getCurrentSchemaVersion(entityType, entityId);
|
||||
|
||||
const migrationPath = await this.findMigrationPath(
|
||||
currentVersion,
|
||||
targetVersion
|
||||
);
|
||||
const migrationPath = await this.findMigrationPath(currentVersion, targetVersion);
|
||||
|
||||
let migratedData = currentData;
|
||||
|
||||
@@ -964,24 +917,13 @@ export class SchemaMigrationService {
|
||||
}
|
||||
|
||||
// Validate migrated data against target schema
|
||||
const validationResult = await this.validateAgainstSchema(
|
||||
migratedData,
|
||||
targetVersion
|
||||
);
|
||||
const validationResult = await this.validateAgainstSchema(migratedData, targetVersion);
|
||||
|
||||
if (!validationResult.isValid) {
|
||||
throw new MigrationError(
|
||||
'MIGRATION_VALIDATION_FAILED',
|
||||
validationResult.errors
|
||||
);
|
||||
throw new MigrationError('MIGRATION_VALIDATION_FAILED', validationResult.errors);
|
||||
}
|
||||
|
||||
await this.saveMigratedData(
|
||||
entityType,
|
||||
entityId,
|
||||
migratedData,
|
||||
targetVersion
|
||||
);
|
||||
await this.saveMigratedData(entityType, entityId, migratedData, targetVersion);
|
||||
|
||||
return {
|
||||
success: true,
|
||||
@@ -991,10 +933,7 @@ export class SchemaMigrationService {
|
||||
};
|
||||
}
|
||||
|
||||
private async applyMigrationStep(
|
||||
step: MigrationStep,
|
||||
data: any
|
||||
): Promise<any> {
|
||||
private async applyMigrationStep(step: MigrationStep, data: any): Promise<any> {
|
||||
switch (step.type) {
|
||||
case 'FIELD_RENAME':
|
||||
return this.renameField(data, step.config);
|
||||
@@ -1050,11 +989,7 @@ const migrationSteps = [
|
||||
```typescript
|
||||
@Injectable()
|
||||
export class JsonSecurityService {
|
||||
async applyFieldLevelSecurity(
|
||||
data: any,
|
||||
schema: any,
|
||||
userContext: UserContext
|
||||
): Promise<any> {
|
||||
async applyFieldLevelSecurity(data: any, schema: any, userContext: UserContext): Promise<any> {
|
||||
const securedData = { ...data };
|
||||
const securityRules = await this.getSecurityRules(schema.name);
|
||||
|
||||
@@ -1081,10 +1016,7 @@ export class JsonSecurityService {
|
||||
for (const fieldPath of sensitiveFields) {
|
||||
const fieldValue = this.getFieldValue(data, fieldPath);
|
||||
if (fieldValue) {
|
||||
const encrypted = await this.cryptoService.encrypt(
|
||||
fieldValue,
|
||||
'field-level'
|
||||
);
|
||||
const encrypted = await this.cryptoService.encrypt(fieldValue, 'field-level');
|
||||
this.setFieldValue(encryptedData, fieldPath, encrypted);
|
||||
}
|
||||
}
|
||||
@@ -1129,15 +1061,8 @@ export class JsonSecurityService {
|
||||
export class JsonSchemaController {
|
||||
@Post('validate/:schemaName')
|
||||
@RequirePermission('schema.validate')
|
||||
async validateData(
|
||||
@Param('schemaName') schemaName: string,
|
||||
@Body() dto: ValidateDataDto
|
||||
): Promise<ValidationResult> {
|
||||
return this.jsonSchemaService.validateData(
|
||||
schemaName,
|
||||
dto.data,
|
||||
dto.options
|
||||
);
|
||||
async validateData(@Param('schemaName') schemaName: string, @Body() dto: ValidateDataDto): Promise<ValidationResult> {
|
||||
return this.jsonSchemaService.validateData(schemaName, dto.data, dto.options);
|
||||
}
|
||||
|
||||
@Post('schemas')
|
||||
@@ -1153,18 +1078,12 @@ export class JsonSchemaController {
|
||||
@Param('entityId') entityId: string,
|
||||
@Body() dto: MigrateDataDto
|
||||
): Promise<MigrationResult> {
|
||||
return this.migrationService.migrateData(
|
||||
entityType,
|
||||
entityId,
|
||||
dto.targetVersion
|
||||
);
|
||||
return this.migrationService.migrateData(entityType, entityId, dto.targetVersion);
|
||||
}
|
||||
|
||||
@Get('ui-schema/:schemaName')
|
||||
@RequirePermission('schema.view')
|
||||
async getUiSchema(
|
||||
@Param('schemaName') schemaName: string
|
||||
): Promise<UiSchema> {
|
||||
async getUiSchema(@Param('schemaName') schemaName: string): Promise<UiSchema> {
|
||||
return this.schemaService.getUiSchema(schemaName);
|
||||
}
|
||||
}
|
||||
@@ -1186,32 +1105,22 @@ export class CorrespondenceService {
|
||||
private detailsService: DetailsService
|
||||
) {}
|
||||
|
||||
async createCorrespondence(
|
||||
dto: CreateCorrespondenceDto
|
||||
): Promise<Correspondence> {
|
||||
async createCorrespondence(dto: CreateCorrespondenceDto): Promise<Correspondence> {
|
||||
// 1. Validate details against schema
|
||||
const validationResult = await this.jsonSchemaService.validateData(
|
||||
`CORRESPONDENCE_${dto.type}`,
|
||||
dto.details
|
||||
);
|
||||
const validationResult = await this.jsonSchemaService.validateData(`CORRESPONDENCE_${dto.type}`, dto.details);
|
||||
|
||||
if (!validationResult.isValid) {
|
||||
throw new ValidationError('INVALID_DETAILS', validationResult.errors);
|
||||
}
|
||||
|
||||
// 2. Apply security and sanitization
|
||||
const secureDetails = await this.detailsService.sanitizeDetails(
|
||||
validationResult.sanitizedData,
|
||||
dto.type
|
||||
);
|
||||
const secureDetails = await this.detailsService.sanitizeDetails(validationResult.sanitizedData, dto.type);
|
||||
|
||||
// 3. Create correspondence entity
|
||||
const correspondence = this.correspondenceRepository.create({
|
||||
...dto,
|
||||
details: secureDetails,
|
||||
schema_version: await this.getCurrentSchemaVersion(
|
||||
`CORRESPONDENCE_${dto.type}`
|
||||
),
|
||||
schema_version: await this.getCurrentSchemaVersion(`CORRESPONDENCE_${dto.type}`),
|
||||
});
|
||||
|
||||
// 4. Setup virtual columns for performance
|
||||
@@ -1220,9 +1129,7 @@ export class CorrespondenceService {
|
||||
return this.correspondenceRepository.save(correspondence);
|
||||
}
|
||||
|
||||
async searchCorrespondences(
|
||||
filters: SearchFilters
|
||||
): Promise<Correspondence[]> {
|
||||
async searchCorrespondences(filters: SearchFilters): Promise<Correspondence[]> {
|
||||
// Use virtual columns for efficient filtering
|
||||
const query = this.correspondenceRepository.createQueryBuilder('c');
|
||||
|
||||
@@ -1343,7 +1250,6 @@ describe('VirtualColumnService', () => {
|
||||
### **Phase 3: Tasks**
|
||||
|
||||
- **[ ] T3.1 WorkflowEngineModule (New)**
|
||||
|
||||
- [ ] ออกแบบ Generic Schema สำหรับ Workflow State Machine
|
||||
- [ ] Implement Service: `initializeWorkflow()`, `processAction()`, `getNextStep()`
|
||||
- [ ] รองรับ Logic การ "ข้ามขั้นตอน" และ "ส่งกลับ" ภายใน Engine เดียว
|
||||
@@ -1418,7 +1324,6 @@ states:
|
||||
```
|
||||
|
||||
- **[ ] T3.1.2 Workflow Core Entities & Database Schema**
|
||||
|
||||
- [ ] WorkflowDefinition Entity
|
||||
- [ ] WorkflowInstance Entity
|
||||
- [ ] WorkflowHistory Entity
|
||||
@@ -1485,7 +1390,6 @@ export class WorkflowInstance {
|
||||
```
|
||||
|
||||
- **[ ] T3.1.3 DSL Parser & Compiler Service**
|
||||
|
||||
- [ ] YAML Parser สำหรับอ่าน DSL definitions
|
||||
- [ ] Syntax Validator สำหรับ compile-time validation
|
||||
- [ ] Schema Compiler สำหรับแปลง DSL → Normalized JSON
|
||||
@@ -1517,9 +1421,7 @@ export class WorkflowDslService {
|
||||
// Terminal states ต้องไม่มี transitions
|
||||
() => !definition.states.filter((s) => s.terminal).some((s) => s.on),
|
||||
// State names must be unique
|
||||
() =>
|
||||
new Set(definition.states.map((s) => s.name)).size ===
|
||||
definition.states.length,
|
||||
() => new Set(definition.states.map((s) => s.name)).size === definition.states.length,
|
||||
// Transition targets must exist
|
||||
() => this.validateTransitionTargets(definition),
|
||||
];
|
||||
@@ -1663,11 +1565,7 @@ interface StateWithTimeout {
|
||||
```typescript
|
||||
@Injectable()
|
||||
export class WorkflowEventService {
|
||||
async executeEvents(
|
||||
events: WorkflowEvent[],
|
||||
instance: WorkflowInstance,
|
||||
context: WorkflowContext
|
||||
): Promise<void> {
|
||||
async executeEvents(events: WorkflowEvent[], instance: WorkflowInstance, context: WorkflowContext): Promise<void> {
|
||||
for (const event of events) {
|
||||
switch (event.type) {
|
||||
case 'notify':
|
||||
@@ -1691,16 +1589,8 @@ export class WorkflowEventService {
|
||||
instance: WorkflowInstance,
|
||||
context: WorkflowContext
|
||||
): Promise<void> {
|
||||
const recipients = await this.resolveRecipients(
|
||||
event.target,
|
||||
instance,
|
||||
context
|
||||
);
|
||||
const message = await this.renderTemplate(
|
||||
event.template,
|
||||
instance,
|
||||
context
|
||||
);
|
||||
const recipients = await this.resolveRecipients(event.target, instance, context);
|
||||
const message = await this.renderTemplate(event.template, instance, context);
|
||||
|
||||
await this.notificationService.send({
|
||||
type: 'workflow',
|
||||
@@ -1732,35 +1622,24 @@ export class WorkflowEngineController {
|
||||
@Param('id') instanceId: string,
|
||||
@Body() dto: WorkflowTransitionDto
|
||||
): Promise<TransitionResult> {
|
||||
return this.workflowEngine.processTransition(
|
||||
instanceId,
|
||||
dto.action,
|
||||
dto.context
|
||||
);
|
||||
return this.workflowEngine.processTransition(instanceId, dto.action, dto.context);
|
||||
}
|
||||
|
||||
@Get('instances/:id/actions')
|
||||
@RequirePermission('workflow.view')
|
||||
async getAvailableActions(
|
||||
@Param('id') instanceId: string,
|
||||
@Query() context: WorkflowContext
|
||||
): Promise<string[]> {
|
||||
async getAvailableActions(@Param('id') instanceId: string, @Query() context: WorkflowContext): Promise<string[]> {
|
||||
return this.workflowEngine.getAvailableActions(instanceId, context);
|
||||
}
|
||||
|
||||
@Post('definitions')
|
||||
@RequirePermission('workflow.manage')
|
||||
async createWorkflowDefinition(
|
||||
@Body() dto: CreateWorkflowDefinitionDto
|
||||
): Promise<WorkflowDefinition> {
|
||||
async createWorkflowDefinition(@Body() dto: CreateWorkflowDefinitionDto): Promise<WorkflowDefinition> {
|
||||
return this.workflowDslService.compileAndSave(dto.dslContent);
|
||||
}
|
||||
|
||||
@Get('instances/:id/history')
|
||||
@RequirePermission('workflow.view')
|
||||
async getWorkflowHistory(
|
||||
@Param('id') instanceId: string
|
||||
): Promise<WorkflowHistory[]> {
|
||||
async getWorkflowHistory(@Param('id') instanceId: string): Promise<WorkflowHistory[]> {
|
||||
return this.workflowHistoryService.getHistory(instanceId);
|
||||
}
|
||||
}
|
||||
@@ -1781,13 +1660,8 @@ export class CorrespondenceWorkflowService {
|
||||
private correspondenceService: CorrespondenceService
|
||||
) {}
|
||||
|
||||
async submitCorrespondence(
|
||||
correspondenceId: string,
|
||||
userId: string
|
||||
): Promise<void> {
|
||||
const correspondence = await this.correspondenceService.findById(
|
||||
correspondenceId
|
||||
);
|
||||
async submitCorrespondence(correspondenceId: string, userId: string): Promise<void> {
|
||||
const correspondence = await this.correspondenceService.findById(correspondenceId);
|
||||
|
||||
// Create workflow instance
|
||||
const instance = await this.workflowEngine.createInstance({
|
||||
@@ -1824,11 +1698,7 @@ describe('WorkflowEngineService', () => {
|
||||
const context = { userId: 'user1', roles: ['APPROVER'] };
|
||||
|
||||
// Act
|
||||
const result = await workflowEngine.processTransition(
|
||||
instance.id,
|
||||
'APPROVE',
|
||||
context
|
||||
);
|
||||
const result = await workflowEngine.processTransition(instance.id, 'APPROVE', context);
|
||||
|
||||
// Assert
|
||||
expect(result.success).toBe(true);
|
||||
@@ -1841,23 +1711,19 @@ describe('WorkflowEngineService', () => {
|
||||
const context = { userId: 'user2', roles: ['VIEWER'] };
|
||||
|
||||
// Act & Assert
|
||||
await expect(
|
||||
workflowEngine.processTransition(instance.id, 'APPROVE', context)
|
||||
).rejects.toThrow(WorkflowError);
|
||||
await expect(workflowEngine.processTransition(instance.id, 'APPROVE', context)).rejects.toThrow(WorkflowError);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
- **🔗 Critical Dependencies of T3.1.1-T3.1.8**
|
||||
|
||||
- T1.1 (Common Module) - สำหรับ base entities และ shared services
|
||||
- T1.4 (RBAC Guard) - สำหรับ permission checking
|
||||
- T2.5 (JSON Schema) - สำหรับ DSL validation
|
||||
- T6.2 (Notification) - สำหรับ event handling
|
||||
|
||||
- **🎯 Success Metrics**
|
||||
|
||||
- ✅ Support ทั้ง Correspondence Routing และ RFA Workflow
|
||||
- ✅ DSL ที่ human-readable และ editable โดยไม่ต้องแก้โค้ด
|
||||
- ✅ Performance: < 50ms ต่อ state transition
|
||||
@@ -1865,7 +1731,6 @@ describe('WorkflowEngineService', () => {
|
||||
- ✅ Complete audit trail สำหรับทุก workflow instance
|
||||
|
||||
- **[ ] T3.2 CorrespondenceModule - Basic CRUD**
|
||||
|
||||
- [ ] สร้าง Entities (Correspondence, Revision, Recipient, Tag, Reference, Attachment)
|
||||
- [ ] สร้าง CorrespondenceService (Create with Document Numbering, Update with new Revision, Soft Delete)
|
||||
- [ ] สร้าง Controllers (POST/GET/PUT/DELETE /correspondences)
|
||||
@@ -1875,7 +1740,6 @@ describe('WorkflowEngineService', () => {
|
||||
- [ ] **Dependencies:** T1.1, T1.2, T1.3, T1.4, T1.5, T2.3, T2.2, T2.5
|
||||
|
||||
- **[ ] T3.3 CorrespondenceModule - Advanced Features**
|
||||
|
||||
- [ ] Implement Status Transitions (DRAFT → SUBMITTED)
|
||||
- [ ] Implement References (Link Documents)
|
||||
- [ ] Implement Search (Basic)
|
||||
@@ -1884,7 +1748,6 @@ describe('WorkflowEngineService', () => {
|
||||
- [ ] **Dependencies:** T3.2
|
||||
|
||||
- **[ ] T3.4 Correspondence Integration with Workflow**
|
||||
|
||||
- [ ] เชื่อมต่อ `CorrespondenceService` เข้ากับ `WorkflowEngineModule`
|
||||
- [ ] ย้าย Logic การ Routing เดิมมาใช้ Engine ใหม่
|
||||
- [ ] สร้าง API endpoints สำหรับ Frontend (Templates, Pending Tasks, Bulk Action)
|
||||
@@ -1901,7 +1764,6 @@ describe('WorkflowEngineService', () => {
|
||||
### **Phase 4: Tasks**
|
||||
|
||||
- **[ ] T4.1 DrawingModule - Contract Drawings**
|
||||
|
||||
- [ ] สร้าง Entities (ContractDrawing, Volume, Category, SubCategory, Attachment)
|
||||
- [ ] สร้าง ContractDrawingService CRUD
|
||||
- [ ] สร้าง Controllers (GET/POST /drawings/contract)
|
||||
@@ -1910,7 +1772,6 @@ describe('WorkflowEngineService', () => {
|
||||
- [ ] **Dependencies:** T1.1, T1.2, T1.4, T1.5, T2.2
|
||||
|
||||
- **[ ] T4.2 DrawingModule - Shop Drawings**
|
||||
|
||||
- [ ] สร้าง Entities (ShopDrawing, Revision, Main/SubCategory, ContractRef, RevisionAttachment)
|
||||
- [ ] สร้าง ShopDrawingService CRUD (รวมการสร้าง Revision)
|
||||
- [ ] สร้าง Controllers (GET/POST /drawings/shop, /drawings/shop/:id/revisions)
|
||||
@@ -1920,7 +1781,6 @@ describe('WorkflowEngineService', () => {
|
||||
- [ ] **Dependencies:** T4.1
|
||||
|
||||
- **[ ] T5.1 RfaModule with Unified Workflow**
|
||||
|
||||
- [ ] สร้าง Entities (Rfa, RfaRevision, RfaItem, RfaWorkflowTemplate/Step)
|
||||
- [ ] สร้าง RfaService (Create RFA, Link Shop Drawings)
|
||||
- [ ] Implement RFA Workflow โดยใช้ Configuration ของ `WorkflowEngineModule`
|
||||
@@ -1938,7 +1798,6 @@ describe('WorkflowEngineService', () => {
|
||||
### **Phase 5: Tasks**
|
||||
|
||||
- **[ ] T5.2 CirculationModule - Internal Routing**
|
||||
|
||||
- [ ] สร้าง Entities (Circulation, Template, Routing, Attachment)
|
||||
- [ ] สร้าง CirculationService (Create 1:1 with Correspondence, Assign User, Complete/Close Step)
|
||||
- [ ] สร้าง Controllers (POST/GET /circulations, POST /circulations/:id/steps/...)
|
||||
@@ -1947,7 +1806,6 @@ describe('WorkflowEngineService', () => {
|
||||
- [ ] **Dependencies:** T3.2, T2.5, T6.2
|
||||
|
||||
- **[ ] T5.3 TransmittalModule - Document Forwarding**
|
||||
|
||||
- [ ] สร้าง Entities (Transmittal, TransmittalItem)
|
||||
- [ ] สร้าง TransmittalService (Create Correspondence + Transmittal, Link Multiple Correspondences)
|
||||
- [ ] สร้าง Controllers (POST/GET /transmittals)
|
||||
@@ -1964,7 +1822,6 @@ describe('WorkflowEngineService', () => {
|
||||
### **Phase 6: Tasks**
|
||||
|
||||
- **[ ] T6.1 SearchModule - Elasticsearch Integration**
|
||||
|
||||
- [ ] Setup Elasticsearch Container
|
||||
- [ ] สร้าง SearchService (index/update/delete documents, search)
|
||||
- [ ] Index ทุก Document Type
|
||||
@@ -1974,7 +1831,6 @@ describe('WorkflowEngineService', () => {
|
||||
- [ ] **Dependencies:** T3.2, T5.1, T4.2, T5.2, T5.3
|
||||
|
||||
- **[ ] T6.2 Notification Queue & Digest**
|
||||
|
||||
- [ ] สร้าง NotificationService (sendEmail/Line/System)
|
||||
- [ ] **Producer:** Push Event ลง BullMQ Queue
|
||||
- [ ] **Consumer:** จัดกลุ่ม Notification (Digest Message) และส่งผ่าน Email/Line
|
||||
@@ -1985,7 +1841,6 @@ describe('WorkflowEngineService', () => {
|
||||
- [ ] **Dependencies:** T1.1, T6.4
|
||||
|
||||
- **[ ] T6.3 MonitoringModule - Observability**
|
||||
|
||||
- [ ] สร้าง Health Check Controller (GET /health)
|
||||
- [ ] สร้าง Metrics Service (API response times, Error rates)
|
||||
- [ ] สร้าง Performance Interceptor (Track request duration)
|
||||
@@ -1994,7 +1849,6 @@ describe('WorkflowEngineService', () => {
|
||||
- [ ] **Dependencies:** T1.1
|
||||
|
||||
- **[ ] T6.4 ResilienceModule - Circuit Breaker & Retry**
|
||||
|
||||
- [ ] สร้าง Circuit Breaker Service (@CircuitBreaker() decorator)
|
||||
- [ ] สร้าง Retry Service (@Retry() decorator)
|
||||
- [ ] สร้าง Fallback Strategies
|
||||
@@ -2003,7 +1857,6 @@ describe('WorkflowEngineService', () => {
|
||||
- [ ] **Dependencies:** T1.1
|
||||
|
||||
- **[ ] T6.5 Data Partitioning Strategy**
|
||||
|
||||
- [ ] ออกแบบ Table Partitioning สำหรับ `audit_logs` และ `notifications` (แบ่งตาม Range: Year)
|
||||
- [ ] เขียน Raw SQL Migration สำหรับสร้าง Partition Table
|
||||
- [ ] **Deliverable:** Database Performance และ Scalability ดีขึ้น
|
||||
@@ -2018,21 +1871,18 @@ describe('WorkflowEngineService', () => {
|
||||
### **Phase 7: Tasks**
|
||||
|
||||
- **[ ] T7.1 Concurrency Testing**
|
||||
|
||||
- [ ] เขียน Test Scenarios ยิง Request ขอเลขที่เอกสารพร้อมกัน 100 Request (ต้องไม่ซ้ำและไม่ข้าม)
|
||||
- [ ] ทดสอบ Optimistic Lock ทำงานถูกต้องเมื่อ Redis ถูกปิด
|
||||
- [ ] ทดสอบ File Upload พร้อมกันหลายไฟล์
|
||||
- [ ] **Deliverable:** ระบบทนทานต่อ Concurrency Issues
|
||||
|
||||
- **[ ] T7.2 Transaction Integrity Testing**
|
||||
|
||||
- [ ] ทดสอบ Upload ไฟล์แล้ว Kill Process ก่อน Commit
|
||||
- [ ] ทดสอบ Two-Phase File Storage ทำงานถูกต้อง
|
||||
- [ ] ทดสอบ Database Transaction Rollback Scenarios
|
||||
- [ ] **Deliverable:** Data Integrity รับประกันได้
|
||||
|
||||
- **[ ] T7.3 Security & Idempotency Test**
|
||||
|
||||
- [ ] ทดสอบ Replay Attack โดยใช้ `Idempotency-Key` ซ้ำ
|
||||
- [ ] ทดสอบ Maintenance Mode Block API ได้จริง
|
||||
- [ ] ทดสอบ RBAC 4-Level ทำงานถูกต้อง 100%
|
||||
@@ -2045,7 +1895,6 @@ describe('WorkflowEngineService', () => {
|
||||
- **[ ] T7.6 E2E Testing**
|
||||
|
||||
- **[ ] T7.7 Performance Testing**
|
||||
|
||||
- [ ] Load Testing: 100 concurrent users
|
||||
- [ ] **(สำคัญ)** การจูนและทดสอบ Load Test จะต้องทำในสภาพแวดล้อมที่จำลอง Spec ของ QNAP Server (TS-473A, AMD Ryzen V1500B) เพื่อให้ได้ค่า Response Time และ Connection Pool ที่เที่ยงตรง
|
||||
- [ ] Stress Testing
|
||||
@@ -2053,14 +1902,12 @@ describe('WorkflowEngineService', () => {
|
||||
- [ ] **Deliverable:** Performance targets บรรลุ
|
||||
|
||||
- **[ ] T7.8 Security Testing**
|
||||
|
||||
- [ ] Penetration Testing (OWASP Top 10)
|
||||
- [ ] Security Audit (Code review, Dependency scanning)
|
||||
- [ ] File Upload Security Testing
|
||||
- [ ] **Deliverable:** Security tests ผ่าน
|
||||
|
||||
- **[ ] T7.9 Performance Optimization**
|
||||
|
||||
- [ ] Implement Caching (Master Data, User Permissions, Search Results)
|
||||
- [ ] Database Optimization (Review Indexes, Query Optimization, Pagination)
|
||||
- [ ] **Deliverable:** Response Time < 200ms (90th percentile)
|
||||
|
||||
@@ -925,8 +925,8 @@ F10_3 --> F10_4
|
||||
|
||||
## 📊 **สรุป Timeline**
|
||||
|
||||
| Phase | ระยะเวลา | จำนวนงาน | Output หลัก |
|
||||
| -------- | ------------ | ------------ | ------------------------------------ |
|
||||
| Phase | ระยะเวลา | จำนวนงาน | Output หลัก |
|
||||
| -------- | -------------- | ------------ | ------------------------------------ |
|
||||
| Phase 0 | 1 สัปดาห์ | 4 | Foundation & Tooling Ready |
|
||||
| Phase 1 | 1 สัปดาห์ | 4 | Core Application Structure |
|
||||
| Phase 2 | 1 สัปดาห์ | 4 | User Management & Security |
|
||||
|
||||
@@ -206,7 +206,6 @@
|
||||
### **Phase 0: Tasks**
|
||||
|
||||
- **[ ] F0.1 Project Setup & Tooling**
|
||||
|
||||
- [ ] Initialize Next.js 14+ project with TypeScript
|
||||
- [ ] Configure pnpm workspace
|
||||
- [ ] Setup ESLint, Prettier, and pre-commit hooks
|
||||
@@ -217,7 +216,6 @@
|
||||
- [ ] **Dependencies:** None
|
||||
|
||||
- **[ ] F0.2 Design System & UI Components**
|
||||
|
||||
- [ ] Setup color palette and design tokens
|
||||
- [ ] Create responsive design breakpoints
|
||||
- [ ] Implement core shadcn/ui components:
|
||||
@@ -233,7 +231,6 @@
|
||||
- [ ] **Dependencies:** F0.1
|
||||
|
||||
- **[ ] F0.3 API Client & Authentication**
|
||||
|
||||
- [ ] Setup Axios client with interceptors:
|
||||
- [ ] Idempotency-Key header injection
|
||||
- [ ] Authentication token management
|
||||
@@ -282,7 +279,6 @@
|
||||
### **Phase 1: Tasks**
|
||||
|
||||
- **[ ] F1.1 Main Layout & Navigation**
|
||||
|
||||
- [ ] Create App Shell layout:
|
||||
- [ ] Navbar with user menu and notifications
|
||||
- [ ] Collapsible sidebar with navigation
|
||||
@@ -299,7 +295,6 @@
|
||||
- [ ] **Dependencies:** F0.2, F0.3
|
||||
|
||||
- **[ ] F1.2 Authentication Pages**
|
||||
|
||||
- [ ] Create login page with form validation
|
||||
- [ ] Implement forgot password flow
|
||||
- [ ] Create registration page (admin-only)
|
||||
@@ -310,7 +305,6 @@
|
||||
- [ ] **Dependencies:** F0.3, F1.1
|
||||
|
||||
- **[ ] F1.3 Dashboard & Landing**
|
||||
|
||||
- [ ] Create public landing page for non-authenticated users
|
||||
- [ ] Implement main dashboard with:
|
||||
- [ ] KPI cards (document counts, pending tasks)
|
||||
@@ -356,7 +350,6 @@
|
||||
### **Phase 2: Tasks**
|
||||
|
||||
- **[ ] F2.1 User Profile & Settings**
|
||||
|
||||
- [ ] Create user profile page:
|
||||
- [ ] Personal information display/edit
|
||||
- [ ] Password change functionality
|
||||
@@ -368,7 +361,6 @@
|
||||
- [ ] **Dependencies:** F1.1, F0.4
|
||||
|
||||
- **[ ] F2.2 Admin Panel - User Management**
|
||||
|
||||
- [ ] Create user list with search and filters
|
||||
- [ ] Implement user creation form
|
||||
- [ ] Create user edit interface
|
||||
@@ -379,7 +371,6 @@
|
||||
- [ ] **Dependencies:** F1.1, F2.1
|
||||
|
||||
- **[ ] F2.3 Admin Panel - Role Management**
|
||||
|
||||
- [ ] Create role list and management interface
|
||||
- [ ] Implement role creation and editing
|
||||
- [ ] Create permission assignment interface
|
||||
@@ -432,7 +423,6 @@
|
||||
### **Phase 3: Tasks**
|
||||
|
||||
- **[ ] F3.1 Project Management UI**
|
||||
|
||||
- [ ] Create project list with search and filters
|
||||
- [ ] Implement project creation and editing
|
||||
- [ ] Create project detail view
|
||||
@@ -443,7 +433,6 @@
|
||||
- [ ] **Dependencies:** F1.1, F2.4
|
||||
|
||||
- **[ ] F3.2 Organization Management**
|
||||
|
||||
- [ ] Create organization list and management
|
||||
- [ ] Implement organization creation and editing
|
||||
- [ ] Create organization detail view
|
||||
@@ -479,7 +468,6 @@
|
||||
### **Phase 4: Tasks**
|
||||
|
||||
- **[ ] F4.1 Correspondence List & Search**
|
||||
|
||||
- [ ] Create correspondence list with advanced filtering:
|
||||
- [ ] Filter by type, status, project, organization
|
||||
- [ ] Search by title, document number, content
|
||||
@@ -494,7 +482,6 @@
|
||||
- [ ] **Dependencies:** F1.1, F3.1
|
||||
|
||||
- **[ ] F4.2 Correspondence Creation Form**
|
||||
|
||||
- [ ] Create dynamic form generator based on JSON schema
|
||||
- [ ] Implement form with multiple sections:
|
||||
- [ ] Basic information (type, title, recipients)
|
||||
@@ -512,7 +499,6 @@
|
||||
- [ ] **Dependencies:** F0.4, F4.1
|
||||
|
||||
- **[ ] F4.3 Correspondence Detail View**
|
||||
|
||||
- [ ] Create comprehensive detail page:
|
||||
- [ ] Document header with metadata
|
||||
- [ ] Content display based on type
|
||||
@@ -544,7 +530,6 @@
|
||||
### **Phase 4: Testing - Correspondence System**
|
||||
|
||||
- **[ ] F4.T1 Correspondence Test Suite**
|
||||
|
||||
- [ ] **Unit Tests:** Form validation, file upload components
|
||||
- [ ] **Integration Tests:** Complete document lifecycle, file attachment flow
|
||||
- [ ] **E2E Tests:** End-to-end correspondence creation and management
|
||||
@@ -563,7 +548,6 @@
|
||||
### **Phase 5: Tasks**
|
||||
|
||||
- **[ ] F5.1 Workflow Visualization Component**
|
||||
|
||||
- [ ] Create horizontal workflow progress visualization
|
||||
- [ ] Implement step status indicators (pending, active, completed, skipped)
|
||||
- [ ] Add due date and assignee information
|
||||
@@ -574,7 +558,6 @@
|
||||
- [ ] **Dependencies:** F4.3
|
||||
|
||||
- **[ ] F5.2 Routing Template Management**
|
||||
|
||||
- [ ] Create routing template list and editor
|
||||
- [ ] Implement drag-and-drop step configuration
|
||||
- [ ] Add step configuration (purpose, duration, assignee rules)
|
||||
@@ -585,7 +568,6 @@
|
||||
- [ ] **Dependencies:** F3.1, F4.2
|
||||
|
||||
- **[ ] F5.3 Workflow Step Actions**
|
||||
|
||||
- [ ] Create step action interface:
|
||||
- [ ] Approve, reject, request changes
|
||||
- [ ] Add comments and attachments
|
||||
@@ -623,7 +605,6 @@
|
||||
### **Phase 6: Tasks**
|
||||
|
||||
- **[ ] F6.1 Contract Drawings Management**
|
||||
|
||||
- [ ] Create contract drawing list with categorization
|
||||
- [ ] Implement drawing upload and metadata management
|
||||
- [ ] Create drawing preview and viewer
|
||||
@@ -634,7 +615,6 @@
|
||||
- [ ] **Dependencies:** F3.1, F4.4
|
||||
|
||||
- **[ ] F6.2 Shop Drawings Management**
|
||||
|
||||
- [ ] Create shop drawing list with revision tracking
|
||||
- [ ] Implement shop drawing creation and revision system
|
||||
- [ ] Create drawing comparison interface
|
||||
@@ -645,7 +625,6 @@
|
||||
- [ ] **Dependencies:** F6.1
|
||||
|
||||
- **[ ] F6.3 Drawing Revision System**
|
||||
|
||||
- [ ] Create revision history interface
|
||||
- [ ] Implement revision comparison functionality
|
||||
- [ ] Add revision notes and change tracking
|
||||
@@ -681,7 +660,6 @@
|
||||
### **Phase 7: Tasks**
|
||||
|
||||
- **[ ] F7.1 RFA List & Dashboard**
|
||||
|
||||
- [ ] Create RFA dashboard with status overview
|
||||
- [ ] Implement advanced RFA filtering and search
|
||||
- [ ] Create RFA calendar view for deadlines
|
||||
@@ -692,7 +670,6 @@
|
||||
- [ ] **Dependencies:** F4.1, F5.1
|
||||
|
||||
- **[ ] F7.2 RFA Creation with Dynamic Forms**
|
||||
|
||||
- [ ] Create RFA type-specific form generator
|
||||
- [ ] Implement dynamic form fields based on RFA type:
|
||||
- [ ] RFA_DWG: Shop drawing selection
|
||||
@@ -712,7 +689,6 @@
|
||||
- [ ] **Dependencies:** F4.2, F6.2
|
||||
|
||||
- **[ ] F7.3 RFA Workflow Integration**
|
||||
|
||||
- [ ] Integrate RFA with unified workflow engine
|
||||
- [ ] Create RFA-specific workflow steps and actions
|
||||
- [ ] Implement RFA approval interface
|
||||
@@ -748,7 +724,6 @@
|
||||
### **Phase 8: Tasks**
|
||||
|
||||
- **[ ] F8.1 Circulation Management**
|
||||
|
||||
- [ ] Create circulation list and management interface
|
||||
- [ ] Implement circulation creation from correspondence
|
||||
- [ ] Create circulation template management
|
||||
@@ -759,7 +734,6 @@
|
||||
- [ ] **Dependencies:** F4.1, F5.2
|
||||
|
||||
- **[ ] F8.2 Task Assignment Interface**
|
||||
|
||||
- [ ] Create task assignment interface with user selection
|
||||
- [ ] Implement task priority and deadline setting
|
||||
- [ ] Add task dependency management
|
||||
@@ -795,7 +769,6 @@
|
||||
### **Phase 9: Tasks**
|
||||
|
||||
- **[ ] F9.1 Advanced Search Interface**
|
||||
|
||||
- [ ] Create unified search interface across all document types
|
||||
- [ ] Implement faceted search with multiple filters
|
||||
- [ ] Add search result highlighting and relevance scoring
|
||||
@@ -806,7 +779,6 @@
|
||||
- [ ] **Dependencies:** F4.1, F7.1
|
||||
|
||||
- **[ ] F9.2 Notification System**
|
||||
|
||||
- [ ] Create notification center with real-time updates
|
||||
- [ ] Implement notification preferences management
|
||||
- [ ] Add notification grouping and digest views
|
||||
@@ -817,7 +789,6 @@
|
||||
- [ ] **Dependencies:** F1.3, F5.4
|
||||
|
||||
- **[ ] F9.3 Reporting & Analytics**
|
||||
|
||||
- [ ] Create reporting dashboard with customizable widgets
|
||||
- [ ] Implement data visualization components (charts, graphs)
|
||||
- [ ] Add report scheduling and export
|
||||
@@ -853,7 +824,6 @@
|
||||
### **Phase 10: Tasks**
|
||||
|
||||
- **[ ] F10.1 Comprehensive Testing**
|
||||
|
||||
- [ ] Idempotency Testing: เพิ่มการทดสอบเฉพาะสำหรับ Axios Interceptor เพื่อจำลองการส่ง Request POST/PUT/DELETE ที่มี Idempotency-Key ซ้ำไปยัง Mock API (MSW) เพื่อยืนยันว่า Client-side ไม่ส่ง Key ซ้ำในการทำงานปกติ และไม่เกิด Side Effect จากการ Replay Attack.
|
||||
- [ ] Write unit tests for all components and utilities
|
||||
- [ ] Create integration tests for critical user flows
|
||||
@@ -865,7 +835,6 @@
|
||||
- [ ] **Dependencies:** All previous phases
|
||||
|
||||
- **[ ] F10.2 Performance Optimization**
|
||||
|
||||
- [ ] Implement code splitting and lazy loading
|
||||
- [ ] Optimize bundle size and asset delivery
|
||||
- [ ] Add performance monitoring and metrics
|
||||
@@ -876,7 +845,6 @@
|
||||
- [ ] **Dependencies:** F10.1
|
||||
|
||||
- **[ ] F10.3 Security Hardening**
|
||||
|
||||
- [ ] Conduct security audit and penetration testing
|
||||
- [ ] Implement Content Security Policy (CSP)
|
||||
- [ ] Add security headers and protections
|
||||
|
||||
@@ -474,26 +474,26 @@
|
||||
|
||||
**Purpose**: Child table storing revision history of correspondences (1:N)
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------------------ | ------------ | --------------------------------- | -------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
|
||||
| correspondence_id | INT | NOT NULL, FK | Master correspondence ID |
|
||||
| revision_number | INT | NOT NULL | Revision sequence (0, 1, 2...) |
|
||||
| revision_label | VARCHAR(10) | NULL | Display revision (A, B, 1.1...) |
|
||||
| is_current | BOOLEAN | DEFAULT FALSE | Current revision flag |
|
||||
| correspondence_status_id | INT | NOT NULL, FK | Current status of this revision |
|
||||
| title | VARCHAR(255) | NOT NULL | Document title |
|
||||
| document_date | DATE | NULL | Document date |
|
||||
| issued_date | DATETIME | NULL | Issue date |
|
||||
| received_date | DATETIME | NULL | Received date |
|
||||
| due_date | DATETIME | NULL | Due date for response |
|
||||
| description | TEXT | NULL | Revision description |
|
||||
| details | JSON | NULL | Type-specific details (e.g., RFI questions) |
|
||||
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Revision creation timestamp |
|
||||
| created_by | INT | NULL, FK | User who created revision |
|
||||
| updated_by | INT | NULL, FK | User who last updated |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------------------ | ------------ | --------------------------------- | ------------------------------------------------------------ |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique revision ID |
|
||||
| correspondence_id | INT | NOT NULL, FK | Master correspondence ID |
|
||||
| revision_number | INT | NOT NULL | Revision sequence (0, 1, 2...) |
|
||||
| revision_label | VARCHAR(10) | NULL | Display revision (A, B, 1.1...) |
|
||||
| is_current | BOOLEAN | DEFAULT FALSE | Current revision flag |
|
||||
| correspondence_status_id | INT | NOT NULL, FK | Current status of this revision |
|
||||
| title | VARCHAR(255) | NOT NULL | Document title |
|
||||
| document_date | DATE | NULL | Document date |
|
||||
| issued_date | DATETIME | NULL | Issue date |
|
||||
| received_date | DATETIME | NULL | Received date |
|
||||
| due_date | DATETIME | NULL | Due date for response |
|
||||
| description | TEXT | NULL | Revision description |
|
||||
| details | JSON | NULL | Type-specific details (e.g., RFI questions) |
|
||||
| created_at | DATETIME | DEFAULT CURRENT_TIMESTAMP | Revision creation timestamp |
|
||||
| created_by | INT | NULL, FK | User who created revision |
|
||||
| updated_by | INT | NULL, FK | User who last updated |
|
||||
| v_ref_project_id | INT | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column ดึง Project ID จาก JSON details เพื่อทำ Index |
|
||||
| v_ref_type | VARCHAR(50) | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column ดึง Type จาก JSON details |
|
||||
| v_ref_type | VARCHAR(50) | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column ดึง Type จาก JSON details |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -627,16 +627,16 @@
|
||||
|
||||
**Purpose**: เก็บข้อมูลแม่แบบ (Template) ของสายงานการส่งต่อเอกสารเพื่อขออนุมัติ ทำให้ไม่ต้องกำหนดขั้นตอนซ้ำทุกครั้ง สามารถสร้างเป็นแม่แบบทั่วไป หรือเฉพาะสำหรับโครงการใดโครงการหนึ่งได้
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| --------------- | ------------ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลัก (Primary Key) ของแม่แบบ รันค่าอัตโนมัติ |
|
||||
| template_name | VARCHAR(255) | NOT NULL | ชื่อของแม่แบบ เช่น "เสนอโครงการ", "ขออนุมัติจัดซื้อ" |
|
||||
| description | TEXT | NULL | คำอธิบายรายละเอียดเกี่ยวกับแม่แบบนี้ |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| --------------- | ------------ | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลัก (Primary Key) ของแม่แบบ รันค่าอัตโนมัติ |
|
||||
| template_name | VARCHAR(255) | NOT NULL | ชื่อของแม่แบบ เช่น "เสนอโครงการ", "ขออนุมัติจัดซื้อ" |
|
||||
| description | TEXT | NULL | คำอธิบายรายละเอียดเกี่ยวกับแม่แบบนี้ |
|
||||
| project_id | INT | NULL | ID ของโครงการที่แม่แบบนี้สังกัดอยู่ (ถ้ามี) **ค่า NULL หมายถึง** เป็น "แม่แบบทั่วไป" ที่สามารถใช้กับทุกโครงการได้ |
|
||||
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | วันที่และเวลาที่สร้างแม่แบบนี้ |
|
||||
| updated_at | TIMESTAMP | NOT NULL,`DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | วันที่และเวลาที่แก้ไขข้อมูลในแม่แบบนี้ล่าสุด |
|
||||
| is_active | BOOLEAN | DEFAULT TRUE | สถานะใช้งาน |
|
||||
| workflow_config | JSON | NULL | เก็บ State Machine Configuration หรือ Rules เพิ่มเติมที่ซับซ้อนกว่า Column ปกติ |
|
||||
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | วันที่และเวลาที่สร้างแม่แบบนี้ |
|
||||
| updated_at | TIMESTAMP | NOT NULL,`DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | วันที่และเวลาที่แก้ไขข้อมูลในแม่แบบนี้ล่าสุด |
|
||||
| is_active | BOOLEAN | DEFAULT TRUE | สถานะใช้งาน |
|
||||
| workflow_config | JSON | NULL | เก็บ State Machine Configuration หรือ Rules เพิ่มเติมที่ซับซ้อนกว่า Column ปกติ |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -653,14 +653,14 @@
|
||||
|
||||
**Purpose**: เก็บรายละเอียดของแต่ละขั้นตอน (Steps) ภายในแม่แบบสายงาน (correspondence_routing_templates) กำหนดว่าจะส่งไปที่องค์กรไหน ลำดับเป็นเท่าไร และเพื่อวัตถุประสงค์อะไร
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :----------------- | --------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของขั้นตอน |
|
||||
| template_id | INT | NOT NULL | ID ของแม่แบบที่ขั้นตอนนี้สังกัดอยู่ |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอน (1, 2, 3, ...) |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรที่เป็นผู้รับในขั้นตอนนี้ |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :----------------- | --------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของขั้นตอน |
|
||||
| template_id | INT | NOT NULL | ID ของแม่แบบที่ขั้นตอนนี้สังกัดอยู่ |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอน (1, 2, 3, ...) |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรที่เป็นผู้รับในขั้นตอนนี้ |
|
||||
| step_purpose | ENUM | NOT NULL,DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้ **ค่าที่เป็นไปได้:** [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ] |
|
||||
| expected_days | INT | NULL | วันที่คาดหวัง |
|
||||
| expected_days | INT | NULL | วันที่คาดหวัง |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -679,22 +679,22 @@
|
||||
|
||||
**Purpose**: เป็นตารางที่เก็บข้อมูลการส่งต่อเอกสารจริง (Instance/Run-time) ติดตามประวัติการเคลื่อนย้ายของแต่ละเอกสาร ว่าผ่านใครมาบ้าง อยู่ที่ใคร และสถานะปัจจุบันคืออะไร
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------- | --------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของรายการส่งต่อ |
|
||||
| correspondence_id | INT | NOT NUL | ID ของเอกสาร (FK ไปยัง correspondence_revisions) |
|
||||
| template_id | INT | NULL | ID ของแม่แบบที่ใช้สร้างสายงานนี้ (เก็บไว้เป็นข้อมูลอ้างอิง) |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอนการส่งต่อจริง |
|
||||
| from_organization_id | INT | NOT NULL | ID ขององค์กรผู้ส่ง |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรผู้รับ |
|
||||
| step_purpose | ENUM | NOT NULL, DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้จริง **ค่าที่เป็นไปได้:** [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ, FOR_ACTION: เพื่อดำเนินการ] |
|
||||
| status | ENUM | NOT NULL, DEFAULT SENT | [ACTIONED: ดำเนินการแล้ว, FORWARDED: ส่งต่อแล้ว, REPLIE: ตอบกลับแล้ว] |
|
||||
| comments | TEXT | NULL | หมายเหตุหรือความคิดเห็นในการส่งต่อ |
|
||||
| due_date | DATETIME | NULL | วันที่ครบกำหนดที่ต้องดำเนินการในขั้นตอนนี้ |
|
||||
| processed_by_user_id | INT | NULL | ID ของผู้ใช้ที่ดำเนินการในขั้นตอนนี้จริงๆ |
|
||||
| processed_at | TIMESTAMP | NULL | เวลาที่ผู้ใช้ดำเนินการเสร็จสิ้น |
|
||||
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | เวลาที่สร้างรายการส่งต่อนี้ |
|
||||
| state_context | JSON | NULL | เก็บข้อมูล Context ของ Workflow ณ ขณะนั้น (Snapshot) |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------- | --------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของรายการส่งต่อ |
|
||||
| correspondence_id | INT | NOT NUL | ID ของเอกสาร (FK ไปยัง correspondence_revisions) |
|
||||
| template_id | INT | NULL | ID ของแม่แบบที่ใช้สร้างสายงานนี้ (เก็บไว้เป็นข้อมูลอ้างอิง) |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอนการส่งต่อจริง |
|
||||
| from_organization_id | INT | NOT NULL | ID ขององค์กรผู้ส่ง |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรผู้รับ |
|
||||
| step_purpose | ENUM | NOT NULL, DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้จริง **ค่าที่เป็นไปได้:** [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ, FOR_ACTION: เพื่อดำเนินการ] |
|
||||
| status | ENUM | NOT NULL, DEFAULT SENT | [ACTIONED: ดำเนินการแล้ว, FORWARDED: ส่งต่อแล้ว, REPLIE: ตอบกลับแล้ว] |
|
||||
| comments | TEXT | NULL | หมายเหตุหรือความคิดเห็นในการส่งต่อ |
|
||||
| due_date | DATETIME | NULL | วันที่ครบกำหนดที่ต้องดำเนินการในขั้นตอนนี้ |
|
||||
| processed_by_user_id | INT | NULL | ID ของผู้ใช้ที่ดำเนินการในขั้นตอนนี้จริงๆ |
|
||||
| processed_at | TIMESTAMP | NULL | เวลาที่ผู้ใช้ดำเนินการเสร็จสิ้น |
|
||||
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | เวลาที่สร้างรายการส่งต่อนี้ |
|
||||
| state_context | JSON | NULL | เก็บข้อมูล Context ของ Workflow ณ ขณะนั้น (Snapshot) |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -719,11 +719,11 @@
|
||||
|
||||
**Purpose**: ตารางนี้ใช้กำหนดกฎ (State Machine) ว่าสถานะใดสามารถเปลี่ยนไปเป็นสถานะใดได้บ้าง โดยขึ้นอยู่กับประเภทของหนังสือ เพื่อควบคุมการไหลของสถานะให้ถูกต้องตามข้อบังคับ
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------- | --------- | ----------- | ----------------------------------------------- |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------- | --------- | ----------- | ------------------------------------------------------ |
|
||||
| type_id | INT | PRIMARY KEY | ID ของประเภทหนังสือ (เช่น หนังสือภายใน, หนังสือภายนอก) |
|
||||
| from_status_id | INT | PRIMARY KEY | ID ของสถานะต้นทาง (เช่น ร่าง) |
|
||||
| to_status_id | INT | PRIMARY KEY | ID ของสถานะปลายทาง (เช่น รออนุมัติ) |
|
||||
| from_status_id | INT | PRIMARY KEY | ID ของสถานะต้นทาง (เช่น ร่าง) |
|
||||
| to_status_id | INT | PRIMARY KEY | ID ของสถานะปลายทาง (เช่น รออนุมัติ) |
|
||||
|
||||
**คีย์หลัก (Primary Key):**
|
||||
|
||||
@@ -957,14 +957,14 @@
|
||||
|
||||
**Purpose**: Master table for RFA approval workflow templates
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| --------------- | ------------ | ----------------------------------- | -------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique template ID |
|
||||
| template_name | VARCHAR(100) | NOT NULL | Template name |
|
||||
| description | TEXT | NULL | Template description |
|
||||
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
|
||||
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| --------------- | ------------ | ----------------------------------- | ------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique template ID |
|
||||
| template_name | VARCHAR(100) | NOT NULL | Template name |
|
||||
| description | TEXT | NULL | Template description |
|
||||
| is_active | TINYINT(1) | DEFAULT 1 | Active status |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
|
||||
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
|
||||
| workflow_config | JSON | NULL | เก็บ State Machine Configuration หรือ Rules เพิ่มเติมที่ซับซ้อนกว่า Column ปกติ |
|
||||
|
||||
**Indexes**:
|
||||
@@ -1024,20 +1024,20 @@
|
||||
|
||||
**Purpose**: Transaction log table tracking actual RFA approval workflow execution
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| --------------- | --------- | ----------------------------------- | ------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique workflow log ID |
|
||||
| rfa_revision_id | INT | NOT NULL, FK | Reference to RFA revision |
|
||||
| step_number | INT | NOT NULL | Current step number |
|
||||
| organization_id | INT | NOT NULL, FK | Organization responsible |
|
||||
| assigned_to | INT | NULL, FK | Assigned user ID |
|
||||
| action_type | ENUM | NULL | Action type: REVIEW, APPROVE, ACKNOWLEDGE |
|
||||
| status | ENUM | NULL | Status: PENDING, IN_PROGRESS, COMPLETED, REJECTED |
|
||||
| comments | TEXT | NULL | Comments/remarks |
|
||||
| completed_at | DATETIME | NULL | Completion timestamp |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
|
||||
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
|
||||
| state_context | JSON* | NULL | เก็บข้อมูล Context ของ Workflow ณ ขณะนั้น (Snapshot) |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| --------------- | --------- | ----------------------------------- | ---------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique workflow log ID |
|
||||
| rfa_revision_id | INT | NOT NULL, FK | Reference to RFA revision |
|
||||
| step_number | INT | NOT NULL | Current step number |
|
||||
| organization_id | INT | NOT NULL, FK | Organization responsible |
|
||||
| assigned_to | INT | NULL, FK | Assigned user ID |
|
||||
| action_type | ENUM | NULL | Action type: REVIEW, APPROVE, ACKNOWLEDGE |
|
||||
| status | ENUM | NULL | Status: PENDING, IN_PROGRESS, COMPLETED, REJECTED |
|
||||
| comments | TEXT | NULL | Comments/remarks |
|
||||
| completed_at | DATETIME | NULL | Completion timestamp |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Record creation timestamp |
|
||||
| updated_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP ON UPDATE | Last update timestamp |
|
||||
| state_context | JSON\* | NULL | เก็บข้อมูล Context ของ Workflow ณ ขณะนั้น (Snapshot) |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -1673,20 +1673,20 @@
|
||||
|
||||
**Purpose**: Central repository for all file attachments in the system
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------------- | ------------ | --------------------------- | -------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique attachment ID |
|
||||
| original_filename | VARCHAR(255) | NOT NULL | Original filename from upload |
|
||||
| stored_filename | VARCHAR(255) | NOT NULL | System-generated unique filename |
|
||||
| file_path | VARCHAR(500) | NOT NULL | Full file path on server (/share/dms-data/) |
|
||||
| mime_type | VARCHAR(100) | NOT NULL | MIME type (application/pdf, image/jpeg, etc.) |
|
||||
| file_size | INT | NOT NULL | File size in bytes |
|
||||
| uploaded_by_user_id | INT | NOT NULL, FK | User who uploaded file |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Upload timestamp |
|
||||
| is_temporary | BOOLEAN | DEFAULT TRUE | ระบุว่าเป็นไฟล์ชั่วคราว (ยังไม่ได้ Commit) |
|
||||
| temp_id* | VARCHAR(100) | NULL | ID ชั่วคราวสำหรับอ้างอิงตอน Upload Phase 1 (อาจใช้ร่วมกับ id หรือแยกก็ได้) |
|
||||
| expires_at | DATETIME | NULL | เวลาหมดอายุของไฟล์ Temp (เพื่อให้ Cron Job ลบออก) |
|
||||
| checksum | VARCHAR(64) | NULL | SHA-256 Checksum สำหรับ Verify File Integrity [Req 3.9.3] |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------------- | ------------ | --------------------------- | -------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | Unique attachment ID |
|
||||
| original_filename | VARCHAR(255) | NOT NULL | Original filename from upload |
|
||||
| stored_filename | VARCHAR(255) | NOT NULL | System-generated unique filename |
|
||||
| file_path | VARCHAR(500) | NOT NULL | Full file path on server (/share/dms-data/) |
|
||||
| mime_type | VARCHAR(100) | NOT NULL | MIME type (application/pdf, image/jpeg, etc.) |
|
||||
| file_size | INT | NOT NULL | File size in bytes |
|
||||
| uploaded_by_user_id | INT | NOT NULL, FK | User who uploaded file |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Upload timestamp |
|
||||
| is_temporary | BOOLEAN | DEFAULT TRUE | ระบุว่าเป็นไฟล์ชั่วคราว (ยังไม่ได้ Commit) |
|
||||
| temp_id\* | VARCHAR(100) | NULL | ID ชั่วคราวสำหรับอ้างอิงตอน Upload Phase 1 (อาจใช้ร่วมกับ id หรือแยกก็ได้) |
|
||||
| expires_at | DATETIME | NULL | เวลาหมดอายุของไฟล์ Temp (เพื่อให้ Cron Job ลบออก) |
|
||||
| checksum | VARCHAR(64) | NULL | SHA-256 Checksum สำหรับ Verify File Integrity [Req 3.9.3] |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -1865,14 +1865,14 @@
|
||||
|
||||
**Purpose**: Transaction table maintaining running sequence numbers for document numbering
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------------- | --------- | --------------- | ----------------------------------------------- |
|
||||
| project_id | INT | PRIMARY KEY, FK | Reference to projects |
|
||||
| originator_organization_id | INT | PRIMARY KEY, FK | Originating organization |
|
||||
| correspondence_type_id | INT | PRIMARY KEY, FK | Reference to correspondence types |
|
||||
| current_year | INT | PRIMARY KEY | Year (Buddhist calendar) |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------------- | --------- | --------------- | ---------------------------------------------------- |
|
||||
| project_id | INT | PRIMARY KEY, FK | Reference to projects |
|
||||
| originator_organization_id | INT | PRIMARY KEY, FK | Originating organization |
|
||||
| correspondence_type_id | INT | PRIMARY KEY, FK | Reference to correspondence types |
|
||||
| current_year | INT | PRIMARY KEY | Year (Buddhist calendar) |
|
||||
| version | INT | DEFAULT 0 | ใช้สำหรับ Optimistic Locking (ตรวจสอบค่าก่อน Update) |
|
||||
| last_number | INT | DEFAULT 0 | Last assigned sequence number |
|
||||
| last_number | INT | DEFAULT 0 | Last assigned sequence number |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -1905,20 +1905,20 @@
|
||||
|
||||
**Purpose**: Comprehensive audit trail for all significant system actions
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ---------------- | ----------------------------------------- | --------------------------------- | -------------------------------------------------------- |
|
||||
| audit_id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | Unique audit log ID |
|
||||
| user_id | INT | NULL, FK | User who performed action |
|
||||
| action | VARCHAR(100) | NOT NULL | Action code (e.g., 'rfa.create', 'login.success') |
|
||||
| entity_type | VARCHAR(50) | NULL | Entity/module affected (e.g., 'rfa', 'correspondence') |
|
||||
| entity_id | VARCHAR(50) | NULL | Primary ID of affected record |
|
||||
| details_json | JSON | NULL | Additional context/details in JSON format |
|
||||
| ip_address | VARCHAR(45) | NULL | Client IP address (supports IPv6) |
|
||||
| user_agent | VARCHAR(255) | NULL | Browser user agent string |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Action timestamp |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ---------------- | ----------------------------------------- | --------------------------------- | ------------------------------------------------------------ |
|
||||
| audit_id | BIGINT | PRIMARY KEY, AUTO_INCREMENT | Unique audit log ID |
|
||||
| user_id | INT | NULL, FK | User who performed action |
|
||||
| action | VARCHAR(100) | NOT NULL | Action code (e.g., 'rfa.create', 'login.success') |
|
||||
| entity_type | VARCHAR(50) | NULL | Entity/module affected (e.g., 'rfa', 'correspondence') |
|
||||
| entity_id | VARCHAR(50) | NULL | Primary ID of affected record |
|
||||
| details_json | JSON | NULL | Additional context/details in JSON format |
|
||||
| ip_address | VARCHAR(45) | NULL | Client IP address (supports IPv6) |
|
||||
| user_agent | VARCHAR(255) | NULL | Browser user agent string |
|
||||
| created_at | TIMESTAMP | DEFAULT CURRENT_TIMESTAMP | Action timestamp |
|
||||
| v_ref_project_id | INT | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column ดึง Project ID จาก JSON details เพื่อทำ Index |
|
||||
| v_ref_type | VARCHAR(50) | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column ดึง Type จาก JSON details |
|
||||
| request_id | VARCHAR(100) | NULL | Request ID/Trace ID เพื่อเชื่อมโยงกับ App Logs |
|
||||
| v_ref_type | VARCHAR(50) | GENERATED ALWAYS AS (...) VIRTUAL | Virtual Column ดึง Type จาก JSON details |
|
||||
| request_id | VARCHAR(100) | NULL | Request ID/Trace ID เพื่อเชื่อมโยงกับ App Logs |
|
||||
| severity | ENUM('INFO', 'WARN', 'ERROR', 'CRITICAL') | NULL | ระดับความรุนแรงของเหตุการณ์ |
|
||||
|
||||
**Indexes**:
|
||||
@@ -2088,27 +2088,27 @@
|
||||
|
||||
**Purpose**: องรับ **Centralized JSON Schema Registry** เพื่อ Validate ข้อมูล JSON Details ของเอกสารแต่ละประเภท ตาม Requirements 6.11.1 และ Backend Plan T2.5.1
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :-------------------- | :------------- | :--------------- | :------------------------------------------------- |
|
||||
| **id** | `INT` | PK, AI | Unique Identifier |
|
||||
| **schema_code** | `VARCHAR(100)` | UNIQUE, NOT NULL | รหัส Schema (เช่น `RFA_DWG_V1`, `CORR_RFI_V1`) |
|
||||
| **version** | `INT` | NOT NULL | เวอร์ชันของ Schema |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :-------------------- | :------------- | :--------------- | :-------------------------------------------------- |
|
||||
| **id** | `INT` | PK, AI | Unique Identifier |
|
||||
| **schema_code** | `VARCHAR(100)` | UNIQUE, NOT NULL | รหัส Schema (เช่น `RFA_DWG_V1`, `CORR_RFI_V1`) |
|
||||
| **version** | `INT` | NOT NULL | เวอร์ชันของ Schema |
|
||||
| **schema_definition** | `JSON` | NOT NULL | โครงสร้าง JSON Schema (Standard JSON Schema format) |
|
||||
| **is_active** | `BOOLEAN` | DEFAULT TRUE | สถานะการใช้งาน |
|
||||
| **created_at** | `TIMESTAMP` | | วันที่สร้าง |
|
||||
| **created_at** | `TIMESTAMP` | | วันที่สร้าง |
|
||||
|
||||
### 10.6 user_preferences
|
||||
|
||||
**Purpose**: แยกข้อมูลการตั้งค่าส่วนตัว (เช่น Notification Settings) ออกจากตาราง Users เพื่อความยืดหยุ่น ตาม Requirements 5.5 และ 6.8.3
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :--------------- | :------------ | :-------------- | :------------------------------------- |
|
||||
| **user_id** | `INT` | PK, FK | อ้างอิงตาราง users |
|
||||
| **notify_email** | `BOOLEAN` | DEFAULT TRUE | รับแจ้งเตือนทางอีเมล |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :--------------- | :------------ | :-------------- | :---------------------------------------- |
|
||||
| **user_id** | `INT` | PK, FK | อ้างอิงตาราง users |
|
||||
| **notify_email** | `BOOLEAN` | DEFAULT TRUE | รับแจ้งเตือนทางอีเมล |
|
||||
| **notify_line** | `BOOLEAN` | DEFAULT TRUE | รับแจ้งเตือนทาง LINE |
|
||||
| **digest_mode** | `BOOLEAN` | DEFAULT TRUE | รับแจ้งเตือนแบบรวม (Digest) แทน Real-time |
|
||||
| **ui_theme** | `VARCHAR(20)` | DEFAULT 'light' | ธีมหน้าจอ (Light/Dark) |
|
||||
| **updated_at** | `TIMESTAMP` | | วันที่แก้ไขล่าสุด |
|
||||
| **ui_theme** | `VARCHAR(20)` | DEFAULT 'light' | ธีมหน้าจอ (Light/Dark) |
|
||||
| **updated_at** | `TIMESTAMP` | | วันที่แก้ไขล่าสุด |
|
||||
|
||||
## **11. 📊 Views & Procedures (วิว และ โปรซีเดอร์)**
|
||||
|
||||
@@ -2326,28 +2326,23 @@ WHERE user_id = ?
|
||||
**Additional Performance Indexes**:
|
||||
|
||||
1. **Correspondence Tables**:
|
||||
|
||||
- `idx_correspondences_type_project` on (correspondence_type_id, project_id)
|
||||
- `idx_corr_revisions_current_status` on (is_current, correspondence_status_id)
|
||||
- `idx_corr_revisions_correspondence_current` on (correspondence_id, is_current)
|
||||
- `idx_correspondences_project_type` on (project_id, correspondence_type_id)
|
||||
|
||||
2. **RFA Tables**:
|
||||
|
||||
- `idx_rfa_revisions_current_status` on (is_current, rfa_status_code_id)
|
||||
- `idx_rfa_revisions_rfa_current` on (rfa_id, is_current)
|
||||
|
||||
3. **Circulation Tables**:
|
||||
|
||||
- `idx_circulation_routings_status_assigned` on (status, assigned_to)
|
||||
- `idx_circulation_routings_circulation_status` on (circulation_id, status)
|
||||
|
||||
4. **Document Numbering**:
|
||||
|
||||
- `idx_doc_counter_composite` on (project_id, originator_organization_id, correspondence_type_id, current_year)
|
||||
|
||||
5. **Audit & Notifications**:
|
||||
|
||||
- `idx_audit_logs_reporting` on (created_at, entity_type, action)
|
||||
- `idx_notifications_user_unread` on (user_id, is_read, created_at)
|
||||
|
||||
@@ -2375,12 +2370,10 @@ WHERE user_id = ?
|
||||
### Unique Constraints
|
||||
|
||||
1. **Globally Unique**:
|
||||
|
||||
- usernames, emails
|
||||
- shop_drawing.drawing_number
|
||||
|
||||
2. **Unique Within Scope**:
|
||||
|
||||
- (project_id, correspondence_number)
|
||||
- (project_id, condwg_no)
|
||||
- (correspondence_id, revision_number)
|
||||
@@ -2399,13 +2392,11 @@ WHERE user_id = ?
|
||||
### Business Rule Constraints
|
||||
|
||||
1. **Soft Delete Pattern**:
|
||||
|
||||
- deleted_at timestamp instead of hard delete
|
||||
- Preserves audit trail and relationships
|
||||
- Applied to: correspondences, rfas, shop_drawings, contract_drawings
|
||||
|
||||
2. **Current Revision Pattern**:
|
||||
|
||||
- is_current flag with UNIQUE constraint
|
||||
- Ensures only one current revision per document
|
||||
|
||||
@@ -2590,13 +2581,11 @@ ANALYZE TABLE correspondences;
|
||||
### Business Logic Validation
|
||||
|
||||
1. **Document Workflow**:
|
||||
|
||||
- Cannot edit submitted documents (unless Document Control)
|
||||
- Cannot skip workflow steps (unless forced)
|
||||
- Must provide approval comments
|
||||
|
||||
2. **User Management**:
|
||||
|
||||
- Cannot delete users with active assignments
|
||||
- Cannot deactivate own account
|
||||
- Must have valid organization for non-Global roles
|
||||
@@ -2712,19 +2701,16 @@ ANALYZE TABLE correspondences;
|
||||
### Integration Points
|
||||
|
||||
1. **Document Numbering**:
|
||||
|
||||
- Call DocumentNumberingService.generateNextNumber() (NestJS) which handles Redis locking and retry logic
|
||||
- Format with template from document_number_formats
|
||||
- Store in correspondences.correspondence_number
|
||||
|
||||
2. **File Upload**:
|
||||
|
||||
- Upload to QNAP /share/dms-data/
|
||||
- Create attachment record
|
||||
- Link via junction table
|
||||
|
||||
3. **Workflow Execution**:
|
||||
|
||||
- Check rfa_workflow_templates
|
||||
- Create rfa_workflows records
|
||||
- Update status as steps complete
|
||||
|
||||
@@ -2409,28 +2409,23 @@ WHERE user_id = ?
|
||||
**Additional Performance Indexes**:
|
||||
|
||||
1. **Correspondence Tables**:
|
||||
|
||||
- `idx_correspondences_type_project` on (correspondence_type_id, project_id)
|
||||
- `idx_corr_revisions_current_status` on (is_current, correspondence_status_id)
|
||||
- `idx_corr_revisions_correspondence_current` on (correspondence_id, is_current)
|
||||
- `idx_correspondences_project_type` on (project_id, correspondence_type_id)
|
||||
|
||||
2. **RFA Tables**:
|
||||
|
||||
- `idx_rfa_revisions_current_status` on (is_current, rfa_status_code_id)
|
||||
- `idx_rfa_revisions_rfa_current` on (rfa_id, is_current)
|
||||
|
||||
3. **Circulation Tables**:
|
||||
|
||||
- `idx_circulation_routings_status_assigned` on (status, assigned_to)
|
||||
- `idx_circulation_routings_circulation_status` on (circulation_id, status)
|
||||
|
||||
4. **Document Numbering**:
|
||||
|
||||
- `idx_doc_counter_composite` on (project_id, originator_organization_id, correspondence_type_id, current_year)
|
||||
|
||||
5. **Audit & Notifications**:
|
||||
|
||||
- `idx_audit_logs_reporting` on (created_at, entity_type, action)
|
||||
- `idx_notifications_user_unread` on (user_id, is_read, created_at)
|
||||
|
||||
@@ -2458,12 +2453,10 @@ WHERE user_id = ?
|
||||
### Unique Constraints
|
||||
|
||||
1. **Globally Unique**:
|
||||
|
||||
- usernames, emails
|
||||
- shop_drawing.drawing_number
|
||||
|
||||
2. **Unique Within Scope**:
|
||||
|
||||
- (project_id, correspondence_number)
|
||||
- (project_id, condwg_no)
|
||||
- (correspondence_id, revision_number)
|
||||
@@ -2482,13 +2475,11 @@ WHERE user_id = ?
|
||||
### Business Rule Constraints
|
||||
|
||||
1. **Soft Delete Pattern**:
|
||||
|
||||
- deleted_at timestamp instead of hard delete
|
||||
- Preserves audit trail and relationships
|
||||
- Applied to: correspondences, rfas, shop_drawings, contract_drawings
|
||||
|
||||
2. **Current Revision Pattern**:
|
||||
|
||||
- is_current flag with UNIQUE constraint
|
||||
- Ensures only one current revision per document
|
||||
|
||||
@@ -2673,13 +2664,11 @@ ANALYZE TABLE correspondences;
|
||||
### Business Logic Validation
|
||||
|
||||
1. **Document Workflow**:
|
||||
|
||||
- Cannot edit submitted documents (unless Document Control)
|
||||
- Cannot skip workflow steps (unless forced)
|
||||
- Must provide approval comments
|
||||
|
||||
2. **User Management**:
|
||||
|
||||
- Cannot delete users with active assignments
|
||||
- Cannot deactivate own account
|
||||
- Must have valid organization for non-Global roles
|
||||
@@ -2795,19 +2784,16 @@ ANALYZE TABLE correspondences;
|
||||
### Integration Points
|
||||
|
||||
1. **Document Numbering**:
|
||||
|
||||
- Call DocumentNumberingService.generateNextNumber() (NestJS) which handles Redis locking and retry logic
|
||||
- Format with template from document_number_formats
|
||||
- Store in correspondences.correspondence_number
|
||||
|
||||
2. **File Upload**:
|
||||
|
||||
- Upload to QNAP /share/dms-data/
|
||||
- Create attachment record
|
||||
- Link via junction table
|
||||
|
||||
3. **Workflow Execution**:
|
||||
|
||||
- Check rfa_workflow_templates
|
||||
- Create rfa_workflows records
|
||||
- Update status as steps complete
|
||||
|
||||
@@ -10,6 +10,7 @@ Focus on **clarity**, **maintainability**, **consistency**, and **accessibility*
|
||||
## ⚙️ TypeScript General Guidelines
|
||||
|
||||
### Basic Principles
|
||||
|
||||
- Use **English** for all code and documentation.
|
||||
- Explicitly type all variables, parameters, and return values.
|
||||
- Avoid `any`; create custom types or interfaces.
|
||||
@@ -18,13 +19,14 @@ Focus on **clarity**, **maintainability**, **consistency**, and **accessibility*
|
||||
- Avoid blank lines within functions.
|
||||
|
||||
### Naming Conventions
|
||||
| Entity | Convention | Example |
|
||||
|:--|:--|:--|
|
||||
| Classes | PascalCase | `UserService` |
|
||||
| Variables & Functions | camelCase | `getUserInfo` |
|
||||
| Files & Folders | kebab-case | `user-service.ts` |
|
||||
| Environment Variables | UPPERCASE | `DATABASE_URL` |
|
||||
| Booleans | Verb + Noun | `isActive`, `canDelete`, `hasPermission` |
|
||||
|
||||
| Entity | Convention | Example |
|
||||
| :-------------------- | :---------- | :--------------------------------------- |
|
||||
| Classes | PascalCase | `UserService` |
|
||||
| Variables & Functions | camelCase | `getUserInfo` |
|
||||
| Files & Folders | kebab-case | `user-service.ts` |
|
||||
| Environment Variables | UPPERCASE | `DATABASE_URL` |
|
||||
| Booleans | Verb + Noun | `isActive`, `canDelete`, `hasPermission` |
|
||||
|
||||
Use full words — no abbreviations — except for standard ones (`API`, `URL`, `req`, `res`, `err`, `ctx`).
|
||||
|
||||
@@ -82,6 +84,7 @@ Use full words — no abbreviations — except for standard ones (`API`, `URL`,
|
||||
# 🏗️ Backend (NestJS)
|
||||
|
||||
### Principles
|
||||
|
||||
- **Modular architecture**:
|
||||
- One module per domain.
|
||||
- Controller → Service → Model structure.
|
||||
@@ -91,12 +94,14 @@ Use full words — no abbreviations — except for standard ones (`API`, `URL`,
|
||||
- Configs, decorators, DTOs, guards, interceptors, notifications, shared services, types, validators.
|
||||
|
||||
### Core Functionalities
|
||||
|
||||
- Global **filters** for exception handling.
|
||||
- **Middlewares** for request handling.
|
||||
- **Guards** for permissions and RBAC.
|
||||
- **Interceptors** for response transformation and logging.
|
||||
|
||||
### Testing
|
||||
|
||||
- Use **Jest** for testing.
|
||||
- Test each controller and service.
|
||||
- Add `admin/test` endpoint as a smoke test.
|
||||
@@ -106,10 +111,12 @@ Use full words — no abbreviations — except for standard ones (`API`, `URL`,
|
||||
# 🖥️ Frontend (NextJS / React)
|
||||
|
||||
### Developer Profile
|
||||
|
||||
Senior-level TypeScript + React/NextJS engineer.
|
||||
Expert in **TailwindCSS**, **Shadcn/UI**, and **Radix** for UI development.
|
||||
|
||||
### Code Implementation Guidelines
|
||||
|
||||
- Use **early returns** for clarity.
|
||||
- Always style with **TailwindCSS** classes.
|
||||
- Prefer `class:` conditional syntax over ternary operators.
|
||||
@@ -121,6 +128,7 @@ Expert in **TailwindCSS**, **Shadcn/UI**, and **Radix** for UI development.
|
||||
- Always import required modules explicitly.
|
||||
|
||||
### UI/UX with React
|
||||
|
||||
- Use **semantic HTML**.
|
||||
- Apply **responsive Tailwind** classes.
|
||||
- Maintain visual hierarchy with typography and spacing.
|
||||
@@ -132,37 +140,44 @@ Expert in **TailwindCSS**, **Shadcn/UI**, and **Radix** for UI development.
|
||||
# 🎨 UI/UX (Bootstrap Integration)
|
||||
|
||||
### Key Principles
|
||||
|
||||
- Use **Bootstrap 5+** for responsive design and consistent UI.
|
||||
- Focus on **maintainability**, **readability**, and **accessibility**.
|
||||
- Use clear and descriptive class names.
|
||||
|
||||
### Bootstrap Usage
|
||||
|
||||
- Structure layout with **container**, **row**, **col**.
|
||||
- Use built-in **components** (buttons, modals, alerts, etc.) instead of custom CSS.
|
||||
- Apply **utility classes** for quick styling (spacing, colors, text, etc.).
|
||||
- Ensure **ARIA compliance** and semantic markup.
|
||||
|
||||
### Form Validation & Errors
|
||||
|
||||
- Use Bootstrap’s built-in validation states.
|
||||
- Show errors with **alert components**.
|
||||
- Include labels, placeholders, and feedback messages.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Bootstrap (latest CSS + JS)
|
||||
- Optionally jQuery (for legacy interactive components)
|
||||
|
||||
### Bootstrap-Specific Guidelines
|
||||
|
||||
- Customize Bootstrap via **Sass variables** and **mixins**.
|
||||
- Use responsive visibility utilities.
|
||||
- Avoid overriding Bootstrap; extend it.
|
||||
- Follow official documentation for examples.
|
||||
|
||||
### Performance Optimization
|
||||
|
||||
- Include only necessary Bootstrap modules.
|
||||
- Use CDN for assets and caching.
|
||||
- Optimize images and assets for mobile.
|
||||
|
||||
### Key Conventions
|
||||
|
||||
1. Follow Bootstrap’s naming and structure.
|
||||
2. Prioritize **responsiveness** and **accessibility**.
|
||||
3. Keep the file structure organized and modular.
|
||||
@@ -171,15 +186,15 @@ Expert in **TailwindCSS**, **Shadcn/UI**, and **Radix** for UI development.
|
||||
|
||||
# 🔗 Full Stack Integration Guidelines
|
||||
|
||||
| Aspect | Backend (NestJS) | Frontend (NextJS) | UI Layer (Bootstrap/Tailwind) |
|
||||
|:--|:--|:--|:--|
|
||||
| API | REST / GraphQL Controllers | API hooks via fetch/axios | Components consuming data |
|
||||
| Validation | `class-validator` DTOs | `zod` / form-level validation | Bootstrap validation feedback |
|
||||
| Auth | Guards, JWT | NextAuth / cookies | Auth UI states |
|
||||
| Errors | Global filters | Toasts / modals | Alerts / feedback |
|
||||
| Testing | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles | Scoped modules | Tailwind / Shadcn | Bootstrap utilities |
|
||||
| Accessibility | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
| Aspect | Backend (NestJS) | Frontend (NextJS) | UI Layer (Bootstrap/Tailwind) |
|
||||
| :------------ | :------------------------- | :---------------------------- | :---------------------------- |
|
||||
| API | REST / GraphQL Controllers | API hooks via fetch/axios | Components consuming data |
|
||||
| Validation | `class-validator` DTOs | `zod` / form-level validation | Bootstrap validation feedback |
|
||||
| Auth | Guards, JWT | NextAuth / cookies | Auth UI states |
|
||||
| Errors | Global filters | Toasts / modals | Alerts / feedback |
|
||||
| Testing | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles | Scoped modules | Tailwind / Shadcn | Bootstrap utilities |
|
||||
| Accessibility | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ Focus on **clarity**, **maintainability**, **consistency**, and **accessibility*
|
||||
## ⚙️ TypeScript General Guidelines
|
||||
|
||||
### Basic Principles
|
||||
|
||||
- Use **English** for all code and documentation.
|
||||
- Explicitly type all variables, parameters, and return values.
|
||||
- Avoid `any`; create custom types or interfaces.
|
||||
@@ -18,13 +19,14 @@ Focus on **clarity**, **maintainability**, **consistency**, and **accessibility*
|
||||
- Avoid blank lines within functions.
|
||||
|
||||
### Naming Conventions
|
||||
| Entity | Convention | Example |
|
||||
|:--|:--|:--|
|
||||
| Classes | PascalCase | `UserService` |
|
||||
| Variables & Functions | camelCase | `getUserInfo` |
|
||||
| Files & Folders | kebab-case | `user-service.ts` |
|
||||
| Environment Variables | UPPERCASE | `DATABASE_URL` |
|
||||
| Booleans | Verb + Noun | `isActive`, `canDelete`, `hasPermission` |
|
||||
|
||||
| Entity | Convention | Example |
|
||||
| :-------------------- | :---------- | :--------------------------------------- |
|
||||
| Classes | PascalCase | `UserService` |
|
||||
| Variables & Functions | camelCase | `getUserInfo` |
|
||||
| Files & Folders | kebab-case | `user-service.ts` |
|
||||
| Environment Variables | UPPERCASE | `DATABASE_URL` |
|
||||
| Booleans | Verb + Noun | `isActive`, `canDelete`, `hasPermission` |
|
||||
|
||||
Use full words — no abbreviations — except for standard ones (`API`, `URL`, `req`, `res`, `err`, `ctx`).
|
||||
|
||||
@@ -82,6 +84,7 @@ Use full words — no abbreviations — except for standard ones (`API`, `URL`,
|
||||
# 🏗️ Backend (NestJS)
|
||||
|
||||
### Principles
|
||||
|
||||
- **Modular architecture**:
|
||||
- One module per domain.
|
||||
- Controller → Service → Model structure.
|
||||
@@ -91,12 +94,14 @@ Use full words — no abbreviations — except for standard ones (`API`, `URL`,
|
||||
- Configs, decorators, DTOs, guards, interceptors, notifications, shared services, types, validators.
|
||||
|
||||
### Core Functionalities
|
||||
|
||||
- Global **filters** for exception handling.
|
||||
- **Middlewares** for request handling.
|
||||
- **Guards** for permissions and RBAC.
|
||||
- **Interceptors** for response transformation and logging.
|
||||
|
||||
### Testing
|
||||
|
||||
- Use **Jest** for testing.
|
||||
- Test each controller and service.
|
||||
- Add `admin/test` endpoint as a smoke test.
|
||||
@@ -106,10 +111,12 @@ Use full words — no abbreviations — except for standard ones (`API`, `URL`,
|
||||
# 🖥️ Frontend (NextJS / React)
|
||||
|
||||
### Developer Profile
|
||||
|
||||
Senior-level TypeScript + React/NextJS engineer.
|
||||
Expert in **TailwindCSS**, **Shadcn/UI**, and **Radix** for UI development.
|
||||
|
||||
### Code Implementation Guidelines
|
||||
|
||||
- Use **early returns** for clarity.
|
||||
- Always style with **TailwindCSS** classes.
|
||||
- Prefer `class:` conditional syntax over ternary operators.
|
||||
@@ -121,6 +128,7 @@ Expert in **TailwindCSS**, **Shadcn/UI**, and **Radix** for UI development.
|
||||
- Always import required modules explicitly.
|
||||
|
||||
### UI/UX with React
|
||||
|
||||
- Use **semantic HTML**.
|
||||
- Apply **responsive Tailwind** classes.
|
||||
- Maintain visual hierarchy with typography and spacing.
|
||||
@@ -132,37 +140,44 @@ Expert in **TailwindCSS**, **Shadcn/UI**, and **Radix** for UI development.
|
||||
# 🎨 UI/UX (Bootstrap Integration)
|
||||
|
||||
### Key Principles
|
||||
|
||||
- Use **Bootstrap 5+** for responsive design and consistent UI.
|
||||
- Focus on **maintainability**, **readability**, and **accessibility**.
|
||||
- Use clear and descriptive class names.
|
||||
|
||||
### Bootstrap Usage
|
||||
|
||||
- Structure layout with **container**, **row**, **col**.
|
||||
- Use built-in **components** (buttons, modals, alerts, etc.) instead of custom CSS.
|
||||
- Apply **utility classes** for quick styling (spacing, colors, text, etc.).
|
||||
- Ensure **ARIA compliance** and semantic markup.
|
||||
|
||||
### Form Validation & Errors
|
||||
|
||||
- Use Bootstrap’s built-in validation states.
|
||||
- Show errors with **alert components**.
|
||||
- Include labels, placeholders, and feedback messages.
|
||||
|
||||
### Dependencies
|
||||
|
||||
- Bootstrap (latest CSS + JS)
|
||||
- Optionally jQuery (for legacy interactive components)
|
||||
|
||||
### Bootstrap-Specific Guidelines
|
||||
|
||||
- Customize Bootstrap via **Sass variables** and **mixins**.
|
||||
- Use responsive visibility utilities.
|
||||
- Avoid overriding Bootstrap; extend it.
|
||||
- Follow official documentation for examples.
|
||||
|
||||
### Performance Optimization
|
||||
|
||||
- Include only necessary Bootstrap modules.
|
||||
- Use CDN for assets and caching.
|
||||
- Optimize images and assets for mobile.
|
||||
|
||||
### Key Conventions
|
||||
|
||||
1. Follow Bootstrap’s naming and structure.
|
||||
2. Prioritize **responsiveness** and **accessibility**.
|
||||
3. Keep the file structure organized and modular.
|
||||
@@ -171,15 +186,15 @@ Expert in **TailwindCSS**, **Shadcn/UI**, and **Radix** for UI development.
|
||||
|
||||
# 🔗 Full Stack Integration Guidelines
|
||||
|
||||
| Aspect | Backend (NestJS) | Frontend (NextJS) | UI Layer (Bootstrap/Tailwind) |
|
||||
|:--|:--|:--|:--|
|
||||
| API | REST / GraphQL Controllers | API hooks via fetch/axios | Components consuming data |
|
||||
| Validation | `class-validator` DTOs | `zod` / form-level validation | Bootstrap validation feedback |
|
||||
| Auth | Guards, JWT | NextAuth / cookies | Auth UI states |
|
||||
| Errors | Global filters | Toasts / modals | Alerts / feedback |
|
||||
| Testing | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles | Scoped modules | Tailwind / Shadcn | Bootstrap utilities |
|
||||
| Accessibility | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
| Aspect | Backend (NestJS) | Frontend (NextJS) | UI Layer (Bootstrap/Tailwind) |
|
||||
| :------------ | :------------------------- | :---------------------------- | :---------------------------- |
|
||||
| API | REST / GraphQL Controllers | API hooks via fetch/axios | Components consuming data |
|
||||
| Validation | `class-validator` DTOs | `zod` / form-level validation | Bootstrap validation feedback |
|
||||
| Auth | Guards, JWT | NextAuth / cookies | Auth UI states |
|
||||
| Errors | Global filters | Toasts / modals | Alerts / feedback |
|
||||
| Testing | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles | Scoped modules | Tailwind / Shadcn | Bootstrap utilities |
|
||||
| Accessibility | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
|
||||
---
|
||||
|
||||
@@ -191,7 +206,6 @@ Expert in **TailwindCSS**, **Shadcn/UI**, and **Radix** for UI development.
|
||||
- Use **Prettier + ESLint** for consistent formatting.
|
||||
- Prefer **clarity over cleverness** — readable code wins.
|
||||
|
||||
|
||||
---
|
||||
|
||||
# 🗂️ DMS-Specific Conventions (Document Management System)
|
||||
@@ -215,12 +229,13 @@ src/
|
||||
```
|
||||
|
||||
### Naming Convention
|
||||
| Entity | Example |
|
||||
|:--|:--|
|
||||
| Table | `rfa_revisions`, `drawing_contracts` |
|
||||
| DTO | `CreateRfaDto`, `UpdateContractDto` |
|
||||
| Controller | `rfas.controller.ts` |
|
||||
| Service | `rfas.service.ts` |
|
||||
|
||||
| Entity | Example |
|
||||
| :--------- | :----------------------------------- |
|
||||
| Table | `rfa_revisions`, `drawing_contracts` |
|
||||
| DTO | `CreateRfaDto`, `UpdateContractDto` |
|
||||
| Controller | `rfas.controller.ts` |
|
||||
| Service | `rfas.service.ts` |
|
||||
|
||||
---
|
||||
|
||||
@@ -237,11 +252,13 @@ updateRFA(@Param('id') id: string) {
|
||||
```
|
||||
|
||||
### Roles
|
||||
|
||||
- **Admin**: Full access to all modules.
|
||||
- **Editor**: Modify data within assigned modules.
|
||||
- **Viewer**: Read‑only access.
|
||||
|
||||
### Permissions
|
||||
|
||||
- `rfa.create`, `rfa.update`, `rfa.delete`, `rfa.view`
|
||||
- `drawing.upload`, `drawing.map`, `drawing.view`
|
||||
- `contract.assign`, `contract.view`
|
||||
@@ -254,14 +271,14 @@ Seed mapping between roles and permissions via seeder scripts.
|
||||
|
||||
Log all CRUD and mapping operations:
|
||||
|
||||
| Field | Description |
|
||||
|:--|:--|
|
||||
| `actor_id` | user performing the action |
|
||||
| `module_name` | e.g. `rfa`, `drawing` |
|
||||
| `action` | `create`, `update`, `delete`, `map` |
|
||||
| `target_id` | primary id of the record |
|
||||
| `timestamp` | UTC timestamp |
|
||||
| `description` | contextual note |
|
||||
| Field | Description |
|
||||
| :------------ | :---------------------------------- |
|
||||
| `actor_id` | user performing the action |
|
||||
| `module_name` | e.g. `rfa`, `drawing` |
|
||||
| `action` | `create`, `update`, `delete`, `map` |
|
||||
| `target_id` | primary id of the record |
|
||||
| `timestamp` | UTC timestamp |
|
||||
| `description` | contextual note |
|
||||
|
||||
Example implementation:
|
||||
|
||||
@@ -280,6 +297,7 @@ await this.auditLogService.log({
|
||||
## 📂 File Handling
|
||||
|
||||
### File Upload Standard
|
||||
|
||||
- Upload path: `/storage/{year}/{month}/`
|
||||
- File naming: `{drawing_code}_{revision}_{timestamp}.pdf`
|
||||
- Allowed types: `pdf, dwg, docx, xlsx, zip`
|
||||
@@ -288,19 +306,21 @@ await this.auditLogService.log({
|
||||
- Serve via secure endpoint `/files/:id/download`.
|
||||
|
||||
### Access Control
|
||||
|
||||
Each file download must verify user permission (`hasPermission('drawing.view')`).
|
||||
|
||||
---
|
||||
|
||||
## 📊 Reporting & Exports
|
||||
|
||||
| Report | Description |
|
||||
|:--|:--|
|
||||
| **Report A** | RFA → Drawings → All Drawing Revisions |
|
||||
| **Report B** | RFA Revision Timeline vs Drawing Revision |
|
||||
| Report | Description |
|
||||
| :---------------- | :---------------------------------------------- |
|
||||
| **Report A** | RFA → Drawings → All Drawing Revisions |
|
||||
| **Report B** | RFA Revision Timeline vs Drawing Revision |
|
||||
| **Dashboard KPI** | RFAs, Drawings, Revisions, Transmittals summary |
|
||||
|
||||
### Export Rules
|
||||
|
||||
- Export formats: CSV, Excel, PDF.
|
||||
- Provide print view.
|
||||
- Include source entity link (e.g., `/rfas/:id`).
|
||||
@@ -310,11 +330,13 @@ Each file download must verify user permission (`hasPermission('drawing.view')`)
|
||||
## 🧮 Frontend: DataTable & Form Patterns
|
||||
|
||||
### DataTable (Server‑Side)
|
||||
|
||||
- Endpoint: `/api/{module}?page=1&pageSize=20`
|
||||
- Must support: pagination, sorting, search, filters.
|
||||
- Always display latest revision inline (for RFA/Drawing).
|
||||
|
||||
### Form Standards
|
||||
|
||||
- Dependent dropdowns:
|
||||
- Contract → Subcategory
|
||||
- RFA → Related Drawing
|
||||
@@ -326,30 +348,30 @@ Each file download must verify user permission (`hasPermission('drawing.view')`)
|
||||
## 🧭 Dashboard & Activity Feed
|
||||
|
||||
### Dashboard Cards
|
||||
|
||||
- Show latest RFA, Drawing, Transmittal, KPI summary.
|
||||
- Include quick links to modules.
|
||||
|
||||
### Activity Feed
|
||||
|
||||
- Display recent AuditLog actions (10 latest).
|
||||
|
||||
```ts
|
||||
// Example response
|
||||
[
|
||||
{ user: 'admin', action: 'Updated RFA 023-Rev02', time: '2025‑11‑04T09:30Z' }
|
||||
]
|
||||
[{ user: 'admin', action: 'Updated RFA 023-Rev02', time: '2025‑11‑04T09:30Z' }];
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Integration Summary
|
||||
|
||||
| Aspect | Backend | Frontend | Description |
|
||||
|:--|:--|:--|
|
||||
| **File Handling** | Secure storage, token check | Upload/Preview UI | Consistent standard path |
|
||||
| **RBAC** | `RequirePermission` guard | Hide/disable UI actions | Unified permission logic |
|
||||
| **AuditLog** | Persist actions | Show in dashboard | Traceable user activity |
|
||||
| **Reports** | Aggregation queries | Export + Print | Consistent data pipeline |
|
||||
| **DataTables** | Server‑side paging | Filter/Search UI | Scalable dataset management |
|
||||
| Aspect | Backend | Frontend | Description |
|
||||
| :---------------- | :-------------------------- | :---------------------- | --------------------------- |
|
||||
| **File Handling** | Secure storage, token check | Upload/Preview UI | Consistent standard path |
|
||||
| **RBAC** | `RequirePermission` guard | Hide/disable UI actions | Unified permission logic |
|
||||
| **AuditLog** | Persist actions | Show in dashboard | Traceable user activity |
|
||||
| **Reports** | Aggregation queries | Export + Print | Consistent data pipeline |
|
||||
| **DataTables** | Server‑side paging | Filter/Search UI | Scalable dataset management |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,82 +1,84 @@
|
||||
# 📝 Documents Management Sytem Version 1.1.0: Application Requirements Specification
|
||||
|
||||
## 📌 1. วัตถุประสงค์
|
||||
สร้างเว็บแอปพลิเคชั่นสำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System) ที่สามารถจัดการและควบคุม การสื่อสารด้วยเอกสารที่ซับซ้อน อย่างมีประสิทธิภาพ
|
||||
* มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
* ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
* เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
|
||||
## 🛠️ 2. สถาปัตยกรรมและเทคโนโลยี (System Architecture & Technology Stack)
|
||||
สร้างเว็บแอปพลิเคชั่นสำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System) ที่สามารถจัดการและควบคุม การสื่อสารด้วยเอกสารที่ซับซ้อน อย่างมีประสิทธิภาพ
|
||||
|
||||
ใช้สถาปัตยกรรมแบบ Headless/API-First ที่ทันสมัย ทำงานทั้งหมดบน QNAP Server ผ่าน Container Station เพื่อความสะดวกในการจัดการและบำรุงรักษา, Domain: np-dms.work, มี fix ip, รัน docker command ใน application ของ Container Station ได้โดยตรง, ประกอบด้วย
|
||||
- มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
- ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
- เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
|
||||
* 2.1. Infrastructure & Environment:
|
||||
- Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
- Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
|
||||
- Development Environment: VS Code on Windows 11
|
||||
- Domain: np-dms.work, www.np-dms.work
|
||||
- ip: 159.192.126.103
|
||||
- Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
- Data Storage: /share/dms-data บน QNAP
|
||||
- ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
* 2.2. Code Hosting:
|
||||
- Application name: git
|
||||
- Service: Gitea (Self-hosted on QNAP)
|
||||
- Service name: gitea
|
||||
- Domain: git.np-dms.work
|
||||
- หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
|
||||
* 2.3. Backend / Data Platform:
|
||||
- Application name: lcbp3-backend
|
||||
- Service: NestJS
|
||||
- Service name: backend
|
||||
- Domain: backend.np-dms.work
|
||||
- Framework: NestJS (Node.js, TypeScript, ESM)
|
||||
- หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
|
||||
* 2.4. Database:
|
||||
- Application name: lcbp3-db
|
||||
- Service: mariadb:10.11
|
||||
- Service name: mariadb
|
||||
- Domain: db.np-dms.work
|
||||
- หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
|
||||
- Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
|
||||
* 2.5. Database management:
|
||||
- Application name: lcbp3-db
|
||||
- Service: phpmyadmin:5-apache
|
||||
- Service name: pma
|
||||
- Domain: pma.np-dms.work
|
||||
- หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
|
||||
* 2.6. Frontend:
|
||||
- Application name: lcbp3-frontend
|
||||
- Service: next.js
|
||||
- Service name: frontend
|
||||
- Domain: lcbp3.np-dms.work
|
||||
- Framework: Next.js (App Router, React, TypeScript, ESM)
|
||||
- Styling: Tailwind CSS + PostCSS
|
||||
- Component Library: shadcn/ui
|
||||
- หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
|
||||
* 2.7. Workflow automation:
|
||||
- Application name: lcbp3-n8n
|
||||
- Service: n8nio/n8n:latest
|
||||
- Service name: n8n
|
||||
- Domain: n8n.np-dms.work
|
||||
- หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
|
||||
* 2.8. Reverse Proxy:
|
||||
- Application name: lcbp3-npm
|
||||
- Service: Nginx Proxy Manager (nginx-proxy-manage: latest)
|
||||
- Service name: npm
|
||||
- Domain: npm.np-dms.work
|
||||
- หน้าที่: เป็นด่านหน้าในการรับ-ส่งข้อมูล จัดการโดเมนทั้งหมด, ทำหน้าที่เป็น Proxy ชี้ไปยัง Service ที่ถูกต้อง, และจัดการ SSL Certificate (HTTPS) ให้อัตโนมัติ
|
||||
## 🛠️ 2. สถาปัตยกรรมและเทคโนโลยี (System Architecture & Technology Stack)
|
||||
|
||||
ใช้สถาปัตยกรรมแบบ Headless/API-First ที่ทันสมัย ทำงานทั้งหมดบน QNAP Server ผ่าน Container Station เพื่อความสะดวกในการจัดการและบำรุงรักษา, Domain: np-dms.work, มี fix ip, รัน docker command ใน application ของ Container Station ได้โดยตรง, ประกอบด้วย
|
||||
|
||||
- 2.1. Infrastructure & Environment:
|
||||
- Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
- Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
|
||||
- Development Environment: VS Code on Windows 11
|
||||
- Domain: np-dms.work, www.np-dms.work
|
||||
- ip: 159.192.126.103
|
||||
- Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
- Data Storage: /share/dms-data บน QNAP
|
||||
- ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
- 2.2. Code Hosting:
|
||||
- Application name: git
|
||||
- Service: Gitea (Self-hosted on QNAP)
|
||||
- Service name: gitea
|
||||
- Domain: git.np-dms.work
|
||||
- หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
|
||||
- 2.3. Backend / Data Platform:
|
||||
- Application name: lcbp3-backend
|
||||
- Service: NestJS
|
||||
- Service name: backend
|
||||
- Domain: backend.np-dms.work
|
||||
- Framework: NestJS (Node.js, TypeScript, ESM)
|
||||
- หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
|
||||
- 2.4. Database:
|
||||
- Application name: lcbp3-db
|
||||
- Service: mariadb:10.11
|
||||
- Service name: mariadb
|
||||
- Domain: db.np-dms.work
|
||||
- หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
|
||||
- Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
|
||||
- 2.5. Database management:
|
||||
- Application name: lcbp3-db
|
||||
- Service: phpmyadmin:5-apache
|
||||
- Service name: pma
|
||||
- Domain: pma.np-dms.work
|
||||
- หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
|
||||
- 2.6. Frontend:
|
||||
- Application name: lcbp3-frontend
|
||||
- Service: next.js
|
||||
- Service name: frontend
|
||||
- Domain: lcbp3.np-dms.work
|
||||
- Framework: Next.js (App Router, React, TypeScript, ESM)
|
||||
- Styling: Tailwind CSS + PostCSS
|
||||
- Component Library: shadcn/ui
|
||||
- หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
|
||||
- 2.7. Workflow automation:
|
||||
- Application name: lcbp3-n8n
|
||||
- Service: n8nio/n8n:latest
|
||||
- Service name: n8n
|
||||
- Domain: n8n.np-dms.work
|
||||
- หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
|
||||
- 2.8. Reverse Proxy:
|
||||
- Application name: lcbp3-npm
|
||||
- Service: Nginx Proxy Manager (nginx-proxy-manage: latest)
|
||||
- Service name: npm
|
||||
- Domain: npm.np-dms.work
|
||||
- หน้าที่: เป็นด่านหน้าในการรับ-ส่งข้อมูล จัดการโดเมนทั้งหมด, ทำหน้าที่เป็น Proxy ชี้ไปยัง Service ที่ถูกต้อง, และจัดการ SSL Certificate (HTTPS) ให้อัตโนมัติ
|
||||
|
||||
## 📦 3. ข้อกำหนดด้านฟังก์ชันการทำงาน (Functional Requirements)
|
||||
|
||||
* 3.1. การจัดการโครงสร้างโครงการและองค์กร
|
||||
- 3.1. การจัดการโครงสร้างโครงการและองค์กร
|
||||
- 3.1.1. โครงการ (Projects): ระบบต้องสามารถจัดการเอกสารภายในหลายโครงการได้ (ปัจจุบันมี 4 โครงการ และจะเพิ่มขึ้นในอนาคต)
|
||||
- 3.1.2. สัญญา (Contracts): ระบบต้องสามารถจัดการเอกสารภายในแต่ละสัญญาได้ ในแต่ละโครงการ มีได้หลายสัญญา หรืออย่างน้อย 1 สัญญา
|
||||
- 3.1.3. องค์กร (Organizations):
|
||||
- มีหลายองค์กรในโครงการ องค์กรณ์ที่เป็น Owner, Designer และ Consultant สามารถอยู่ในหลายโครงการและหลายสัญญาได้
|
||||
- Contractor จะถือ 1 สัญญา และอยู่ใน 1 โครงการเท่านั้น
|
||||
|
||||
* 3.2. การจัดการเอกสารโต้ตอบ (Correspondence Management)
|
||||
- 3.2. การจัดการเอกสารโต้ตอบ (Correspondence Management)
|
||||
- 3.2.1. วัตถุประสงค์: เอกสารโต้ตอบ (correspondences) ระหว่างองกรณื-องกรณ์ ภายใน โครงการ (Projects) และระหว่าง องค์กร-องค์กร ภายนอก โครงการ (Projects)
|
||||
- 3.2.2. ประเภทเอกสาร: ระบบต้องรองรับเอกสารรูปแบบ ไฟล์ PDF หลายประเภท (Types) เช่น จดหมาย (Letter), อีเมล์ (Email), Request for Information (RFI), และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
|
||||
- 3.2.3. การสร้างเอกสาร (Correspondence):
|
||||
@@ -86,22 +88,21 @@
|
||||
- เอกสารสามารถอ้างถึง (Reference) เอกสารฉบับก่อนหน้าได้หลายฉบับ
|
||||
- สามารถกำหนด Tag ได้หลาย Tag เพื่อจัดกลุ่มและใช้ในการค้นหาขั้นสูง
|
||||
- 3.2.5. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
0 - สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อเป็นผู้รับ ได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบขององกรณ์ที่เป็น ผู้รับ/ผู้ส่ง ทราบ เมื่อมีเอกสารใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
0 - สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อเป็นผู้รับ ได้ - มีระบบแจ้งเตือน ให้ผู้รับผิดชอบขององกรณ์ที่เป็น ผู้รับ/ผู้ส่ง ทราบ เมื่อมีเอกสารใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
|
||||
* 3.3. การจัดกาแบบคู่สัญญา (Contract Drawing)
|
||||
- 3.3. การจัดกาแบบคู่สัญญา (Contract Drawing)
|
||||
- 3.3.1. วัตถุประสงค์: แบบคู่สัญญา (Contract Drawing) ใช้เพื่ออ้างอิงและใช้ในการตรวจสอบ
|
||||
- 3.3.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.3.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.3.4. การอ้างอิงและจัดกลุ่ม: ใช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Contract Drawing
|
||||
- 3.3.4. การอ้างอิงและจัดกลุ่ม: ใช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Contract Drawing
|
||||
|
||||
* 3.4. การจัดกาแบบก่อสร้าง (Shop Drawing)
|
||||
- 3.4. การจัดกาแบบก่อสร้าง (Shop Drawing)
|
||||
- 3.4.1. วัตถุประสงค์: แบบก่อสร้าง (Shop Drawing) ใช้เในการตรวจสอบ โดยจัดส่งด้วย Request for Approval (RFA)
|
||||
- 3.4.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.4.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.4.4. การอ้างอิงและจัดกลุ่ม: ช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Shop Drawings
|
||||
- 3.4.4. การอ้างอิงและจัดกลุ่ม: ช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Shop Drawings
|
||||
|
||||
* 3.5. การจัดการเอกสารขออนุมัติ (Request for Approval & Workflow)
|
||||
- 3.5. การจัดการเอกสารขออนุมัติ (Request for Approval & Workflow)
|
||||
- 3.5.1. วัตถุประสงค์: เอกสารขออนุมัติ (Request for Approval) ใช้ในการส่งเอกสารเพิอขออนุมัติ
|
||||
- 3.5.2. ประเภทเอกสาร: Request for Approval (RFA) เป็นชนิดหนึ่งของ Correspondence ที่มีลักษณะเฉพาะที่ต้องได้รับการอนุมัติ มีประเภทดังนี้:
|
||||
- Request for Drawing Approval (RFA_DWG)
|
||||
@@ -113,19 +114,18 @@
|
||||
- เอกสาร RFA_DWG จะประกอบไปด้วย Shop Drawing (shop_drawings) หลายแผ่น ซึ่งแต่ละแผ่นมี Revision ของตัวเอง
|
||||
- Shop Drawing แต่ละ Revision สามารถอ้างอิงถึง Contract Drawing (Ccontract_drawings) หลายแผ่น หรือไม่อ้างถึงก็ได้
|
||||
- ระบบต้องมีส่วนสำหรับจัดการข้อมูล Master Data ของทั้ง Shop Drawing และ Contract Drawing แยกจากกัน
|
||||
- 3.6.5. Workflow การอนุมัติ: ต้องรองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น
|
||||
- ส่งจาก Originator -> Organization 1 -> Organization 2 -> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Workflow ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
|
||||
- 3.6.5. Workflow การอนุมัติ: ต้องรองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น
|
||||
- ส่งจาก Originator -> Organization 1 -> Organization 2 -> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Workflow ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
|
||||
- 3.6.6. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
0 - สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ทราบ เมื่อมี RFA ใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
0 - สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ได้ - มีระบบแจ้งเตือน ให้ผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ทราบ เมื่อมี RFA ใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
|
||||
* 3.6.การจัดการเอกสารนำส่ง (Transmittals)
|
||||
- 3.6.การจัดการเอกสารนำส่ง (Transmittals)
|
||||
- 3.6.1. วัตถุประสงค์: เอกสารนำส่ง ใช้สำหรับ นำส่ง Request for Approval (RFAS) หลายฉบับ ไปยังองค์กรอื่น
|
||||
- 3.6.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.6.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.6.4. การอ้างอิงและจัดกลุ่ม: เอกสารนำส่ง เป็นส่วนหนึ่งใน Correspondence
|
||||
|
||||
* 3.7. ใบเวียนเอกสารภายใน (Internal Circulation Sheet)
|
||||
- 3.7. ใบเวียนเอกสารภายใน (Internal Circulation Sheet)
|
||||
- 3.7.1. วัตถุประสงค์: การสื่อสาร เอกสาร (Correspondence) ทุกฉบับ จะมีใบเวียนเอกสารเพื่อควบคุมและมอบหมายงานภายในองค์กร (สามารถดูและแก้ไขได้เฉพาะคนในองค์กร)
|
||||
- 3.7.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.7.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ในองค์กรนั้น สามารถสร้างและแก้ไขได้
|
||||
@@ -138,60 +138,59 @@
|
||||
- มีระบบแจ้งเตือนเมื่อมี Circulation ใหม่ และแจ้งเตือนล่วงหน้าก่อนถึงวันแล้วเสร็จ
|
||||
- สามารถปิด Circulation ได้เมื่อดำเนินการตอบกลับไปยังองค์กรผู้ส่ง (Originator) แล้ว หรือ รับทราบแล้ว (For Information)
|
||||
|
||||
* 3.8. ประวัติการแก้ไข (Revisions): ระบบจะเก็บประวัติการสร้างและแก้ไข เอกสารทั้งหมด
|
||||
- 3.8. ประวัติการแก้ไข (Revisions): ระบบจะเก็บประวัติการสร้างและแก้ไข เอกสารทั้งหมด
|
||||
|
||||
* 3.9. การจัดเก็บ: เอกสารและไฟล์แนบจะถูกจัดเก็บในโฟลเดอร์บน Server (/share/dms-data/) โดยมีการอ้างอิงข้อมูล (Metadata) ในฐานข้อมูล และสามารถจัดเรียงตามวันที่ในเอกสาร (Document Date) ได้ ตัวอย่างเช่น
|
||||
- 3.9. การจัดเก็บ: เอกสารและไฟล์แนบจะถูกจัดเก็บในโฟลเดอร์บน Server (/share/dms-data/) โดยมีการอ้างอิงข้อมูล (Metadata) ในฐานข้อมูล และสามารถจัดเรียงตามวันที่ในเอกสาร (Document Date) ได้ ตัวอย่างเช่น
|
||||
- Correspondence จัดเก็บใน /share/dms-data/correspondences/YYMMDD/ชื่อไฟล์.pdf
|
||||
- Request for Approval จัดเก็บใน /share/dms-data/rfas/YYMMDD/ชื่อไฟล์.pdf
|
||||
- Shop Drawings จัดเก็บใน /share/dms-data/shop_drawings/YYMMDD/ชื่อไฟล์.pdf
|
||||
|
||||
## 🔐 4. ข้อกำหนดด้านสิทธิ์และการเข้าถึง (Access Control Requirements)
|
||||
|
||||
* 4.1. ภาพรวม: ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
|
||||
* 4.2. ระดับของสิทธิ์:
|
||||
- 4.1. ภาพรวม: ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
|
||||
- 4.2. ระดับของสิทธิ์:
|
||||
- Global Roles: สิทธิ์ในภาพรวมของระบบ
|
||||
- Project-Specific Roles: สิทธิ์ที่ถูกกำหนดให้ผู้ใช้สำหรับโครงการนั้นๆ โดยเฉพาะ (เช่น เป็น Editor ในโครงการ A แต่เป็น Viewer ในโครงการ B)
|
||||
- Contract-Specific Roles: สิทธิ์ที่ถูกกำหนดให้โครงการสำหรับสัญญานั้นๆ (เช่น เป็น Admin ในสัญญา 1 จะเป็น Admin ใน โครงการ A และ ฺB ที่อยู่ในสัญญา 1)
|
||||
* 4.3. บทบาท (Roles) พื้นฐาน:
|
||||
- 4.3. บทบาท (Roles) พื้นฐาน:
|
||||
- Superadmin: ไม่มีข้อจำกัดใดๆ สามารถจัดการได้ทุกอย่างข้ามองค์กร
|
||||
- Admin: มีสิทธิ์เต็มที่ แต่จำกัดเฉพาะในองค์กรที่ตัวเองสังกัด สามารถจัดการผู้ใช้ในองค์กรได้ สามารถสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลังผ่านหน้า Admin
|
||||
- Document Control สามารถ เพิ่ม/แก้ไข/ลบ เอกสาร เฉพาะในองค์กรที่ตัวเองสังกัด ไม่สามารถจัดการผู้ใช้ได้
|
||||
- Editor: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนดไว้ เฉพาะในองค์กรที่ตัวเองสังกัด
|
||||
- Viewer: สามารถดู เอกสาร เฉพาะในองค์กรที่ตัวเองสังกัด
|
||||
|
||||
* 4.4. การบังคับใช้สิทธิ์: สิทธิ์ขององค์กรจะครอบคลุมสิทธิ์ของผู้ใช้ และการเข้าถึงข้อมูลที่เกี่ยวข้องกับโครงการ (เช่น การแก้ไขเอกสาร) จะถูกตรวจสอบเทียบกับสิทธิ์ที่ผู้ใช้มีในโครงการนั้นๆ โดยเฉพาะ
|
||||
- 4.4. การบังคับใช้สิทธิ์: สิทธิ์ขององค์กรจะครอบคลุมสิทธิ์ของผู้ใช้ และการเข้าถึงข้อมูลที่เกี่ยวข้องกับโครงการ (เช่น การแก้ไขเอกสาร) จะถูกตรวจสอบเทียบกับสิทธิ์ที่ผู้ใช้มีในโครงการนั้นๆ โดยเฉพาะ
|
||||
|
||||
## 👥 5. ข้อกำหนดด้านผู้ใช้งาน (User Interface & Experience)
|
||||
|
||||
* 5.1. Layout หลัก: หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย:
|
||||
- 5.1. Layout หลัก: หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย:
|
||||
- Navbar (ส่วนบน): แสดงชื่อระบบ, เมนูผู้ใช้ (Profile), เมนูสำหรับ Admin/Superadmin (จัดการผู้ใช้, จัดการสิทธิ์), และปุ่ม Login/Logout
|
||||
- Sidebar (ด้านข้าง): เป็นเมนูหลักสำหรับเข้าถึงส่วนที่เกี่ยวกับเอกสารทั้งหมด เช่น Dashboard, Correspondences, RFA, Drawings
|
||||
- Main Content Area: พื้นที่สำหรับแสดงเนื้อหาหลักของหน้าที่เลือก
|
||||
* 5.2. หน้า Landing Page: เป็นหน้าแรกที่แสดงข้อมูลบางส่วนของโครงการสำหรับผู้ใช้ที่ยังไม่ได้ล็อกอิน
|
||||
* 5.3. หน้า Dashboard: เป็นหน้าแรกหลังจากล็อกอิน ประกอบด้วย:
|
||||
- 5.2. หน้า Landing Page: เป็นหน้าแรกที่แสดงข้อมูลบางส่วนของโครงการสำหรับผู้ใช้ที่ยังไม่ได้ล็อกอิน
|
||||
- 5.3. หน้า Dashboard: เป็นหน้าแรกหลังจากล็อกอิน ประกอบด้วย:
|
||||
- การ์ดสรุปภาพรวม (KPI Cards): แสดงข้อมูลสรุปที่สำคัญขององค์กร เช่น จำนวนเอกสาร, งานที่เกินกำหนด
|
||||
- ตาราง "งานของฉัน" (My Tasks Table): แสดงรายการงานทั้งหมดจาก Circulation ที่ผู้ใช้ต้องดำเนินการ
|
||||
* 5.4. การติดตามสถานะ: องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
|
||||
* 5.5. การจัดการข้อมูลส่วนตัว (Profile Page): ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้
|
||||
* 5.6. การจัดการเอกสารทางเทคนิค (Technical Documents & Workflow): ผู้ใช้สามารถดู Technical Document ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว, ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ admin ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ admin ขึ้นไป
|
||||
- 5.4. การติดตามสถานะ: องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
|
||||
- 5.5. การจัดการข้อมูลส่วนตัว (Profile Page): ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้
|
||||
- 5.6. การจัดการเอกสารทางเทคนิค (Technical Documents & Workflow): ผู้ใช้สามารถดู Technical Document ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว, ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ admin ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ admin ขึ้นไป
|
||||
|
||||
## 6. ข้อกำหนดที่ไม่ใช่ฟังก์ชันการทำงาน (Non-Functional Requirements)
|
||||
|
||||
* 6.1. การบันทึกการกระทำ (Audit Log): ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน audit_logs เพื่อการตรวจสอบย้อนหลัง
|
||||
* 6.2. การค้นหา (Search): ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสารจากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
|
||||
* 6.3. การทำรายงาน (Reporting): สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
|
||||
* 6.4. ประสิทธิภาพ (Performance): มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
* 6.5. ความปลอดภัย (Security):
|
||||
- 6.1. การบันทึกการกระทำ (Audit Log): ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน audit_logs เพื่อการตรวจสอบย้อนหลัง
|
||||
- 6.2. การค้นหา (Search): ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสารจากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
|
||||
- 6.3. การทำรายงาน (Reporting): สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
|
||||
- 6.4. ประสิทธิภาพ (Performance): มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
- 6.5. ความปลอดภัย (Security):
|
||||
- มีระบบ Rate Limiting เพื่อป้องกันการโจมตีแบบ Brute-force
|
||||
- การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด
|
||||
|
||||
## 📈 7.
|
||||
## 📈 7.
|
||||
|
||||
## 🧩 8.
|
||||
|
||||
🎯
|
||||
📤
|
||||
📊
|
||||
✅
|
||||
🔄
|
||||
|
||||
|
||||
|
||||
@@ -5,195 +5,195 @@
|
||||
แนวทางปฏิบัติที่ดีที่สุดแบบครบวงจรสำหรับการพัฒนา **NestJS Backend**, **NextJS Frontend** และ **Tailwind-based UI/UX** ในสภาพแวดล้อม TypeScript
|
||||
มุ่งเน้นที่ **ความชัดเจน (clarity)**, **ความง่ายในการบำรุงรักษา (maintainability)**, **ความสอดคล้องกัน (consistency)** และ **การเข้าถึงได้ (accessibility)** ตลอดทั้งสแต็ก
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## ⚙️ แนวทางทั่วไปสำหรับ TypeScript
|
||||
|
||||
### หลักการพื้นฐาน
|
||||
|
||||
- ใช้ **ภาษาอังกฤษ** สำหรับโค้ดและเอกสารทั้งหมด
|
||||
- กำหนดไทป์ (type) อย่างชัดเจนสำหรับตัวแปร, พารามิเตอร์ และค่าที่ส่งกลับ (return values) ทั้งหมด
|
||||
- หลีกเลี่ยงการใช้ `any`; ให้สร้างไทป์ (types) หรืออินเทอร์เฟซ (interfaces) ที่กำหนดเอง
|
||||
- ใช้ **JSDoc** สำหรับคลาส (classes) และเมธอด (methods) ที่เป็น public
|
||||
- ส่งออก (Export) **สัญลักษณ์หลัก (main symbol) เพียงหนึ่งเดียว** ต่อไฟล์
|
||||
- หลีกเลี่ยงบรรทัดว่างภายในฟังก์ชัน
|
||||
- ใช้ **ภาษาอังกฤษ** สำหรับโค้ดและเอกสารทั้งหมด
|
||||
- กำหนดไทป์ (type) อย่างชัดเจนสำหรับตัวแปร, พารามิเตอร์ และค่าที่ส่งกลับ (return values) ทั้งหมด
|
||||
- หลีกเลี่ยงการใช้ `any`; ให้สร้างไทป์ (types) หรืออินเทอร์เฟซ (interfaces) ที่กำหนดเอง
|
||||
- ใช้ **JSDoc** สำหรับคลาส (classes) และเมธอด (methods) ที่เป็น public
|
||||
- ส่งออก (Export) **สัญลักษณ์หลัก (main symbol) เพียงหนึ่งเดียว** ต่อไฟล์
|
||||
- หลีกเลี่ยงบรรทัดว่างภายในฟังก์ชัน
|
||||
|
||||
### ข้อตกลงในการตั้งชื่อ (Naming Conventions)
|
||||
|
||||
| Entity (สิ่งที่ตั้งชื่อ) | Convention (รูปแบบ) | Example (ตัวอย่าง) |
|
||||
|:--|:--|:--|
|
||||
| Classes | PascalCase | `UserService` |
|
||||
| Variables & Functions | camelCase | `getUserInfo` |
|
||||
| Files & Folders | kebab-case | `user-service.ts` |
|
||||
| Environment Variables | UPPERCASE | `DATABASE_URL` |
|
||||
| Booleans | Verb + Noun | `isActive`, `canDelete`, `hasPermission` |
|
||||
| Entity (สิ่งที่ตั้งชื่อ) | Convention (รูปแบบ) | Example (ตัวอย่าง) |
|
||||
| :----------------------- | :------------------ | :--------------------------------------- |
|
||||
| Classes | PascalCase | `UserService` |
|
||||
| Variables & Functions | camelCase | `getUserInfo` |
|
||||
| Files & Folders | kebab-case | `user-service.ts` |
|
||||
| Environment Variables | UPPERCASE | `DATABASE_URL` |
|
||||
| Booleans | Verb + Noun | `isActive`, `canDelete`, `hasPermission` |
|
||||
|
||||
ใช้คำเต็ม — ไม่ใช้อักษรย่อ — ยกเว้นคำมาตรฐาน (เช่น `API`, `URL`, `req`, `res`, `err`, `ctx`)
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🧩 ฟังก์ชัน (Functions)
|
||||
|
||||
- เขียนฟังก์ชันให้สั้น และทำ **หน้าที่เพียงอย่างเดียว** (single-purpose) (\< 20 บรรทัด)
|
||||
- ใช้ **early returns** เพื่อลดการซ้อน (nesting) ของโค้ด
|
||||
- ใช้ **map**, **filter**, **reduce** แทนการใช้ loops เมื่อเหมาะสม
|
||||
- ควรใช้ **arrow functions** สำหรับตรรกะสั้นๆ, และใช้ **named functions** ในกรณีอื่น
|
||||
- ใช้ **default parameters** แทนการตรวจสอบค่า null
|
||||
- จัดกลุ่มพารามิเตอร์หลายตัวให้เป็นอ็อบเจกต์เดียว (RO-RO pattern)
|
||||
- ส่งค่ากลับ (Return) เป็นอ็อบเจกต์ที่มีไทป์กำหนด (typed objects) ไม่ใช่ค่าพื้นฐาน (primitives)
|
||||
- รักษาระดับของสิ่งที่เป็นนามธรรม (abstraction level) ให้เป็นระดับเดียวในแต่ละฟังก์ชัน
|
||||
- เขียนฟังก์ชันให้สั้น และทำ **หน้าที่เพียงอย่างเดียว** (single-purpose) (\< 20 บรรทัด)
|
||||
- ใช้ **early returns** เพื่อลดการซ้อน (nesting) ของโค้ด
|
||||
- ใช้ **map**, **filter**, **reduce** แทนการใช้ loops เมื่อเหมาะสม
|
||||
- ควรใช้ **arrow functions** สำหรับตรรกะสั้นๆ, และใช้ **named functions** ในกรณีอื่น
|
||||
- ใช้ **default parameters** แทนการตรวจสอบค่า null
|
||||
- จัดกลุ่มพารามิเตอร์หลายตัวให้เป็นอ็อบเจกต์เดียว (RO-RO pattern)
|
||||
- ส่งค่ากลับ (Return) เป็นอ็อบเจกต์ที่มีไทป์กำหนด (typed objects) ไม่ใช่ค่าพื้นฐาน (primitives)
|
||||
- รักษาระดับของสิ่งที่เป็นนามธรรม (abstraction level) ให้เป็นระดับเดียวในแต่ละฟังก์ชัน
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🧱 การจัดการข้อมูล (Data Handling)
|
||||
|
||||
- ห่อหุ้มข้อมูล (Encapsulate) ในไทป์แบบผสม (composite types)
|
||||
- ใช้ **immutability** (การไม่เปลี่ยนแปลงค่า) ด้วย `readonly` และ `as const`
|
||||
- ทำการตรวจสอบความถูกต้องของข้อมูล (Validations) ในคลาสหรือ DTOs ไม่ใช่ภายในฟังก์ชันทางธุรกิจ
|
||||
- ตรวจสอบความถูกต้องของข้อมูลโดยใช้ DTOs ที่มีไทป์กำหนดเสมอ
|
||||
- ห่อหุ้มข้อมูล (Encapsulate) ในไทป์แบบผสม (composite types)
|
||||
- ใช้ **immutability** (การไม่เปลี่ยนแปลงค่า) ด้วย `readonly` และ `as const`
|
||||
- ทำการตรวจสอบความถูกต้องของข้อมูล (Validations) ในคลาสหรือ DTOs ไม่ใช่ภายในฟังก์ชันทางธุรกิจ
|
||||
- ตรวจสอบความถูกต้องของข้อมูลโดยใช้ DTOs ที่มีไทป์กำหนดเสมอ
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🧰 คลาส (Classes)
|
||||
|
||||
- ปฏิบัติตามหลักการ **SOLID**
|
||||
- ควรใช้ **composition มากกว่า inheritance** (Prefer composition over inheritance)
|
||||
- กำหนด **interfaces** สำหรับสัญญา (contracts)
|
||||
- ให้คลาสมุ่งเน้นการทำงานเฉพาะอย่างและมีขนาดเล็ก (\< 200 บรรทัด, \< 10 เมธอด, \< 10 properties)
|
||||
- ปฏิบัติตามหลักการ **SOLID**
|
||||
- ควรใช้ **composition มากกว่า inheritance** (Prefer composition over inheritance)
|
||||
- กำหนด **interfaces** สำหรับสัญญา (contracts)
|
||||
- ให้คลาสมุ่งเน้นการทำงานเฉพาะอย่างและมีขนาดเล็ก (\< 200 บรรทัด, \< 10 เมธอด, \< 10 properties)
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🚨 การจัดการข้อผิดพลาด (Error Handling)
|
||||
|
||||
- ใช้ Exceptions สำหรับข้อผิดพลาดที่ไม่คาดคิด
|
||||
- ดักจับ (Catch) ข้อผิดพลาดเพื่อแก้ไขหรือเพิ่มบริบท (context) เท่านั้น; หากไม่เช่นนั้น ให้ใช้ global error handlers
|
||||
- ระบุข้อความข้อผิดพลาด (error messages) ที่มีความหมายเสมอ
|
||||
- ใช้ Exceptions สำหรับข้อผิดพลาดที่ไม่คาดคิด
|
||||
- ดักจับ (Catch) ข้อผิดพลาดเพื่อแก้ไขหรือเพิ่มบริบท (context) เท่านั้น; หากไม่เช่นนั้น ให้ใช้ global error handlers
|
||||
- ระบุข้อความข้อผิดพลาด (error messages) ที่มีความหมายเสมอ
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🧪 การทดสอบ (ทั่วไป) (Testing (General))
|
||||
|
||||
- ใช้รูปแบบ **Arrange–Act–Assert**
|
||||
- ใช้ชื่อตัวแปรในการทดสอบที่สื่อความหมาย (`inputData`, `expectedOutput`)
|
||||
- เขียน **unit tests** สำหรับ public methods ทั้งหมด
|
||||
- จำลอง (Mock) การพึ่งพาภายนอก (external dependencies)
|
||||
- เพิ่ม **acceptance tests** ต่อโมดูลโดยใช้รูปแบบ Given–When–Then
|
||||
- ใช้รูปแบบ **Arrange–Act–Assert**
|
||||
- ใช้ชื่อตัวแปรในการทดสอบที่สื่อความหมาย (`inputData`, `expectedOutput`)
|
||||
- เขียน **unit tests** สำหรับ public methods ทั้งหมด
|
||||
- จำลอง (Mock) การพึ่งพาภายนอก (external dependencies)
|
||||
- เพิ่ม **acceptance tests** ต่อโมดูลโดยใช้รูปแบบ Given–When–Then
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
# 🏗️ แบ็กเอนด์ (NestJS) (Backend (NestJS))
|
||||
|
||||
### หลักการ
|
||||
|
||||
- **สถาปัตยกรรมแบบโมดูลาร์ (Modular architecture)**:
|
||||
- หนึ่งโมดูลต่อหนึ่งโดเมน
|
||||
- โครงสร้างแบบ Controller → Service → Repository (Model)
|
||||
- DTOs ที่ตรวจสอบความถูกต้องด้วย **class-validator**
|
||||
- ใช้ **MikroORM** (หรือ TypeORM/Prisma) สำหรับการคงอยู่ของข้อมูล (persistence) ซึ่งสอดคล้องกับสคีมา MariaDB
|
||||
- ห่อหุ้มโค้ดที่ใช้ซ้ำได้ไว้ใน **common module** (`@app/common`):
|
||||
- Configs, decorators, DTOs, guards, interceptors, notifications, shared services, types, validators
|
||||
- **สถาปัตยกรรมแบบโมดูลาร์ (Modular architecture)**:
|
||||
- หนึ่งโมดูลต่อหนึ่งโดเมน
|
||||
- โครงสร้างแบบ Controller → Service → Repository (Model)
|
||||
- DTOs ที่ตรวจสอบความถูกต้องด้วย **class-validator**
|
||||
- ใช้ **MikroORM** (หรือ TypeORM/Prisma) สำหรับการคงอยู่ของข้อมูล (persistence) ซึ่งสอดคล้องกับสคีมา MariaDB
|
||||
- ห่อหุ้มโค้ดที่ใช้ซ้ำได้ไว้ใน **common module** (`@app/common`):
|
||||
- Configs, decorators, DTOs, guards, interceptors, notifications, shared services, types, validators
|
||||
|
||||
### ฟังก์ชันหลัก (Core Functionalities)
|
||||
|
||||
- Global **filters** สำหรับการจัดการ exception
|
||||
- **Middlewares** สำหรับการจัดการ request
|
||||
- **Guards** สำหรับการอนุญาต (permissions) และ RBAC
|
||||
- **Interceptors** สำหรับการแปลงข้อมูล response และการบันทึก log
|
||||
- Global **filters** สำหรับการจัดการ exception
|
||||
- **Middlewares** สำหรับการจัดการ request
|
||||
- **Guards** สำหรับการอนุญาต (permissions) และ RBAC
|
||||
- **Interceptors** สำหรับการแปลงข้อมูล response และการบันทึก log
|
||||
|
||||
### ข้อจำกัดในการ Deploy (QNAP Container Station)
|
||||
|
||||
- **ห้ามใช้ไฟล์ `.env`** ในการตั้งค่า Environment Variables
|
||||
- การตั้งค่าทั้งหมด (เช่น Database connection string, JWT secret) **จะต้องถูกกำหนดผ่าน Environment Variable ใน `docker-compose.yml` โดยตรง** ซึ่งจะจัดการผ่าน UI ของ QNAP Container Station
|
||||
- **ห้ามใช้ไฟล์ `.env`** ในการตั้งค่า Environment Variables
|
||||
- การตั้งค่าทั้งหมด (เช่น Database connection string, JWT secret) **จะต้องถูกกำหนดผ่าน Environment Variable ใน `docker-compose.yml` โดยตรง** ซึ่งจะจัดการผ่าน UI ของ QNAP Container Station
|
||||
|
||||
### โครงสร้างโมดูลตามโดเมน (Domain-Driven Module Structure)
|
||||
|
||||
เพื่อให้สอดคล้องกับสคีมา SQL (LCBP3-DMS) เราจะใช้โครงสร้างโมดูลแบบ **Domain-Driven (แบ่งตามขอบเขตธุรกิจ)** แทนการแบ่งตามฟังก์ชัน:
|
||||
|
||||
1. **CoreModule / CommonModule:**
|
||||
* เก็บ Services ที่ใช้ร่วมกัน เช่น `DatabaseModule`, `FileStorageService` (จัดการไฟล์ใน QNAP), `AuditLogService`, และ `NotificationService`
|
||||
- เก็บ Services ที่ใช้ร่วมกัน เช่น `DatabaseModule`, `FileStorageService` (จัดการไฟล์ใน QNAP), `AuditLogService`, และ `NotificationService`
|
||||
2. **AuthModule / UserModule:**
|
||||
* จัดการ `users`, `roles`, `permissions` และการยืนยันตัวตน (JWT, Guards)
|
||||
* **(สำคัญ)** ต้องรับผิดชอบการตรวจสอบสิทธิ์ **3 ระดับ**: สิทธิ์ระดับระบบ (Global Role), สิทธิ์ระดับโปรเจกต์ (Project Role), และ **สิทธิ์ระดับสัญญา (Contract Role)**
|
||||
* **(สำคัญ)** ต้องมี API สำหรับ Admin เพื่อ **สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก** (ไม่ใช่แค่ seed ข้อมูลเริ่มต้น)
|
||||
- จัดการ `users`, `roles`, `permissions` และการยืนยันตัวตน (JWT, Guards)
|
||||
- **(สำคัญ)** ต้องรับผิดชอบการตรวจสอบสิทธิ์ **3 ระดับ**: สิทธิ์ระดับระบบ (Global Role), สิทธิ์ระดับโปรเจกต์ (Project Role), และ **สิทธิ์ระดับสัญญา (Contract Role)**
|
||||
- **(สำคัญ)** ต้องมี API สำหรับ Admin เพื่อ **สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก** (ไม่ใช่แค่ seed ข้อมูลเริ่มต้น)
|
||||
3. **ProjectModule:**
|
||||
* จัดการ `projects`, `organizations`, `contracts`, `project_parties`, `contract_parties`
|
||||
- จัดการ `projects`, `organizations`, `contracts`, `project_parties`, `contract_parties`
|
||||
4. **CorrespondenceModule (โมดูลศูนย์กลาง):**
|
||||
* จัดการ `correspondences`, `correspondence_revisions`
|
||||
* จัดการ `correspondence_attachments` (ตารางเชื่อมไฟล์แนบ)
|
||||
* รับผิดชอบเวิร์กโฟลว์ **"Correspondence Routings"** (`correspondence_routings`) สำหรับการส่งต่อเอกสารทั่วไประหว่างองค์กร
|
||||
- จัดการ `correspondences`, `correspondence_revisions`
|
||||
- จัดการ `correspondence_attachments` (ตารางเชื่อมไฟล์แนบ)
|
||||
- รับผิดชอบเวิร์กโฟลว์ **"Correspondence Routings"** (`correspondence_routings`) สำหรับการส่งต่อเอกสารทั่วไประหว่างองค์กร
|
||||
5. **RfaModule:**
|
||||
* จัดการ `rfas`, `rfa_revisions`, `rfa_items`
|
||||
* รับผิดชอบเวิร์กโฟลว์ **"RFA Workflows"** (`rfa_workflows`) สำหรับการอนุมัติเอกสารทางเทคนิค
|
||||
- จัดการ `rfas`, `rfa_revisions`, `rfa_items`
|
||||
- รับผิดชอบเวิร์กโฟลว์ **"RFA Workflows"** (`rfa_workflows`) สำหรับการอนุมัติเอกสารทางเทคนิค
|
||||
6. **DrawingModule:**
|
||||
* จัดการ `shop_drawings`, `shop_drawing_revisions`, `contract_drawings` และหมวดหมู่ต่างๆ
|
||||
* จัดการ `shop_drawing_revision_attachments` (ตารางเชื่อมไฟล์แนบ)
|
||||
- จัดการ `shop_drawings`, `shop_drawing_revisions`, `contract_drawings` และหมวดหมู่ต่างๆ
|
||||
- จัดการ `shop_drawing_revision_attachments` (ตารางเชื่อมไฟล์แนบ)
|
||||
7. **CirculationModule:**
|
||||
* จัดการ `circulations`, `circulation_templates`, `circulation_assignees`
|
||||
* จัดการ `circulation_attachments` (ตารางเชื่อมไฟล์แนบ)
|
||||
* รับผิดชอบเวิร์กโฟลGว์ **"Circulations"** สำหรับการเวียนเอกสาร **ภายในองค์กร**
|
||||
- จัดการ `circulations`, `circulation_templates`, `circulation_assignees`
|
||||
- จัดการ `circulation_attachments` (ตารางเชื่อมไฟล์แนบ)
|
||||
- รับผิดชอบเวิร์กโฟลGว์ **"Circulations"** สำหรับการเวียนเอกสาร **ภายในองค์กร**
|
||||
8. **TransmittalModule:**
|
||||
* จัดการ `transmittals` และ `transmittal_items`
|
||||
- จัดการ `transmittals` และ `transmittal_items`
|
||||
9. **SearchModule:**
|
||||
* **(สำหรับ V1)** ให้บริการค้นหาขั้นสูง (Advanced Search) โดยต้องรองรับการกรองจาก ชื่อเรื่อง (LIKE), ประเภท, วันที่, และ **Tags** (ผ่านการ Join ตาราง) โดยค้นหาผ่าน Views (`v_current_rfas`, `v_current_correspondences`)
|
||||
- **(สำหรับ V1)** ให้บริการค้นหาขั้นสูง (Advanced Search) โดยต้องรองรับการกรองจาก ชื่อเรื่อง (LIKE), ประเภท, วันที่, และ **Tags** (ผ่านการ Join ตาราง) โดยค้นหาผ่าน Views (`v_current_rfas`, `v_current_correspondences`)
|
||||
|
||||
### เครื่องมือและไลบรารีที่แนะนำ (Recommended Tools & Libraries)
|
||||
|
||||
🔐 **Authentication & Authorization**
|
||||
|
||||
* `@nestjs/passport`
|
||||
* `@nestjs/jwt`
|
||||
* `casl` – สำหรับ RBAC (Role-Based Access Control)
|
||||
- `@nestjs/passport`
|
||||
- `@nestjs/jwt`
|
||||
- `casl` – สำหรับ RBAC (Role-Based Access Control)
|
||||
|
||||
🗃️ **Database & ORM**
|
||||
|
||||
* `@nestjs/typeorm` – ORM สำหรับ SQL (หรือ `Prisma` เป็นทางเลือก)
|
||||
* `typeorm-seeding` – สำหรับสร้างข้อมูลจำลอง (seeding)
|
||||
- `@nestjs/typeorm` – ORM สำหรับ SQL (หรือ `Prisma` เป็นทางเลือก)
|
||||
- `typeorm-seeding` – สำหรับสร้างข้อมูลจำลอง (seeding)
|
||||
|
||||
📦 **Validation & Transformation**
|
||||
|
||||
* `class-validator`
|
||||
* `class-transformer`
|
||||
- `class-validator`
|
||||
- `class-transformer`
|
||||
|
||||
📁 **File Upload & Storage**
|
||||
|
||||
* `@nestjs/platform-express`
|
||||
* `multer` – สำหรับจัดการไฟล์
|
||||
- `@nestjs/platform-express`
|
||||
- `multer` – สำหรับจัดการไฟล์
|
||||
|
||||
🔍 **Search**
|
||||
|
||||
* **(สำหรับ V1)** เน้นการค้นหาขั้นสูงตาม Requirement 6.2 (Full-text search/Elasticsearch จะพิจารณาใน V2)
|
||||
- **(สำหรับ V1)** เน้นการค้นหาขั้นสูงตาม Requirement 6.2 (Full-text search/Elasticsearch จะพิจารณาใน V2)
|
||||
|
||||
📬 **Notification**
|
||||
|
||||
* `nodemailer` – สำหรับส่งอีเมล
|
||||
* `@nestjs/schedule` – สำหรับ cron job หรือแจ้งเตือนตามเวลา
|
||||
- `nodemailer` – สำหรับส่งอีเมล
|
||||
- `@nestjs/schedule` – สำหรับ cron job หรือแจ้งเตือนตามเวลา
|
||||
|
||||
📊 **Logging & Monitoring**
|
||||
|
||||
* `winston` หรือ `nestjs-pino` – ระบบ log ที่ยืดหยุ่น
|
||||
* `@nestjs/terminus` – สำหรับ health check
|
||||
- `winston` หรือ `nestjs-pino` – ระบบ log ที่ยืดหยุ่น
|
||||
- `@nestjs/terminus` – สำหรับ health check
|
||||
|
||||
🧪 **Testing**
|
||||
|
||||
* `@nestjs/testing`
|
||||
* `jest` – สำหรับ unit/integration test
|
||||
- `@nestjs/testing`
|
||||
- `jest` – สำหรับ unit/integration test
|
||||
|
||||
🌐 **API Documentation**
|
||||
|
||||
* `@nestjs/swagger` – **(สำคัญมาก)** สร้าง Swagger UI อัตโนมัติ ต้องใช้ DTOs อย่างเคร่งครัดเพื่อความชัดเจนของ API สำหรับทีม Frontend
|
||||
- `@nestjs/swagger` – **(สำคัญมาก)** สร้าง Swagger UI อัตโนมัติ ต้องใช้ DTOs อย่างเคร่งครัดเพื่อความชัดเจนของ API สำหรับทีม Frontend
|
||||
|
||||
🛡️ **Security**
|
||||
|
||||
* `helmet` – ป้องกันช่องโหว่ HTTP
|
||||
* `rate-limiter-flexible` – ป้องกัน brute force
|
||||
- `helmet` – ป้องกันช่องโหว่ HTTP
|
||||
- `rate-limiter-flexible` – ป้องกัน brute force
|
||||
|
||||
### การทดสอบ (Testing)
|
||||
|
||||
- ใช้ **Jest** สำหรับการทดสอบ
|
||||
- ทดสอบทุก controller และ service
|
||||
- เพิ่ม endpoint `admin/test` เพื่อใช้เป็น smoke test
|
||||
- ใช้ **Jest** สำหรับการทดสอบ
|
||||
- ทดสอบทุก controller และ service
|
||||
- เพิ่ม endpoint `admin/test` เพื่อใช้เป็น smoke test
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
# 🖥️ ฟรอนต์เอนด์ (NextJS / React / UI) (Frontend (NextJS / React / UI))
|
||||
|
||||
@@ -204,47 +204,47 @@
|
||||
|
||||
### แนวทางการพัฒนาโค้ด (Code Implementation Guidelines)
|
||||
|
||||
- ใช้ **early returns** เพื่อความชัดเจน
|
||||
- ใช้คลาสของ **TailwindCSS** ในการกำหนดสไตล์เสมอ
|
||||
- ควรใช้ `class:` syntax แบบมีเงื่อนไข (หรือ utility `clsx`) มากกว่าการใช้ ternary operators ใน class strings
|
||||
- ใช้ **const arrow functions** สำหรับ components และ handlers
|
||||
- Event handlers ให้ขึ้นต้นด้วย `handle...` (เช่น `handleClick`, `handleSubmit`)
|
||||
- รวมแอตทริบิวต์สำหรับการเข้าถึง (accessibility) ด้วย:
|
||||
`tabIndex="0"`, `aria-label`, `onKeyDown`, ฯลฯ
|
||||
- ตรวจสอบให้แน่ใจว่าโค้ดทั้งหมด **สมบูรณ์**, **ผ่านการทดสอบ**, และ **ไม่ซ้ำซ้อน (DRY)**
|
||||
- ต้อง import โมดูลที่จำเป็นต้องใช้อย่างชัดเจนเสมอ
|
||||
- ใช้ **early returns** เพื่อความชัดเจน
|
||||
- ใช้คลาสของ **TailwindCSS** ในการกำหนดสไตล์เสมอ
|
||||
- ควรใช้ `class:` syntax แบบมีเงื่อนไข (หรือ utility `clsx`) มากกว่าการใช้ ternary operators ใน class strings
|
||||
- ใช้ **const arrow functions** สำหรับ components และ handlers
|
||||
- Event handlers ให้ขึ้นต้นด้วย `handle...` (เช่น `handleClick`, `handleSubmit`)
|
||||
- รวมแอตทริบิวต์สำหรับการเข้าถึง (accessibility) ด้วย:
|
||||
`tabIndex="0"`, `aria-label`, `onKeyDown`, ฯลฯ
|
||||
- ตรวจสอบให้แน่ใจว่าโค้ดทั้งหมด **สมบูรณ์**, **ผ่านการทดสอบ**, และ **ไม่ซ้ำซ้อน (DRY)**
|
||||
- ต้อง import โมดูลที่จำเป็นต้องใช้อย่างชัดเจนเสมอ
|
||||
|
||||
### UI/UX ด้วย React
|
||||
|
||||
- ใช้ **semantic HTML**
|
||||
- ใช้คลาสของ **Tailwind** ที่รองรับ responsive (`sm:`, `md:`, `lg:`)
|
||||
- รักษาลำดับชั้นของการมองเห็น (visual hierarchy) ด้วยการใช้ typography และ spacing
|
||||
- ใช้ **Shadcn** components (Button, Input, Card, ฯลฯ) เพื่อ UI ที่สอดคล้องกัน
|
||||
- ทำให้ components มีขนาดเล็กและมุ่งเน้นการทำงานเฉพาะอย่าง
|
||||
- ใช้ utility classes สำหรับการจัดสไตล์อย่างรวดเร็ว (spacing, colors, text, ฯลฯ)
|
||||
- ตรวจสอบให้แน่ใจว่าสอดคล้องกับ **ARIA** และใช้ semantic markup
|
||||
- ใช้ **semantic HTML**
|
||||
- ใช้คลาสของ **Tailwind** ที่รองรับ responsive (`sm:`, `md:`, `lg:`)
|
||||
- รักษาลำดับชั้นของการมองเห็น (visual hierarchy) ด้วยการใช้ typography และ spacing
|
||||
- ใช้ **Shadcn** components (Button, Input, Card, ฯลฯ) เพื่อ UI ที่สอดคล้องกัน
|
||||
- ทำให้ components มีขนาดเล็กและมุ่งเน้นการทำงานเฉพาะอย่าง
|
||||
- ใช้ utility classes สำหรับการจัดสไตล์อย่างรวดเร็ว (spacing, colors, text, ฯลฯ)
|
||||
- ตรวจสอบให้แน่ใจว่าสอดคล้องกับ **ARIA** และใช้ semantic markup
|
||||
|
||||
### การตรวจสอบฟอร์มและข้อผิดพลาด (Form Validation & Errors)
|
||||
|
||||
- ใช้ไลบรารีฝั่ง client เช่น `zod` และ `react-hook-form`
|
||||
- แสดงข้อผิดพลาดด้วย **alert components** หรือข้อความ inline
|
||||
- ต้องมี labels, placeholders, และข้อความ feedback
|
||||
- ใช้ไลบรารีฝั่ง client เช่น `zod` และ `react-hook-form`
|
||||
- แสดงข้อผิดพลาดด้วย **alert components** หรือข้อความ inline
|
||||
- ต้องมี labels, placeholders, และข้อความ feedback
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
# 🔗 แนวทางการบูรณาการ Full Stack (Full Stack Integration Guidelines)
|
||||
|
||||
| Aspect (แง่มุม) | Backend (NestJS) | Frontend (NextJS) | UI Layer (Tailwind/Shadcn) |
|
||||
|:--|:--|:--|:--|
|
||||
| API | REST / GraphQL Controllers | API hooks ผ่าน fetch/axios/SWR | Components ที่รับข้อมูล |
|
||||
| Validation (การตรวจสอบ) | `class-validator` DTOs | `zod` / `react-hook-form` | สถานะของฟอร์ม/input ใน Shadcn |
|
||||
| Auth (การยืนยันตัวตน) | Guards, JWT | NextAuth / cookies | สถานะ UI ของ Auth (loading, signed in) |
|
||||
| Errors (ข้อผิดพลาด) | Global filters | Toasts / modals | Alerts / ข้อความ feedback |
|
||||
| Testing (การทดสอบ) | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles (สไตล์) | Scoped modules (ถ้าจำเป็น) | Tailwind / Shadcn | Tailwind utilities |
|
||||
| Accessibility (การเข้าถึง) | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
| Aspect (แง่มุม) | Backend (NestJS) | Frontend (NextJS) | UI Layer (Tailwind/Shadcn) |
|
||||
| :------------------------- | :------------------------- | :----------------------------- | :------------------------------------- |
|
||||
| API | REST / GraphQL Controllers | API hooks ผ่าน fetch/axios/SWR | Components ที่รับข้อมูล |
|
||||
| Validation (การตรวจสอบ) | `class-validator` DTOs | `zod` / `react-hook-form` | สถานะของฟอร์ม/input ใน Shadcn |
|
||||
| Auth (การยืนยันตัวตน) | Guards, JWT | NextAuth / cookies | สถานะ UI ของ Auth (loading, signed in) |
|
||||
| Errors (ข้อผิดพลาด) | Global filters | Toasts / modals | Alerts / ข้อความ feedback |
|
||||
| Testing (การทดสอบ) | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles (สไตล์) | Scoped modules (ถ้าจำเป็น) | Tailwind / Shadcn | Tailwind utilities |
|
||||
| Accessibility (การเข้าถึง) | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
# 🗂️ ข้อตกลงเฉพาะสำหรับ DMS (LCBP3-DMS)
|
||||
|
||||
@@ -270,15 +270,15 @@ src/
|
||||
|
||||
### ข้อตกลงการตั้งชื่อ (Naming Convention)
|
||||
|
||||
| Entity (สิ่งที่ตั้งชื่อ) | Example (ตัวอย่างจาก SQL) |
|
||||
|:--|:--|
|
||||
| Table | `correspondences`, `rfa_revisions`, `contract_parties` |
|
||||
| Column | `correspondence_id`, `created_by`, `is_current` |
|
||||
| DTO | `CreateRfaDto`, `UpdateCorrespondenceDto` |
|
||||
| Controller | `rfas.controller.ts` |
|
||||
| Service | `correspondences.service.ts` |
|
||||
| Entity (สิ่งที่ตั้งชื่อ) | Example (ตัวอย่างจาก SQL) |
|
||||
| :----------------------- | :----------------------------------------------------- |
|
||||
| Table | `correspondences`, `rfa_revisions`, `contract_parties` |
|
||||
| Column | `correspondence_id`, `created_by`, `is_current` |
|
||||
| DTO | `CreateRfaDto`, `UpdateCorrespondenceDto` |
|
||||
| Controller | `rfas.controller.ts` |
|
||||
| Service | `correspondences.service.ts` |
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🧩 RBAC และการควบคุมสิทธิ์ (RBAC & Permission Control)
|
||||
|
||||
@@ -294,40 +294,40 @@ updateRFA(@Param('id') id: string) {
|
||||
|
||||
### Roles (บทบาท)
|
||||
|
||||
- **Superadmin**: ไม่มีข้อจำกัดใดๆ
|
||||
- **Admin**: มีสิทธิ์เต็มที่ในองค์กร
|
||||
- **Document Control**: เพิ่ม/แก้ไข/ลบ เอกสารในองค์กร
|
||||
- **Editor**: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนด
|
||||
- **Viewer**: สามารถดู เอกสาร
|
||||
- **Superadmin**: ไม่มีข้อจำกัดใดๆ
|
||||
- **Admin**: มีสิทธิ์เต็มที่ในองค์กร
|
||||
- **Document Control**: เพิ่ม/แก้ไข/ลบ เอกสารในองค์กร
|
||||
- **Editor**: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนด
|
||||
- **Viewer**: สามารถดู เอกสาร
|
||||
|
||||
### ตัวอย่าง Permissions (จากตาราง `permissions`)
|
||||
|
||||
- `rfas.view`, `rfas.create`, `rfas.respond`, `rfas.delete`
|
||||
- `drawings.view`, `drawings.upload`, `drawings.delete`
|
||||
- `corr.view`, `corr.manage`
|
||||
- `transmittals.manage`
|
||||
- `cirs.manage`
|
||||
- `project_parties.manage`
|
||||
- `rfas.view`, `rfas.create`, `rfas.respond`, `rfas.delete`
|
||||
- `drawings.view`, `drawings.upload`, `drawings.delete`
|
||||
- `corr.view`, `corr.manage`
|
||||
- `transmittals.manage`
|
||||
- `cirs.manage`
|
||||
- `project_parties.manage`
|
||||
|
||||
การจับคู่ระหว่าง roles และ permissions **เริ่มต้น** จะถูก seed ผ่านสคริปต์ (ดังที่เห็นในไฟล์ SQL) **อย่างไรก็ตาม `AuthModule`/`UserModule` ต้องมี API สำหรับ Admin เพื่อสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลัง**
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🧾 มาตรฐาน AuditLog (AuditLog Standard)
|
||||
|
||||
บันทึกการดำเนินการ CRUD และการจับคู่ทั้งหมดลงในตาราง `audit_logs`
|
||||
|
||||
| Field (ฟิลด์) | Type (จาก SQL) | Description (คำอธิบาย) |
|
||||
|:--|:--|:--|
|
||||
| `audit_id` | `BIGINT` | Primary Key |
|
||||
| `user_id` | `INT` | ผู้ใช้ที่ดำเนินการ (FK -\> users) |
|
||||
| `action` | `VARCHAR(100)` | `rfa.create`, `correspondence.update`, `login.success` |
|
||||
| `entity_type`| `VARCHAR(50)` | ชื่อตาราง/โมดูล เช่น 'rfa', 'correspondence' |
|
||||
| `entity_id` | `VARCHAR(50)` | Primary ID ของระเบียนที่ได้รับผลกระทบ |
|
||||
| `details_json`| `JSON` | ข้อมูลบริบท (เช่น ฟิลด์ที่มีการเปลี่ยนแปลง) |
|
||||
| `ip_address` | `VARCHAR(45)` | IP address ของผู้ดำเนินการ |
|
||||
| `user_agent` | `VARCHAR(255)`| User Agent ของผู้ดำเนินการ |
|
||||
| `created_at` | `TIMESTAMP` | Timestamp (UTC) |
|
||||
| Field (ฟิลด์) | Type (จาก SQL) | Description (คำอธิบาย) |
|
||||
| :------------- | :------------- | :----------------------------------------------------- |
|
||||
| `audit_id` | `BIGINT` | Primary Key |
|
||||
| `user_id` | `INT` | ผู้ใช้ที่ดำเนินการ (FK -\> users) |
|
||||
| `action` | `VARCHAR(100)` | `rfa.create`, `correspondence.update`, `login.success` |
|
||||
| `entity_type` | `VARCHAR(50)` | ชื่อตาราง/โมดูล เช่น 'rfa', 'correspondence' |
|
||||
| `entity_id` | `VARCHAR(50)` | Primary ID ของระเบียนที่ได้รับผลกระทบ |
|
||||
| `details_json` | `JSON` | ข้อมูลบริบท (เช่น ฟิลด์ที่มีการเปลี่ยนแปลง) |
|
||||
| `ip_address` | `VARCHAR(45)` | IP address ของผู้ดำเนินการ |
|
||||
| `user_agent` | `VARCHAR(255)` | User Agent ของผู้ดำเนินการ |
|
||||
| `created_at` | `TIMESTAMP` | Timestamp (UTC) |
|
||||
|
||||
ตัวอย่างการใช้งาน:
|
||||
|
||||
@@ -342,24 +342,24 @@ await this.auditLogService.log({
|
||||
});
|
||||
```
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 📂 การจัดการไฟล์ (File Handling) (ปรับปรุงใหม่)
|
||||
|
||||
### มาตรฐานการอัปโหลดไฟล์ (File Upload Standard)
|
||||
|
||||
- **ตรรกะใหม่:** การอัปโหลดไฟล์ทั้งหมดจะถูกจัดการโดย `FileStorageService` และบันทึกข้อมูลไฟล์ลงในตาราง `attachments` (ตารางกลาง)
|
||||
- ไฟล์จะถูกเชื่อมโยงไปยัง Entity ที่ถูกต้องผ่าน **ตารางเชื่อม (Junction Tables)** เท่านั้น:
|
||||
- `correspondence_attachments` (เชื่อม Correspondence กับ Attachments)
|
||||
- `circulation_attachments` (เชื่อม Circulation กับ Attachments)
|
||||
- `shop_drawing_revision_attachments` (เชื่อม Drawing Revision กับ Attachments)
|
||||
- **(สำคัญ)** คอลัมน์ `file_path` ถูกลบออกจาก `shop_drawing_revisions` แล้ว ต้องใช้ระบบตารางเชื่อมใหม่นี้เท่านั้น
|
||||
- เส้นทางจัดเก็บไฟล์ (Upload path): อ้างอิงจาก Requirement 2.1 คือ `/share/dms-data` โดย `FileStorageService` จะสร้างโฟลเดอร์ย่อยแบบรวมศูนย์ (เช่น `/share/dms-data/uploads/{YYYY}/{MM}/[stored_filename]`)
|
||||
- **(หมายเหตุ)**: โครงสร้างนี้ *แทนที่* โครงสร้างแบบแยกโมดูลที่ระบุใน Requirement 3.9 เนื่องจากการออกแบบใหม่ได้รวมศูนย์ไฟล์ไว้ที่ตาราง `attachments` กลางแล้ว
|
||||
- ประเภทไฟล์ที่อนุญาต: `pdf, dwg, docx, xlsx, zip`
|
||||
- ขนาดสูงสุด: **50 MB**
|
||||
- จัดเก็บนอก webroot
|
||||
- ให้บริการไฟล์ผ่าน endpoint ที่ปลอดภัย `/files/:attachment_id/download`
|
||||
- **ตรรกะใหม่:** การอัปโหลดไฟล์ทั้งหมดจะถูกจัดการโดย `FileStorageService` และบันทึกข้อมูลไฟล์ลงในตาราง `attachments` (ตารางกลาง)
|
||||
- ไฟล์จะถูกเชื่อมโยงไปยัง Entity ที่ถูกต้องผ่าน **ตารางเชื่อม (Junction Tables)** เท่านั้น:
|
||||
- `correspondence_attachments` (เชื่อม Correspondence กับ Attachments)
|
||||
- `circulation_attachments` (เชื่อม Circulation กับ Attachments)
|
||||
- `shop_drawing_revision_attachments` (เชื่อม Drawing Revision กับ Attachments)
|
||||
- **(สำคัญ)** คอลัมน์ `file_path` ถูกลบออกจาก `shop_drawing_revisions` แล้ว ต้องใช้ระบบตารางเชื่อมใหม่นี้เท่านั้น
|
||||
- เส้นทางจัดเก็บไฟล์ (Upload path): อ้างอิงจาก Requirement 2.1 คือ `/share/dms-data` โดย `FileStorageService` จะสร้างโฟลเดอร์ย่อยแบบรวมศูนย์ (เช่น `/share/dms-data/uploads/{YYYY}/{MM}/[stored_filename]`)
|
||||
- **(หมายเหตุ)**: โครงสร้างนี้ _แทนที่_ โครงสร้างแบบแยกโมดูลที่ระบุใน Requirement 3.9 เนื่องจากการออกแบบใหม่ได้รวมศูนย์ไฟล์ไว้ที่ตาราง `attachments` กลางแล้ว
|
||||
- ประเภทไฟล์ที่อนุญาต: `pdf, dwg, docx, xlsx, zip`
|
||||
- ขนาดสูงสุด: **50 MB**
|
||||
- จัดเก็บนอก webroot
|
||||
- ให้บริการไฟล์ผ่าน endpoint ที่ปลอดภัย `/files/:attachment_id/download`
|
||||
|
||||
### การควบคุมการเข้าถึง (Access Control)
|
||||
|
||||
@@ -369,7 +369,7 @@ await this.auditLogService.log({
|
||||
2. ตรวจสอบว่า `attachment_id` นี้ เชื่อมโยงกับ Entity ใด (เช่น `correspondence`, `circulation`, `shop_drawing_revision`) ผ่านตารางเชื่อม
|
||||
3. ตรวจสอบว่าผู้ใช้มีสิทธิ์ (permission) ในการดู Entity ต้นทางนั้นๆ หรือไม่
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 📊 การรายงานและการส่งออก (Reporting & Exports)
|
||||
|
||||
@@ -377,80 +377,78 @@ await this.auditLogService.log({
|
||||
|
||||
การรายงานควรสร้างขึ้นจาก Views ที่กำหนดไว้ล่วงหน้าในฐานข้อมูลเป็นหลัก:
|
||||
|
||||
- `v_current_correspondences`: สำหรับ revision ปัจจุบันทั้งหมดของเอกสารที่ไม่ใช่ RFA
|
||||
- `v_current_rfas`: สำหรับ revision ปัจจุบันทั้งหมดของ RFA และข้อมูล master
|
||||
- `v_contract_parties_all`: สำหรับการตรวจสอบความสัมพันธ์ของ project/contract/organization
|
||||
- `v_current_correspondences`: สำหรับ revision ปัจจุบันทั้งหมดของเอกสารที่ไม่ใช่ RFA
|
||||
- `v_current_rfas`: สำหรับ revision ปัจจุบันทั้งหมดของ RFA และข้อมูล master
|
||||
- `v_contract_parties_all`: สำหรับการตรวจสอบความสัมพันธ์ของ project/contract/organization
|
||||
|
||||
Views เหล่านี้ทำหน้าที่เป็นแหล่งข้อมูลหลักสำหรับการรายงานฝั่งเซิร์ฟเวอร์และการส่งออกข้อมูล
|
||||
|
||||
### กฎการส่งออก (Export Rules)
|
||||
|
||||
- Export formats: CSV, Excel, PDF.
|
||||
- จัดเตรียมมุมมองสำหรับพิมพ์ (Print view).
|
||||
- รวมลิงก์ไปยังต้นทาง (เช่น `/rfas/:id`).
|
||||
- Export formats: CSV, Excel, PDF.
|
||||
- จัดเตรียมมุมมองสำหรับพิมพ์ (Print view).
|
||||
- รวมลิงก์ไปยังต้นทาง (เช่น `/rfas/:id`).
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🧮 ฟรอนต์เอนด์: รูปแบบ DataTable และฟอร์ม (Frontend: DataTable & Form Patterns)
|
||||
|
||||
### DataTable (Server‑Side)
|
||||
|
||||
- Endpoint: `/api/{module}?page=1&pageSize=20&sort=...&filter=...`
|
||||
- ต้องรองรับ: การแบ่งหน้า (pagination), การเรียงลำดับ (sorting), การค้นหา (search), การกรอง (filters)
|
||||
- แสดง revision ล่าสุดแบบ inline เสมอ (สำหรับ RFA/Drawing)
|
||||
- Endpoint: `/api/{module}?page=1&pageSize=20&sort=...&filter=...`
|
||||
- ต้องรองรับ: การแบ่งหน้า (pagination), การเรียงลำดับ (sorting), การค้นหา (search), การกรอง (filters)
|
||||
- แสดง revision ล่าสุดแบบ inline เสมอ (สำหรับ RFA/Drawing)
|
||||
|
||||
### มาตรฐานฟอร์ม (Form Standards)
|
||||
|
||||
- ต้องมีการใช้งาน Dropdowns แบบขึ้นต่อกัน (Dependent dropdowns) (ตามที่สคีมารองรับ):
|
||||
- Project → Contract Drawing Volumes
|
||||
- Contract Drawing Category → Sub-Category
|
||||
- RFA (ประเภท Shop Drawing) → Shop Drawing Revisions ที่เชื่อมโยงได้
|
||||
- การอัปโหลดไฟล์: ต้องมี preview + validation (ผ่านตรรกะของ `attachments` และตารางเชื่อมใหม่)
|
||||
- ส่ง (Submit) ผ่าน API พร้อม feedback แบบ toast
|
||||
- ต้องมีการใช้งาน Dropdowns แบบขึ้นต่อกัน (Dependent dropdowns) (ตามที่สคีมารองรับ):
|
||||
- Project → Contract Drawing Volumes
|
||||
- Contract Drawing Category → Sub-Category
|
||||
- RFA (ประเภท Shop Drawing) → Shop Drawing Revisions ที่เชื่อมโยงได้
|
||||
- การอัปโหลดไฟล์: ต้องมี preview + validation (ผ่านตรรกะของ `attachments` และตารางเชื่อมใหม่)
|
||||
- ส่ง (Submit) ผ่าน API พร้อม feedback แบบ toast
|
||||
|
||||
### ข้อกำหนด Component เฉพาะ (Specific UI Requirements)
|
||||
|
||||
- **Dashboard - My Tasks:** ต้องพัฒนา Component ตาราง "งานของฉัน" (My Tasks) ซึ่งดึงข้อมูลงานที่ผู้ใช้ล็อกอินอยู่ต้องรับผิดชอบ (Main/Action) จากโมดูล `Circulations`
|
||||
- **Workflow Visualization:** ต้องพัฒนา Component สำหรับแสดงผล Workflow (โดยเฉพาะ RFA) ที่แสดงขั้นตอนทั้งหมดเป็นลำดับ โดยขั้นตอนปัจจุบัน (active) เท่านั้นที่ดำเนินการได้ และขั้นตอนอื่นเป็น `disabled` ต้องมีตรรกะสำหรับ Admin ในการ override หรือย้อนกลับขั้นตอนได้
|
||||
- **Dashboard - My Tasks:** ต้องพัฒนา Component ตาราง "งานของฉัน" (My Tasks) ซึ่งดึงข้อมูลงานที่ผู้ใช้ล็อกอินอยู่ต้องรับผิดชอบ (Main/Action) จากโมดูล `Circulations`
|
||||
- **Workflow Visualization:** ต้องพัฒนา Component สำหรับแสดงผล Workflow (โดยเฉพาะ RFA) ที่แสดงขั้นตอนทั้งหมดเป็นลำดับ โดยขั้นตอนปัจจุบัน (active) เท่านั้นที่ดำเนินการได้ และขั้นตอนอื่นเป็น `disabled` ต้องมีตรรกะสำหรับ Admin ในการ override หรือย้อนกลับขั้นตอนได้
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## 🧭 แดชบอร์ดและฟีดกิจกรรม (Dashboard & Activity Feed)
|
||||
|
||||
### การ์ดบนแดชบอร์ด (Dashboard Cards)
|
||||
|
||||
- แสดง Correspondences, RFAs, Circulations ล่าสุด
|
||||
- รวมสรุป KPI (เช่น "RFAs ที่รอการอนุมัติ")
|
||||
- รวมลิงก์ด่วนไปยังโมดูลต่างๆ
|
||||
- แสดง Correspondences, RFAs, Circulations ล่าสุด
|
||||
- รวมสรุป KPI (เช่น "RFAs ที่รอการอนุมัติ")
|
||||
- รวมลิงก์ด่วนไปยังโมดูลต่างๆ
|
||||
|
||||
### ฟีดกิจกรรม (Activity Feed)
|
||||
|
||||
- แสดงรายการ `audit_logs` ล่าสุด (10 รายการ) ที่เกี่ยวข้องกับผู้ใช้
|
||||
- แสดงรายการ `audit_logs` ล่าสุด (10 รายการ) ที่เกี่ยวข้องกับผู้ใช้
|
||||
|
||||
<!-- end list -->
|
||||
|
||||
```ts
|
||||
// ตัวอย่าง API response
|
||||
[
|
||||
{ user: 'editor01', action: 'Updated RFA (LCBP3-RFA-001)', time: '2025-11-04T09:30Z' }
|
||||
]
|
||||
[{ user: 'editor01', action: 'Updated RFA (LCBP3-RFA-001)', time: '2025-11-04T09:30Z' }];
|
||||
```
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
## ✅ มาตรฐานที่นำไปใช้แล้ว (จาก SQL v1.1.0) (Implemented Standards (from SQL v1.1.0))
|
||||
|
||||
ส่วนนี้ยืนยันว่าแนวทางปฏิบัติที่ดีที่สุดต่อไปนี้เป็นส่วนหนึ่งของการออกแบบฐานข้อมูลอยู่แล้ว และควรถูกนำไปใช้ประโยชน์ ไม่ใช่สร้างขึ้นใหม่
|
||||
|
||||
- ✅ **Soft Delete:** นำไปใช้แล้วผ่านคอลัมน์ `deleted_at` ในตารางสำคัญ (เช่น `correspondences`, `rfas`, `project_parties`) ตรรกะการดึงข้อมูลต้องกรอง `deleted_at IS NULL`
|
||||
- ✅ **Database Indexes:** สคีมาได้มีการทำ index ไว้อย่างหนักหน่วงบน foreign keys และคอลัมน์ที่ใช้ค้นหาบ่อย (เช่น `idx_rr_rfa`, `idx_cor_project`, `idx_cr_is_current`) เพื่อประสิทธิภาพ
|
||||
- ✅ **โครงสร้าง RBAC:** มีระบบ `users`, `roles`, `permissions`, `user_roles`, และ `user_project_roles` ที่ครอบคลุมอยู่แล้ว
|
||||
- ✅ **Data Seeding:** ข้อมูล Master (roles, permissions, organization\_roles, initial users, project parties) ถูกรวมอยู่ในสคริปต์สคีมาแล้ว
|
||||
- ✅ **Soft Delete:** นำไปใช้แล้วผ่านคอลัมน์ `deleted_at` ในตารางสำคัญ (เช่น `correspondences`, `rfas`, `project_parties`) ตรรกะการดึงข้อมูลต้องกรอง `deleted_at IS NULL`
|
||||
- ✅ **Database Indexes:** สคีมาได้มีการทำ index ไว้อย่างหนักหน่วงบน foreign keys และคอลัมน์ที่ใช้ค้นหาบ่อย (เช่น `idx_rr_rfa`, `idx_cor_project`, `idx_cr_is_current`) เพื่อประสิทธิภาพ
|
||||
- ✅ **โครงสร้าง RBAC:** มีระบบ `users`, `roles`, `permissions`, `user_roles`, และ `user_project_roles` ที่ครอบคลุมอยู่แล้ว
|
||||
- ✅ **Data Seeding:** ข้อมูล Master (roles, permissions, organization_roles, initial users, project parties) ถูกรวมอยู่ในสคริปต์สคีมาแล้ว
|
||||
|
||||
## 🧩 การปรับปรุงที่แนะนำ (สำหรับอนาคต) (Recommended Enhancements (Future))
|
||||
|
||||
- ✅ **(V2)** นำ Fulltext search หรือ Elasticsearch มาใช้กับฟิลด์เช่น `correspondence_revisions.title` หรือ `details`
|
||||
- ✅ สร้าง Background job (โดยใช้ **n8n** เพื่อเชื่อมต่อกับ **Line** และ/หรือใช้สำหรับการแจ้งเตือน RFA ที่ใกล้ถึงกำหนด `due_date`)
|
||||
- ✅ เพิ่ม job ล้างข้อมูลเป็นระยะสำหรับ `attachments` ที่ไม่ถูกเชื่อมโยงกับ Entity ใดๆ เลย (ไฟล์กำพร้า)
|
||||
- ✅ **(V2)** นำ Fulltext search หรือ Elasticsearch มาใช้กับฟิลด์เช่น `correspondence_revisions.title` หรือ `details`
|
||||
- ✅ สร้าง Background job (โดยใช้ **n8n** เพื่อเชื่อมต่อกับ **Line** และ/หรือใช้สำหรับการแจ้งเตือน RFA ที่ใกล้ถึงกำหนด `due_date`)
|
||||
- ✅ เพิ่ม job ล้างข้อมูลเป็นระยะสำหรับ `attachments` ที่ไม่ถูกเชื่อมโยงกับ Entity ใดๆ เลย (ไฟล์กำพร้า)
|
||||
|
||||
-----
|
||||
---
|
||||
|
||||
@@ -4,198 +4,188 @@
|
||||
|
||||
สร้างเว็บแอปพลิเคชั่นสำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System) ที่สามารถจัดการและควบคุม การสื่อสารด้วยเอกสารที่ซับซ้อน อย่างมีประสิทธิภาพ
|
||||
|
||||
* มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
* ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
* เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
- มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
- ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
- เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
|
||||
## 🛠️ 2. สถาปัตยกรรมและเทคโนโลยี (System Architecture & Technology Stack)
|
||||
|
||||
ใช้สถาปัตยกรรมแบบ Headless/API-First ที่ทันสมัย ทำงานทั้งหมดบน QNAP Server ผ่าน Container Station เพื่อความสะดวกในการจัดการและบำรุงรักษา, Domain: np-dms.work, มี fix ip, รัน docker command ใน application ของ Container Station ได้โดยตรง, ประกอบด้วย
|
||||
|
||||
* 2.1. Infrastructure & Environment:
|
||||
- Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
- Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
|
||||
- Development Environment: VS Code on Windows 11
|
||||
- Domain: np-dms.work, www.np-dms.work
|
||||
- ip: 159.192.126.103
|
||||
- Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
- Data Storage: /share/dms-data บน QNAP
|
||||
- ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
* 2.2. Code Hosting:
|
||||
- Application name: git
|
||||
- Service: Gitea (Self-hosted on QNAP)
|
||||
- Service name: gitea
|
||||
- Domain: git.np-dms.work
|
||||
- หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
|
||||
* 2.3. Backend / Data Platform:
|
||||
- Application name: lcbp3-backend
|
||||
- Service: NestJS
|
||||
- Service name: backend
|
||||
- Domain: backend.np-dms.work
|
||||
- Framework: NestJS (Node.js, TypeScript, ESM)
|
||||
- หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
|
||||
* 2.4. Database:
|
||||
- Application name: lcbp3-db
|
||||
- Service: mariadb:10.11
|
||||
- Service name: mariadb
|
||||
- Domain: db.np-dms.work
|
||||
- หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
|
||||
- Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
|
||||
* 2.5. Database management:
|
||||
- Application name: lcbp3-db
|
||||
- Service: phpmyadmin:5-apache
|
||||
- Service name: pma
|
||||
- Domain: pma.np-dms.work
|
||||
- หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
|
||||
* 2.6. Frontend:
|
||||
- Application name: lcbp3-frontend
|
||||
- Service: next.js
|
||||
- Service name: frontend
|
||||
- Domain: lcbp3.np-dms.work
|
||||
- Framework: Next.js (App Router, React, TypeScript, ESM)
|
||||
- Styling: Tailwind CSS + PostCSS
|
||||
- Component Library: shadcn/ui
|
||||
- หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
|
||||
* 2.7. Workflow automation:
|
||||
- Application name: lcbp3-n8n
|
||||
- Service: n8nio/n8n:latest
|
||||
- Service name: n8n
|
||||
- Domain: n8n.np-dms.work
|
||||
- หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
|
||||
* 2.8. Reverse Proxy:
|
||||
- Application name: lcbp3-npm
|
||||
- Service: Nginx Proxy Manager (nginx-proxy-manage: latest)
|
||||
- Service name: npm
|
||||
- Domain: npm.np-dms.work
|
||||
- หน้าที่: เป็นด่านหน้าในการรับ-ส่งข้อมูล จัดการโดเมนทั้งหมด, ทำหน้าที่เป็น Proxy ชี้ไปยัง Service ที่ถูกต้อง, และจัดการ SSL Certificate (HTTPS) ให้อัตโนมัติ
|
||||
- 2.1. Infrastructure & Environment:
|
||||
- Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
- Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
|
||||
- Development Environment: VS Code on Windows 11
|
||||
- Domain: np-dms.work, www.np-dms.work
|
||||
- ip: 159.192.126.103
|
||||
- Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
- Data Storage: /share/dms-data บน QNAP
|
||||
- ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
- 2.2. Code Hosting:
|
||||
- Application name: git
|
||||
- Service: Gitea (Self-hosted on QNAP)
|
||||
- Service name: gitea
|
||||
- Domain: git.np-dms.work
|
||||
- หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
|
||||
- 2.3. Backend / Data Platform:
|
||||
- Application name: lcbp3-backend
|
||||
- Service: NestJS
|
||||
- Service name: backend
|
||||
- Domain: backend.np-dms.work
|
||||
- Framework: NestJS (Node.js, TypeScript, ESM)
|
||||
- หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
|
||||
- 2.4. Database:
|
||||
- Application name: lcbp3-db
|
||||
- Service: mariadb:10.11
|
||||
- Service name: mariadb
|
||||
- Domain: db.np-dms.work
|
||||
- หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
|
||||
- Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
|
||||
- 2.5. Database management:
|
||||
- Application name: lcbp3-db
|
||||
- Service: phpmyadmin:5-apache
|
||||
- Service name: pma
|
||||
- Domain: pma.np-dms.work
|
||||
- หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
|
||||
- 2.6. Frontend:
|
||||
- Application name: lcbp3-frontend
|
||||
- Service: next.js
|
||||
- Service name: frontend
|
||||
- Domain: lcbp3.np-dms.work
|
||||
- Framework: Next.js (App Router, React, TypeScript, ESM)
|
||||
- Styling: Tailwind CSS + PostCSS
|
||||
- Component Library: shadcn/ui
|
||||
- หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
|
||||
- 2.7. Workflow automation:
|
||||
- Application name: lcbp3-n8n
|
||||
- Service: n8nio/n8n:latest
|
||||
- Service name: n8n
|
||||
- Domain: n8n.np-dms.work
|
||||
- หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
|
||||
- 2.8. Reverse Proxy:
|
||||
- Application name: lcbp3-npm
|
||||
- Service: Nginx Proxy Manager (nginx-proxy-manage: latest)
|
||||
- Service name: npm
|
||||
- Domain: npm.np-dms.work
|
||||
- หน้าที่: เป็นด่านหน้าในการรับ-ส่งข้อมูล จัดการโดเมนทั้งหมด, ทำหน้าที่เป็น Proxy ชี้ไปยัง Service ที่ถูกต้อง, และจัดการ SSL Certificate (HTTPS) ให้อัตโนมัติ
|
||||
|
||||
## 📦 3. ข้อกำหนดด้านฟังก์ชันการทำงาน (Functional Requirements)
|
||||
|
||||
* 3.1. การจัดการโครงสร้างโครงการและองค์กร
|
||||
- 3.1. การจัดการโครงสร้างโครงการและองค์กร
|
||||
- 3.1.1. โครงการ (Projects): ระบบต้องสามารถจัดการเอกสารภายในหลายโครงการได้ (ปัจจุบันมี 4 โครงการ และจะเพิ่มขึ้นในอนาคต)
|
||||
- 3.1.2. สัญญา (Contracts): ระบบต้องสามารถจัดการเอกสารภายในแต่ละสัญญาได้ ในแต่ละโครงการ มีได้หลายสัญญา หรืออย่างน้อย 1 สัญญา
|
||||
- 3.1.3. องค์กร (Organizations):
|
||||
- มีหลายองค์กรในโครงการ องค์กรณ์ที่เป็น Owner, Designer และ Consultant สามารถอยู่ในหลายโครงการและหลายสัญญาได้
|
||||
- Contractor จะถือ 1 สัญญา และอยู่ใน 1 โครงการเท่านั้น
|
||||
|
||||
- 3.1.1. โครงการ (Projects): ระบบต้องสามารถจัดการเอกสารภายในหลายโครงการได้ (ปัจจุบันมี 4 โครงการ และจะเพิ่มขึ้นในอนาคต)
|
||||
- 3.1.2. สัญญา (Contracts): ระบบต้องสามารถจัดการเอกสารภายในแต่ละสัญญาได้ ในแต่ละโครงการ มีได้หลายสัญญา หรืออย่างน้อย 1 สัญญา
|
||||
- 3.1.3. องค์กร (Organizations):
|
||||
- มีหลายองค์กรในโครงการ องค์กรณ์ที่เป็น Owner, Designer และ Consultant สามารถอยู่ในหลายโครงการและหลายสัญญาได้
|
||||
- Contractor จะถือ 1 สัญญา และอยู่ใน 1 โครงการเท่านั้น
|
||||
- 3.2. การจัดการเอกสารโต้ตอบ (Correspondence Management)
|
||||
- 3.2.1. วัตถุประสงค์: เอกสารโต้ตอบ (correspondences) ระหว่างองกรณื-องกรณ์ ภายใน โครงการ (Projects) และระหว่าง องค์กร-องค์กร ภายนอก โครงการ (Projects)
|
||||
- 3.2.2. ประเภทเอกสาร: ระบบต้องรองรับเอกสารรูปแบบ ไฟล์ PDF หลายประเภท (Types) เช่น จดหมาย (Letter), อีเมล์ (Email), Request for Information (RFI), และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
|
||||
- 3.2.3. การสร้างเอกสาร (Correspondence):
|
||||
- ผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารรอไว้ในสถานะ ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
|
||||
- เมื่อกด "Submitted" แล้ว การแก้ไข, ถอนเอกสารกลับไปสถานะ Draft, หรือยกเลิก (Cancel) จะต้องทำโดยผู้ใช้ระดับ Admin ขึ้นไป พร้อมระบุเหตุผล
|
||||
- 3.2.4. การอ้างอิงและจัดกลุ่ม:
|
||||
- เอกสารสามารถอ้างถึง (Reference) เอกสารฉบับก่อนหน้าได้หลายฉบับ
|
||||
- สามารถกำหนด Tag ได้หลาย Tag เพื่อจัดกลุ่มและใช้ในการค้นหาขั้นสูง
|
||||
- 3.2.5. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อเป็นผู้รับ ได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบขององกรณ์ที่เป็น ผู้รับ/ผู้ส่ง ทราบ เมื่อมีเอกสารใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
|
||||
* 3.2. การจัดการเอกสารโต้ตอบ (Correspondence Management)
|
||||
- 3.3. การจัดกาแบบคู่สัญญา (Contract Drawing)
|
||||
- 3.3.1. วัตถุประสงค์: แบบคู่สัญญา (Contract Drawing) ใช้เพื่ออ้างอิงและใช้ในการตรวจสอบ
|
||||
- 3.3.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.3.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.3.4. การอ้างอิงและจัดกลุ่ม: ใช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Contract Drawing
|
||||
|
||||
- 3.2.1. วัตถุประสงค์: เอกสารโต้ตอบ (correspondences) ระหว่างองกรณื-องกรณ์ ภายใน โครงการ (Projects) และระหว่าง องค์กร-องค์กร ภายนอก โครงการ (Projects)
|
||||
- 3.2.2. ประเภทเอกสาร: ระบบต้องรองรับเอกสารรูปแบบ ไฟล์ PDF หลายประเภท (Types) เช่น จดหมาย (Letter), อีเมล์ (Email), Request for Information (RFI), และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
|
||||
- 3.2.3. การสร้างเอกสาร (Correspondence):
|
||||
- ผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารรอไว้ในสถานะ ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
|
||||
- เมื่อกด "Submitted" แล้ว การแก้ไข, ถอนเอกสารกลับไปสถานะ Draft, หรือยกเลิก (Cancel) จะต้องทำโดยผู้ใช้ระดับ Admin ขึ้นไป พร้อมระบุเหตุผล
|
||||
- 3.2.4. การอ้างอิงและจัดกลุ่ม:
|
||||
- เอกสารสามารถอ้างถึง (Reference) เอกสารฉบับก่อนหน้าได้หลายฉบับ
|
||||
- สามารถกำหนด Tag ได้หลาย Tag เพื่อจัดกลุ่มและใช้ในการค้นหาขั้นสูง
|
||||
- 3.2.5. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อเป็นผู้รับ ได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบขององกรณ์ที่เป็น ผู้รับ/ผู้ส่ง ทราบ เมื่อมีเอกสารใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
- 3.4. การจัดกาแบบก่อสร้าง (Shop Drawing)
|
||||
- 3.4.1. วัตถุประสงค์: แบบก่อสร้าง (Shop Drawing) ใช้เในการตรวจสอบ โดยจัดส่งด้วย Request for Approval (RFA)
|
||||
- 3.4.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.4.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.4.4. การอ้างอิงและจัดกลุ่ม: ช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Shop Drawings
|
||||
|
||||
* 3.3. การจัดกาแบบคู่สัญญา (Contract Drawing)
|
||||
- 3.5. การจัดการเอกสารขออนุมัติ (Request for Approval & Workflow)
|
||||
- 3.5.1. วัตถุประสงค์: เอกสารขออนุมัติ (Request for Approval) ใช้ในการส่งเอกสารเพิอขออนุมัติ
|
||||
- 3.5.2. ประเภทเอกสาร: Request for Approval (RFA) เป็นชนิดหนึ่งของ Correspondence ที่มีลักษณะเฉพาะที่ต้องได้รับการอนุมัติ มีประเภทดังนี้:
|
||||
- Request for Drawing Approval (RFA_DWG)
|
||||
- Request for Document Approval (RFA_DOC)
|
||||
- Request for Method statement Approval (RFA_MES)
|
||||
- Request for Material Approval (RFA_MAT)
|
||||
- 3.5.2. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.5.4. การอ้างอิงและจัดกลุ่ม: การจัดการ Drawing (RFA_DWG):
|
||||
- เอกสาร RFA_DWG จะประกอบไปด้วย Shop Drawing (shop_drawings) หลายแผ่น ซึ่งแต่ละแผ่นมี Revision ของตัวเอง
|
||||
- Shop Drawing แต่ละ Revision สามารถอ้างอิงถึง Contract Drawing (Ccontract_drawings) หลายแผ่น หรือไม่อ้างถึงก็ได้
|
||||
- ระบบต้องมีส่วนสำหรับจัดการข้อมูล Master Data ของทั้ง Shop Drawing และ Contract Drawing แยกจากกัน
|
||||
- 3.6.5. Workflow การอนุมัติ: ต้องรองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น
|
||||
- ส่งจาก Originator -\> Organization 1 -\> Organization 2 -\> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Workflow ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
|
||||
- 3.6.6. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ทราบ เมื่อมี RFA ใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
|
||||
- 3.3.1. วัตถุประสงค์: แบบคู่สัญญา (Contract Drawing) ใช้เพื่ออ้างอิงและใช้ในการตรวจสอบ
|
||||
- 3.3.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.3.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.3.4. การอ้างอิงและจัดกลุ่ม: ใช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Contract Drawing
|
||||
- 3.6.การจัดการเอกสารนำส่ง (Transmittals)
|
||||
- 3.6.1. วัตถุประสงค์: เอกสารนำส่ง ใช้สำหรับ นำส่ง Request for Approval (RFAS) หลายฉบับ ไปยังองค์กรอื่น
|
||||
- 3.6.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.6.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.6.4. การอ้างอิงและจัดกลุ่ม: เอกสารนำส่ง เป็นส่วนหนึ่งใน Correspondence
|
||||
|
||||
* 3.4. การจัดกาแบบก่อสร้าง (Shop Drawing)
|
||||
- 3.7. ใบเวียนเอกสารภายใน (Internal Circulation Sheet)
|
||||
- 3.7.1. วัตถุประสงค์: การสื่อสาร เอกสาร (Correspondence) ทุกฉบับ จะมีใบเวียนเอกสารเพื่อควบคุมและมอบหมายงานภายในองค์กร (สามารถดูและแก้ไขได้เฉพาะคนในองค์กร)
|
||||
- 3.7.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.7.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ในองค์กรนั้น สามารถสร้างและแก้ไขได้
|
||||
- 3.7.4. การอ้างอิงและจัดกลุ่ม: การระบุผู้รับผิดชอบ:
|
||||
- ผู้รับผิดชอบหลัก (Main): มีได้หลายคน
|
||||
- ผู้ร่วมปฏิบัติงาน (Action): มีได้หลายคน
|
||||
- ผู้ที่ต้องรับทราบ (Information): มีได้หลายคน
|
||||
- 3.7.5. การติดตามงาน:
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบประเภท Main และ Action ได้
|
||||
- มีระบบแจ้งเตือนเมื่อมี Circulation ใหม่ และแจ้งเตือนล่วงหน้าก่อนถึงวันแล้วเสร็จ
|
||||
- สามารถปิด Circulation ได้เมื่อดำเนินการตอบกลับไปยังองค์กรผู้ส่ง (Originator) แล้ว หรือ รับทราบแล้ว (For Information)
|
||||
|
||||
- 3.4.1. วัตถุประสงค์: แบบก่อสร้าง (Shop Drawing) ใช้เในการตรวจสอบ โดยจัดส่งด้วย Request for Approval (RFA)
|
||||
- 3.4.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.4.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.4.4. การอ้างอิงและจัดกลุ่ม: ช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Shop Drawings
|
||||
- 3.8. ประวัติการแก้ไข (Revisions): ระบบจะเก็บประวัติการสร้างและแก้ไข เอกสารทั้งหมด
|
||||
|
||||
* 3.5. การจัดการเอกสารขออนุมัติ (Request for Approval & Workflow)
|
||||
|
||||
- 3.5.1. วัตถุประสงค์: เอกสารขออนุมัติ (Request for Approval) ใช้ในการส่งเอกสารเพิอขออนุมัติ
|
||||
- 3.5.2. ประเภทเอกสาร: Request for Approval (RFA) เป็นชนิดหนึ่งของ Correspondence ที่มีลักษณะเฉพาะที่ต้องได้รับการอนุมัติ มีประเภทดังนี้:
|
||||
- Request for Drawing Approval (RFA\_DWG)
|
||||
- Request for Document Approval (RFA\_DOC)
|
||||
- Request for Method statement Approval (RFA\_MES)
|
||||
- Request for Material Approval (RFA\_MAT)
|
||||
- 3.5.2. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.5.4. การอ้างอิงและจัดกลุ่ม: การจัดการ Drawing (RFA\_DWG):
|
||||
- เอกสาร RFA\_DWG จะประกอบไปด้วย Shop Drawing (shop\_drawings) หลายแผ่น ซึ่งแต่ละแผ่นมี Revision ของตัวเอง
|
||||
- Shop Drawing แต่ละ Revision สามารถอ้างอิงถึง Contract Drawing (Ccontract\_drawings) หลายแผ่น หรือไม่อ้างถึงก็ได้
|
||||
- ระบบต้องมีส่วนสำหรับจัดการข้อมูล Master Data ของทั้ง Shop Drawing และ Contract Drawing แยกจากกัน
|
||||
- 3.6.5. Workflow การอนุมัติ: ต้องรองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น
|
||||
- ส่งจาก Originator -\> Organization 1 -\> Organization 2 -\> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Workflow ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
|
||||
- 3.6.6. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ทราบ เมื่อมี RFA ใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
|
||||
* 3.6.การจัดการเอกสารนำส่ง (Transmittals)
|
||||
|
||||
- 3.6.1. วัตถุประสงค์: เอกสารนำส่ง ใช้สำหรับ นำส่ง Request for Approval (RFAS) หลายฉบับ ไปยังองค์กรอื่น
|
||||
- 3.6.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.6.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.6.4. การอ้างอิงและจัดกลุ่ม: เอกสารนำส่ง เป็นส่วนหนึ่งใน Correspondence
|
||||
|
||||
* 3.7. ใบเวียนเอกสารภายใน (Internal Circulation Sheet)
|
||||
|
||||
- 3.7.1. วัตถุประสงค์: การสื่อสาร เอกสาร (Correspondence) ทุกฉบับ จะมีใบเวียนเอกสารเพื่อควบคุมและมอบหมายงานภายในองค์กร (สามารถดูและแก้ไขได้เฉพาะคนในองค์กร)
|
||||
- 3.7.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.7.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ในองค์กรนั้น สามารถสร้างและแก้ไขได้
|
||||
- 3.7.4. การอ้างอิงและจัดกลุ่ม: การระบุผู้รับผิดชอบ:
|
||||
- ผู้รับผิดชอบหลัก (Main): มีได้หลายคน
|
||||
- ผู้ร่วมปฏิบัติงาน (Action): มีได้หลายคน
|
||||
- ผู้ที่ต้องรับทราบ (Information): มีได้หลายคน
|
||||
- 3.7.5. การติดตามงาน:
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบประเภท Main และ Action ได้
|
||||
- มีระบบแจ้งเตือนเมื่อมี Circulation ใหม่ และแจ้งเตือนล่วงหน้าก่อนถึงวันแล้วเสร็จ
|
||||
- สามารถปิด Circulation ได้เมื่อดำเนินการตอบกลับไปยังองค์กรผู้ส่ง (Originator) แล้ว หรือ รับทราบแล้ว (For Information)
|
||||
|
||||
* 3.8. ประวัติการแก้ไข (Revisions): ระบบจะเก็บประวัติการสร้างและแก้ไข เอกสารทั้งหมด
|
||||
|
||||
* **3.9. การจัดเก็บ: (ปรับปรุงตามสถาปัตยกรรมใหม่)**
|
||||
|
||||
- เอกสารและไฟล์แนบทั้งหมดจะถูกจัดเก็บในโฟลเดอร์บน Server (`/share/dms-data/`)
|
||||
- ข้อมูล Metadata ของไฟล์ (เช่น ชื่อไฟล์, ขนาด, path) จะถูกเก็บในตาราง `attachments` (ตารางกลาง)
|
||||
- ไฟล์จะถูกเชื่อมโยงกับเอกสารประเภทต่างๆ ผ่านตารางเชื่อม (Junction tables) เช่น `correspondence_attachments`, `circulation_attachments`, และ `shop_drawing_revision_attachments`
|
||||
- สถาปัตยกรรมแบบรวมศูนย์นี้ *แทนที่* แนวคิดเดิมที่จะแยกโฟลเดอร์ตามประเภทเอกสาร เพื่อรองรับการขยายระบบที่ดีกว่า
|
||||
- **3.9. การจัดเก็บ: (ปรับปรุงตามสถาปัตยกรรมใหม่)**
|
||||
- เอกสารและไฟล์แนบทั้งหมดจะถูกจัดเก็บในโฟลเดอร์บน Server (`/share/dms-data/`)
|
||||
- ข้อมูล Metadata ของไฟล์ (เช่น ชื่อไฟล์, ขนาด, path) จะถูกเก็บในตาราง `attachments` (ตารางกลาง)
|
||||
- ไฟล์จะถูกเชื่อมโยงกับเอกสารประเภทต่างๆ ผ่านตารางเชื่อม (Junction tables) เช่น `correspondence_attachments`, `circulation_attachments`, และ `shop_drawing_revision_attachments`
|
||||
- สถาปัตยกรรมแบบรวมศูนย์นี้ _แทนที่_ แนวคิดเดิมที่จะแยกโฟลเดอร์ตามประเภทเอกสาร เพื่อรองรับการขยายระบบที่ดีกว่า
|
||||
|
||||
## 🔐 4. ข้อกำหนดด้านสิทธิ์และการเข้าถึง (Access Control Requirements)
|
||||
|
||||
* 4.1. ภาพรวม: ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
|
||||
- 4.1. ภาพรวม: ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
|
||||
|
||||
* 4.2. ระดับของสิทธิ์:
|
||||
- 4.2. ระดับของสิทธิ์:
|
||||
- Global Roles: สิทธิ์ในภาพรวมของระบบ
|
||||
- Project-Specific Roles: สิทธิ์ที่ถูกกำหนดให้ผู้ใช้สำหรับโครงการนั้นๆ โดยเฉพาะ (เช่น เป็น Editor ในโครงการ A แต่เป็น Viewer ในโครงการ B)
|
||||
- Contract-Specific Roles: สิทธิ์ที่ถูกกำหนดให้โครงการสำหรับสัญญานั้นๆ (เช่น เป็น Admin ในสัญญา 1 จะเป็น Admin ใน โครงการ A และ ฺB ที่อยู่ในสัญญา 1)
|
||||
|
||||
- Global Roles: สิทธิ์ในภาพรวมของระบบ
|
||||
- Project-Specific Roles: สิทธิ์ที่ถูกกำหนดให้ผู้ใช้สำหรับโครงการนั้นๆ โดยเฉพาะ (เช่น เป็น Editor ในโครงการ A แต่เป็น Viewer ในโครงการ B)
|
||||
- Contract-Specific Roles: สิทธิ์ที่ถูกกำหนดให้โครงการสำหรับสัญญานั้นๆ (เช่น เป็น Admin ในสัญญา 1 จะเป็น Admin ใน โครงการ A และ ฺB ที่อยู่ในสัญญา 1)
|
||||
- 4.3. บทบาท (Roles) พื้นฐาน:
|
||||
- Superadmin: ไม่มีข้อจำกัดใดๆ สามารถจัดการได้ทุกอย่างข้ามองค์กร
|
||||
- Admin: มีสิทธิ์เต็มที่ แต่จำกัดเฉพาะในองค์กรที่ตัวเองสังกัด สามารถจัดการผู้ใช้ในองค์กรได้ สามารถสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลังผ่านหน้า Admin
|
||||
- Document Control สามารถ เพิ่ม/แก้ไข/ลบ เอกสาร เฉพาะในองค์กรที่ตัวเองสังกัด ไม่สามารถจัดการผู้ใช้ได้
|
||||
- Editor: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนดไว้ เฉพาะในองค์กรที่ตัวเองสังกัด
|
||||
- Viewer: สามารถดู เอกสาร เฉพาะในองค์กรที่ตัวเองสังกัด
|
||||
|
||||
* 4.3. บทบาท (Roles) พื้นฐาน:
|
||||
|
||||
- Superadmin: ไม่มีข้อจำกัดใดๆ สามารถจัดการได้ทุกอย่างข้ามองค์กร
|
||||
- Admin: มีสิทธิ์เต็มที่ แต่จำกัดเฉพาะในองค์กรที่ตัวเองสังกัด สามารถจัดการผู้ใช้ในองค์กรได้ สามารถสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลังผ่านหน้า Admin
|
||||
- Document Control สามารถ เพิ่ม/แก้ไข/ลบ เอกสาร เฉพาะในองค์กรที่ตัวเองสังกัด ไม่สามารถจัดการผู้ใช้ได้
|
||||
- Editor: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนดไว้ เฉพาะในองค์กรที่ตัวเองสังกัด
|
||||
- Viewer: สามารถดู เอกสาร เฉพาะในองค์กรที่ตัวเองสังกัด
|
||||
|
||||
* 4.4. การบังคับใช้สิทธิ์: สิทธิ์ขององค์กรจะครอบคลุมสิทธิ์ของผู้ใช้ และการเข้าถึงข้อมูลที่เกี่ยวข้องกับโครงการ (เช่น การแก้ไขเอกสาร) จะถูกตรวจสอบเทียบกับสิทธิ์ที่ผู้ใช้มีในโครงการนั้นๆ โดยเฉพาะ
|
||||
- 4.4. การบังคับใช้สิทธิ์: สิทธิ์ขององค์กรจะครอบคลุมสิทธิ์ของผู้ใช้ และการเข้าถึงข้อมูลที่เกี่ยวข้องกับโครงการ (เช่น การแก้ไขเอกสาร) จะถูกตรวจสอบเทียบกับสิทธิ์ที่ผู้ใช้มีในโครงการนั้นๆ โดยเฉพาะ
|
||||
|
||||
## 👥 5. ข้อกำหนดด้านผู้ใช้งาน (User Interface & Experience)
|
||||
|
||||
* 5.1. Layout หลัก: หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย:
|
||||
- Navbar (ส่วนบน): แสดงชื่อระบบ, เมนูผู้ใช้ (Profile), เมนูสำหรับ Admin/Superadmin (จัดการผู้ใช้, จัดการสิทธิ์), และปุ่ม Login/Logout
|
||||
- Sidebar (ด้านข้าง): เป็นเมนูหลักสำหรับเข้าถึงส่วนที่เกี่ยวกับเอกสารทั้งหมด เช่น Dashboard, Correspondences, RFA, Drawings
|
||||
- Main Content Area: พื้นที่สำหรับแสดงเนื้อหาหลักของหน้าที่เลือก
|
||||
* 5.2. หน้า Landing Page: เป็นหน้าแรกที่แสดงข้อมูลบางส่วนของโครงการสำหรับผู้ใช้ที่ยังไม่ได้ล็อกอิน
|
||||
* 5.3. หน้า Dashboard: เป็นหน้าแรกหลังจากล็อกอิน ประกอบด้วย:
|
||||
- การ์ดสรุปภาพรวม (KPI Cards): แสดงข้อมูลสรุปที่สำคัญขององค์กร เช่น จำนวนเอกสาร, งานที่เกินกำหนด
|
||||
- ตาราง "งานของฉัน" (My Tasks Table): แสดงรายการงานทั้งหมดจาก Circulation ที่ผู้ใช้ต้องดำเนินการ
|
||||
* 5.4. การติดตามสถานะ: องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
|
||||
* 5.5. การจัดการข้อมูลส่วนตัว (Profile Page): ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้
|
||||
* 5.6. การจัดการเอกสารทางเทคนิค (Technical Documents & Workflow): ผู้ใช้สามารถดู Technical Document ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว, ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ admin ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ admin ขึ้นไป
|
||||
- 5.1. Layout หลัก: หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย:
|
||||
- Navbar (ส่วนบน): แสดงชื่อระบบ, เมนูผู้ใช้ (Profile), เมนูสำหรับ Admin/Superadmin (จัดการผู้ใช้, จัดการสิทธิ์), และปุ่ม Login/Logout
|
||||
- Sidebar (ด้านข้าง): เป็นเมนูหลักสำหรับเข้าถึงส่วนที่เกี่ยวกับเอกสารทั้งหมด เช่น Dashboard, Correspondences, RFA, Drawings
|
||||
- Main Content Area: พื้นที่สำหรับแสดงเนื้อหาหลักของหน้าที่เลือก
|
||||
- 5.2. หน้า Landing Page: เป็นหน้าแรกที่แสดงข้อมูลบางส่วนของโครงการสำหรับผู้ใช้ที่ยังไม่ได้ล็อกอิน
|
||||
- 5.3. หน้า Dashboard: เป็นหน้าแรกหลังจากล็อกอิน ประกอบด้วย:
|
||||
- การ์ดสรุปภาพรวม (KPI Cards): แสดงข้อมูลสรุปที่สำคัญขององค์กร เช่น จำนวนเอกสาร, งานที่เกินกำหนด
|
||||
- ตาราง "งานของฉัน" (My Tasks Table): แสดงรายการงานทั้งหมดจาก Circulation ที่ผู้ใช้ต้องดำเนินการ
|
||||
- 5.4. การติดตามสถานะ: องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
|
||||
- 5.5. การจัดการข้อมูลส่วนตัว (Profile Page): ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้
|
||||
- 5.6. การจัดการเอกสารทางเทคนิค (Technical Documents & Workflow): ผู้ใช้สามารถดู Technical Document ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว, ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ admin ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ admin ขึ้นไป
|
||||
|
||||
## 6\. ข้อกำหนดที่ไม่ใช่ฟังก์ชันการทำงาน (Non-Functional Requirements)
|
||||
|
||||
* 6.1. การบันทึกการกระทำ (Audit Log): ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน `audit_logs` เพื่อการตรวจสอบย้อนหลัง
|
||||
* 6.2. การค้นหา (Search): ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสารจากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
|
||||
* 6.3. การทำรายงาน (Reporting): สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
|
||||
* 6.4. ประสิทธิภาพ (Performance): มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
* 6.5. ความปลอดภัย (Security):
|
||||
- มีระบบ Rate Limiting เพื่อป้องกันการโจมตีแบบ Brute-force
|
||||
- การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด
|
||||
- 6.1. การบันทึกการกระทำ (Audit Log): ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน `audit_logs` เพื่อการตรวจสอบย้อนหลัง
|
||||
- 6.2. การค้นหา (Search): ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสารจากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
|
||||
- 6.3. การทำรายงาน (Reporting): สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
|
||||
- 6.4. ประสิทธิภาพ (Performance): มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
- 6.5. ความปลอดภัย (Security):
|
||||
- มีระบบ Rate Limiting เพื่อป้องกันการโจมตีแบบ Brute-force
|
||||
- การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด
|
||||
|
||||
+111
-111
@@ -4,12 +4,12 @@
|
||||
|
||||
โครงสร้างประกอบด้วย:
|
||||
|
||||
* Objectives
|
||||
* Deliverables
|
||||
* Task Breakdown (ละเอียดเป็นลำดับงาน)
|
||||
* Developer Checklist
|
||||
* Test Coverage
|
||||
* Dependencies & Risks
|
||||
- Objectives
|
||||
- Deliverables
|
||||
- Task Breakdown (ละเอียดเป็นลำดับงาน)
|
||||
- Developer Checklist
|
||||
- Test Coverage
|
||||
- Dependencies & Risks
|
||||
|
||||
---
|
||||
|
||||
@@ -19,73 +19,73 @@
|
||||
|
||||
## ✔ Deliverables
|
||||
|
||||
* Global ValidationPipe
|
||||
* Sanitization Layer
|
||||
* Rate Limit Rules (anonymous/authenticated)
|
||||
* Security Headers (Helmet)
|
||||
* XSS / SQL Injection safeguards
|
||||
* Security Tests
|
||||
- Global ValidationPipe
|
||||
- Sanitization Layer
|
||||
- Rate Limit Rules (anonymous/authenticated)
|
||||
- Security Headers (Helmet)
|
||||
- XSS / SQL Injection safeguards
|
||||
- Security Tests
|
||||
|
||||
## 🛠 Task Breakdown
|
||||
|
||||
### 2A.1 Validation Pipeline
|
||||
|
||||
* ตั้งค่า Global ValidationPipe
|
||||
* เปิด whitelist, forbidNonWhitelisted
|
||||
* เพิ่ม custom exception mapping → ErrorModel
|
||||
* เชื่อม RequestIdInterceptor
|
||||
- ตั้งค่า Global ValidationPipe
|
||||
- เปิด whitelist, forbidNonWhitelisted
|
||||
- เพิ่ม custom exception mapping → ErrorModel
|
||||
- เชื่อม RequestIdInterceptor
|
||||
|
||||
### 2A.2 Input Sanitization Layer
|
||||
|
||||
* ติดตั้ง sanitize-html หรือ DOMPurify server-side
|
||||
* เพิ่ม sanitization middleware สำหรับ:
|
||||
- ติดตั้ง sanitize-html หรือ DOMPurify server-side
|
||||
- เพิ่ม sanitization middleware สำหรับ:
|
||||
- query params
|
||||
- body JSON
|
||||
- form inputs
|
||||
|
||||
* query params
|
||||
* body JSON
|
||||
* form inputs
|
||||
* เพิ่ม unit test: sanitized input → safe output
|
||||
- เพิ่ม unit test: sanitized input → safe output
|
||||
|
||||
### 2A.3 Security Headers (Helmet)
|
||||
|
||||
* เปิดใช้งาน Helmet ทั้งระบบ
|
||||
* ปรับ policy: `contentSecurityPolicy`, `xssFilter`, `noSniff`
|
||||
* เพิ่ม config per environment
|
||||
- เปิดใช้งาน Helmet ทั้งระบบ
|
||||
- ปรับ policy: `contentSecurityPolicy`, `xssFilter`, `noSniff`
|
||||
- เพิ่ม config per environment
|
||||
|
||||
### 2A.4 Rate Limiting
|
||||
|
||||
* Rate limit แบบ 2 ชั้น:
|
||||
- Rate limit แบบ 2 ชั้น:
|
||||
- anonymous (เช่น 30 req/min)
|
||||
- authenticated (100 req/min)
|
||||
|
||||
* anonymous (เช่น 30 req/min)
|
||||
* authenticated (100 req/min)
|
||||
* สร้าง Redis key pattern: `ratelimit:{ip}`
|
||||
* สร้าง RateLimitGuard + decorator
|
||||
* ทดสอบ burst traffic (locust หรือ autocannon)
|
||||
- สร้าง Redis key pattern: `ratelimit:{ip}`
|
||||
- สร้าง RateLimitGuard + decorator
|
||||
- ทดสอบ burst traffic (locust หรือ autocannon)
|
||||
|
||||
### 2A.5 SQL Injection / XSS Protection
|
||||
|
||||
* เปิด TypeORM parameterized queries
|
||||
* Sanitizer ตรวจจับ script tags
|
||||
* เขียน test ที่ inject payload จำลอง
|
||||
- เปิด TypeORM parameterized queries
|
||||
- Sanitizer ตรวจจับ script tags
|
||||
- เขียน test ที่ inject payload จำลอง
|
||||
|
||||
### 2A.6 Logging + Error Model Integration
|
||||
|
||||
* ผูก SecurityException → Error Model
|
||||
* เพิ่ม request_id logging
|
||||
- ผูก SecurityException → Error Model
|
||||
- เพิ่ม request_id logging
|
||||
|
||||
## ✔ Developer Checklist (Phase 2A)
|
||||
|
||||
* [ ] ทุก controller มี ValidationPipe ครอบ
|
||||
* [ ] Sanitization ทำงานในทุก input source
|
||||
* [ ] Error ทั้งหมดออกตาม Error Model กลาง
|
||||
* [ ] RateLimitGuard ทำงานผ่าน Redis
|
||||
* [ ] มี security test อย่างน้อย 10 ชุด
|
||||
- [ ] ทุก controller มี ValidationPipe ครอบ
|
||||
- [ ] Sanitization ทำงานในทุก input source
|
||||
- [ ] Error ทั้งหมดออกตาม Error Model กลาง
|
||||
- [ ] RateLimitGuard ทำงานผ่าน Redis
|
||||
- [ ] มี security test อย่างน้อย 10 ชุด
|
||||
|
||||
## ✔ Test Coverage (Phase 2A)
|
||||
|
||||
* Input injection tests
|
||||
* Rate limit tests
|
||||
* Validation rejects undefined fields
|
||||
* ErrorModel mapping
|
||||
- Input injection tests
|
||||
- Rate limit tests
|
||||
- Validation rejects undefined fields
|
||||
- ErrorModel mapping
|
||||
|
||||
---
|
||||
|
||||
@@ -95,60 +95,60 @@
|
||||
|
||||
## ✔ Deliverables
|
||||
|
||||
* Schema Registry
|
||||
* Schema Versioning
|
||||
* Schema Validation Service
|
||||
* Compatibility Rules
|
||||
* Schema Migration Tests
|
||||
- Schema Registry
|
||||
- Schema Versioning
|
||||
- Schema Validation Service
|
||||
- Compatibility Rules
|
||||
- Schema Migration Tests
|
||||
|
||||
## 🛠 Task Breakdown
|
||||
|
||||
### 2B.1 Schema Registry
|
||||
|
||||
* Entity: `json_schemas`, `json_schema_versions`
|
||||
* Endpoint: `POST /json-schemas`
|
||||
* ฟิลด์สำคัญ: schema_id, version, schema_json
|
||||
* สร้าง SchemaStore class
|
||||
- Entity: `json_schemas`, `json_schema_versions`
|
||||
- Endpoint: `POST /json-schemas`
|
||||
- ฟิลด์สำคัญ: schema_id, version, schema_json
|
||||
- สร้าง SchemaStore class
|
||||
|
||||
### 2B.2 Schema Versioning
|
||||
|
||||
* Version rule: semantic versioning (major.minor.patch)
|
||||
* Migration notes per version
|
||||
* นโยบาย: Breaking change → major bump
|
||||
* API: `GET /json-schemas/:id?version=`
|
||||
- Version rule: semantic versioning (major.minor.patch)
|
||||
- Migration notes per version
|
||||
- นโยบาย: Breaking change → major bump
|
||||
- API: `GET /json-schemas/:id?version=`
|
||||
|
||||
### 2B.3 Schema Validation Service
|
||||
|
||||
* ใช้ AJV หรือ Fastest-Validator
|
||||
* preload schema เมื่อ boot server
|
||||
* mapping validation error → Error Model
|
||||
* เพิ่ม test: invalid schema / missing fields / wrong types
|
||||
- ใช้ AJV หรือ Fastest-Validator
|
||||
- preload schema เมื่อ boot server
|
||||
- mapping validation error → Error Model
|
||||
- เพิ่ม test: invalid schema / missing fields / wrong types
|
||||
|
||||
### 2B.4 Compatibility Rules
|
||||
|
||||
* ตรวจสอบ backward compatibility:
|
||||
- ตรวจสอบ backward compatibility:
|
||||
- field removal → major version
|
||||
- enum shrink → major version
|
||||
|
||||
* field removal → major version
|
||||
* enum shrink → major version
|
||||
* เพิ่ม script ตรวจ schema diff
|
||||
- เพิ่ม script ตรวจ schema diff
|
||||
|
||||
### 2B.5 Schema Migration Tests
|
||||
|
||||
* ทดสอบ schema upgrade (v1 → v2)
|
||||
* ทดสอบ payload ที่ใช้ version เก่า
|
||||
- ทดสอบ schema upgrade (v1 → v2)
|
||||
- ทดสอบ payload ที่ใช้ version เก่า
|
||||
|
||||
## ✔ Developer Checklist (Phase 2B)
|
||||
|
||||
* [ ] ทุก JSON field อ้างอิง schema version
|
||||
* [ ] ทุก schema ผ่าน validation
|
||||
* [ ] Schema diff pass
|
||||
* [ ] Schema test ครอบครบทุก field
|
||||
- [ ] ทุก JSON field อ้างอิง schema version
|
||||
- [ ] ทุก schema ผ่าน validation
|
||||
- [ ] Schema diff pass
|
||||
- [ ] Schema test ครอบครบทุก field
|
||||
|
||||
## ✔ Test Coverage (Phase 2B)
|
||||
|
||||
* Schema version switch tests
|
||||
* Incompatible payload rejection
|
||||
* Schema registry CRUD
|
||||
- Schema version switch tests
|
||||
- Incompatible payload rejection
|
||||
- Schema registry CRUD
|
||||
|
||||
---
|
||||
|
||||
@@ -158,76 +158,76 @@
|
||||
|
||||
## ✔ Deliverables
|
||||
|
||||
* JSON size validator
|
||||
* JSON sanitizer
|
||||
* JSON compressor (gzip/deflate)
|
||||
* Sensitive fields encryption
|
||||
* JSON transformation layer
|
||||
- JSON size validator
|
||||
- JSON sanitizer
|
||||
- JSON compressor (gzip/deflate)
|
||||
- Sensitive fields encryption
|
||||
- JSON transformation layer
|
||||
|
||||
## 🛠 Task Breakdown
|
||||
|
||||
### 2C.1 JSON Size Controls
|
||||
|
||||
* ตั้ง global limit (เช่น 2MB ต่อฟิลด์)
|
||||
* เพิ่ม JSONSizeGuard
|
||||
* เขียน test: oversize JSON → error_code: `JSON.TOO_LARGE`
|
||||
- ตั้ง global limit (เช่น 2MB ต่อฟิลด์)
|
||||
- เพิ่ม JSONSizeGuard
|
||||
- เขียน test: oversize JSON → error_code: `JSON.TOO_LARGE`
|
||||
|
||||
### 2C.2 JSON Sanitization (ลึกกว่า Phase 2A)
|
||||
|
||||
* ล้าง nested fields
|
||||
* ล้าง `<script>`, `<iframe>`, inline JS
|
||||
* รองรับ JSON array sanitization
|
||||
- ล้าง nested fields
|
||||
- ล้าง `<script>`, `<iframe>`, inline JS
|
||||
- รองรับ JSON array sanitization
|
||||
|
||||
### 2C.3 Compression Layer
|
||||
|
||||
* ใช้ gzip ด้วย `zlib`
|
||||
* เก็บ compressed JSON ใน DB
|
||||
* สร้าง helper: `compressJson()`, `decompressJson()`
|
||||
* Test: compression ratio > 30%
|
||||
- ใช้ gzip ด้วย `zlib`
|
||||
- เก็บ compressed JSON ใน DB
|
||||
- สร้าง helper: `compressJson()`, `decompressJson()`
|
||||
- Test: compression ratio > 30%
|
||||
|
||||
### 2C.4 Sensitive Fields Encryption
|
||||
|
||||
* AES-256-GCM สำหรับฟิลด์ที่กำหนด เช่น:
|
||||
- AES-256-GCM สำหรับฟิลด์ที่กำหนด เช่น:
|
||||
- personal fields
|
||||
- confidential fields
|
||||
|
||||
* personal fields
|
||||
* confidential fields
|
||||
* สร้าง decorator: `@EncryptedField()`
|
||||
* Test: decrypt → original JSON
|
||||
- สร้าง decorator: `@EncryptedField()`
|
||||
- Test: decrypt → original JSON
|
||||
|
||||
### 2C.5 JSON Transformation Layer
|
||||
|
||||
* Map JSON fields → internal format
|
||||
* ใช้กับ Correspondence / RFA
|
||||
* รองรับ schema version migration (เชื่อมกับ Phase 2B)
|
||||
- Map JSON fields → internal format
|
||||
- ใช้กับ Correspondence / RFA
|
||||
- รองรับ schema version migration (เชื่อมกับ Phase 2B)
|
||||
|
||||
## ✔ Developer Checklist (Phase 2C)
|
||||
|
||||
* [ ] JSON size guard ครอบทุก endpoint
|
||||
* [ ] Compression + encryption ทำงานก่อน persist
|
||||
* [ ] Sanitizer ผ่าน nested objects
|
||||
* [ ] Transform layer มี test ครบ
|
||||
- [ ] JSON size guard ครอบทุก endpoint
|
||||
- [ ] Compression + encryption ทำงานก่อน persist
|
||||
- [ ] Sanitizer ผ่าน nested objects
|
||||
- [ ] Transform layer มี test ครบ
|
||||
|
||||
## ✔ Test Coverage (Phase 2C)
|
||||
|
||||
* Oversize JSON tests
|
||||
* Encryption/decryption tests
|
||||
* Compression tests
|
||||
* Schema-versioned transformation tests
|
||||
- Oversize JSON tests
|
||||
- Encryption/decryption tests
|
||||
- Compression tests
|
||||
- Schema-versioned transformation tests
|
||||
|
||||
---
|
||||
|
||||
# 🔗 Dependencies
|
||||
|
||||
* Phase 2A → จำเป็นก่อน 2B, 2C
|
||||
* Phase 2B → ต้องเสร็จเพื่อให้ 2C ทำ transformation
|
||||
- Phase 2A → จำเป็นก่อน 2B, 2C
|
||||
- Phase 2B → ต้องเสร็จเพื่อให้ 2C ทำ transformation
|
||||
|
||||
---
|
||||
|
||||
# ⚠ Risks
|
||||
|
||||
* Schema versioning อาจกระทบ payload เดิม → ต้องมี migration plan
|
||||
* Compression/encryption ทำให้ debug ยาก → ต้องพึ่ง request_id + audit logs
|
||||
* Rate limiting ไม่เหมาะสมอาจ block ผู้ใช้จริง
|
||||
- Schema versioning อาจกระทบ payload เดิม → ต้องมี migration plan
|
||||
- Compression/encryption ทำให้ debug ยาก → ต้องพึ่ง request_id + audit logs
|
||||
- Rate limiting ไม่เหมาะสมอาจ block ผู้ใช้จริง
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,55 +1,54 @@
|
||||
# Documents Management Sytem Version 1.1.0: Application Databases Specification
|
||||
|
||||
## 1. วัตถุประสงค์
|
||||
|
||||
|
||||
## 2. สถาปัตยกรรมและเทคโนโลยี (System Architecture & Technology Stack)
|
||||
|
||||
correspondences ตารางเอกสารโต้ตอบ
|
||||
-- 2.7.5 : n.n.5 for shop_drawing
|
||||
shop_drawings;
|
||||
shop_drawings;
|
||||
-- 2.6.6 : n.n.6 for contract_drawing
|
||||
contract_drawings;
|
||||
contract_drawings;
|
||||
-- 2.5.2 : n.n.2 for rfa
|
||||
rfas;
|
||||
rfas;
|
||||
-- 2.4.4 : n.n.4 for transmittal
|
||||
transmittals;
|
||||
transmittals;
|
||||
-- 2.3.3: n.n.3 for circulation
|
||||
circulations;
|
||||
|
||||
circulations;
|
||||
|
||||
users;
|
||||
users;
|
||||
-- 4.7
|
||||
projects ตารางโครงการ
|
||||
projects ตารางโครงการ
|
||||
-- 4.6
|
||||
contracts ตารางสัญญา
|
||||
contracts ตารางสัญญา
|
||||
-- 4.2
|
||||
permissions;
|
||||
permissions;
|
||||
-- 4.1
|
||||
roles;
|
||||
roles;
|
||||
|
||||
-- Level 5: ตารางที่เป็นรากฐานที่สุด
|
||||
-- 5.2
|
||||
organizations ตารางองกรณ์;
|
||||
organizations ตารางองกรณ์;
|
||||
-- 5.1
|
||||
organization_roles;
|
||||
organization_roles;
|
||||
|
||||
-- 1.2
|
||||
attachments;
|
||||
|
||||
attachments;
|
||||
|
||||
-- 1.1
|
||||
global_default_roles;
|
||||
global_default_roles;
|
||||
|
||||
audit_logs;
|
||||
audit_logs;
|
||||
|
||||
ใช้สถาปัตยกรรมแบบ Headless/API-First ที่ทันสมัย ทำงานทั้งหมดบน QNAP Server ผ่าน Container Station เพื่อความสะดวกในการจัดการและบำรุงรักษา, Domain: np-dms.work, มี fix ip, รัน docker command ใน application ของ Container Station ได้โดยตรง, ประกอบด้วย
|
||||
|
||||
ใช้สถาปัตยกรรมแบบ Headless/API-First ที่ทันสมัย ทำงานทั้งหมดบน QNAP Server ผ่าน Container Station เพื่อความสะดวกในการจัดการและบำรุงรักษา, Domain: np-dms.work, มี fix ip, รัน docker command ใน application ของ Container Station ได้โดยตรง, ประกอบด้วย
|
||||
|
||||
* 2.1. Infrastructure & Environment:
|
||||
- Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
- Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
|
||||
- Development Environment: VS Code on Windows 11
|
||||
- Domain: np-dms.work, www.np-dms.work
|
||||
- ip: 159.192.126.103
|
||||
- Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
- Data Storage: /share/dms-data บน QNAP
|
||||
- ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
*
|
||||
- 2.1. Infrastructure & Environment:
|
||||
- Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
- Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
|
||||
- Development Environment: VS Code on Windows 11
|
||||
- Domain: np-dms.work, www.np-dms.work
|
||||
- ip: 159.192.126.103
|
||||
- Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
- Data Storage: /share/dms-data บน QNAP
|
||||
- ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
-
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,205 +8,205 @@
|
||||
|
||||
### **หลักการพื้นฐาน**
|
||||
|
||||
* ใช้ **ภาษาอังกฤษ** สำหรับโค้ดและเอกสารทั้งหมด
|
||||
* กำหนดไทป์ (type) อย่างชัดเจนสำหรับตัวแปร, พารามิเตอร์ และค่าที่ส่งกลับ (return values) ทั้งหมด
|
||||
* หลีกเลี่ยงการใช้ any; ให้สร้างไทป์ (types) หรืออินเทอร์เฟซ (interfaces) ที่กำหนดเอง
|
||||
* ใช้ **JSDoc** สำหรับคลาส (classes) และเมธอด (methods) ที่เป็น public
|
||||
* ส่งออก (Export) **สัญลักษณ์หลัก (main symbol) เพียงหนึ่งเดียว** ต่อไฟล์
|
||||
* หลีกเลี่ยงบรรทัดว่างภายในฟังก์ชัน
|
||||
- ใช้ **ภาษาอังกฤษ** สำหรับโค้ดและเอกสารทั้งหมด
|
||||
- กำหนดไทป์ (type) อย่างชัดเจนสำหรับตัวแปร, พารามิเตอร์ และค่าที่ส่งกลับ (return values) ทั้งหมด
|
||||
- หลีกเลี่ยงการใช้ any; ให้สร้างไทป์ (types) หรืออินเทอร์เฟซ (interfaces) ที่กำหนดเอง
|
||||
- ใช้ **JSDoc** สำหรับคลาส (classes) และเมธอด (methods) ที่เป็น public
|
||||
- ส่งออก (Export) **สัญลักษณ์หลัก (main symbol) เพียงหนึ่งเดียว** ต่อไฟล์
|
||||
- หลีกเลี่ยงบรรทัดว่างภายในฟังก์ชัน
|
||||
|
||||
### **ข้อตกลงในการตั้งชื่อ (Naming Conventions)**
|
||||
|
||||
| Entity (สิ่งที่ตั้งชื่อ) | Convention (รูปแบบ) | Example (ตัวอย่าง) |
|
||||
| :---- | :---- | :---- |
|
||||
| Classes | PascalCase | UserService |
|
||||
| Variables & Functions | camelCase | getUserInfo |
|
||||
| Files & Folders | kebab-case | user-service.ts |
|
||||
| Environment Variables | UPPERCASE | DATABASE\URL |
|
||||
| Booleans | Verb \+ Noun | isActive, canDelete, hasPermission |
|
||||
| Entity (สิ่งที่ตั้งชื่อ) | Convention (รูปแบบ) | Example (ตัวอย่าง) |
|
||||
| :----------------------- | :------------------ | :--------------------------------- |
|
||||
| Classes | PascalCase | UserService |
|
||||
| Variables & Functions | camelCase | getUserInfo |
|
||||
| Files & Folders | kebab-case | user-service.ts |
|
||||
| Environment Variables | UPPERCASE | DATABASE\URL |
|
||||
| Booleans | Verb \+ Noun | isActive, canDelete, hasPermission |
|
||||
|
||||
ใช้คำเต็ม — ไม่ใช้อักษรย่อ — ยกเว้นคำมาตรฐาน (เช่น API, URL, req, res, err, ctx)
|
||||
|
||||
## **🧩 ฟังก์ชัน (Functions)**
|
||||
|
||||
* เขียนฟังก์ชันให้สั้น และทำ **หน้าที่เพียงอย่างเดียว** (single-purpose) (\< 20 บรรทัด)
|
||||
* ใช้ **early returns** เพื่อลดการซ้อน (nesting) ของโค้ด
|
||||
* ใช้ **map**, **filter**, **reduce** แทนการใช้ loops เมื่อเหมาะสม
|
||||
* ควรใช้ **arrow functions** สำหรับตรรกะสั้นๆ, และใช้ **named functions** ในกรณีอื่น
|
||||
* ใช้ **default parameters** แทนการตรวจสอบค่า null
|
||||
* จัดกลุ่มพารามิเตอร์หลายตัวให้เป็นอ็อบเจกต์เดียว (RO-RO pattern)
|
||||
* ส่งค่ากลับ (Return) เป็นอ็อบเจกต์ที่มีไทป์กำหนด (typed objects) ไม่ใช่ค่าพื้นฐาน (primitives)
|
||||
* รักษาระดับของสิ่งที่เป็นนามธรรม (abstraction level) ให้เป็นระดับเดียวในแต่ละฟังก์ชัน
|
||||
- เขียนฟังก์ชันให้สั้น และทำ **หน้าที่เพียงอย่างเดียว** (single-purpose) (\< 20 บรรทัด)
|
||||
- ใช้ **early returns** เพื่อลดการซ้อน (nesting) ของโค้ด
|
||||
- ใช้ **map**, **filter**, **reduce** แทนการใช้ loops เมื่อเหมาะสม
|
||||
- ควรใช้ **arrow functions** สำหรับตรรกะสั้นๆ, และใช้ **named functions** ในกรณีอื่น
|
||||
- ใช้ **default parameters** แทนการตรวจสอบค่า null
|
||||
- จัดกลุ่มพารามิเตอร์หลายตัวให้เป็นอ็อบเจกต์เดียว (RO-RO pattern)
|
||||
- ส่งค่ากลับ (Return) เป็นอ็อบเจกต์ที่มีไทป์กำหนด (typed objects) ไม่ใช่ค่าพื้นฐาน (primitives)
|
||||
- รักษาระดับของสิ่งที่เป็นนามธรรม (abstraction level) ให้เป็นระดับเดียวในแต่ละฟังก์ชัน
|
||||
|
||||
## **🧱 การจัดการข้อมูล (Data Handling)**
|
||||
|
||||
* ห่อหุ้มข้อมูล (Encapsulate) ในไทป์แบบผสม (composite types)
|
||||
* ใช้ **immutability** (การไม่เปลี่ยนแปลงค่า) ด้วย readonly และ as const
|
||||
* ทำการตรวจสอบความถูกต้องของข้อมูล (Validations) ในคลาสหรือ DTOs ไม่ใช่ภายในฟังก์ชันทางธุรกิจ
|
||||
* ตรวจสอบความถูกต้องของข้อมูลโดยใช้ DTOs ที่มีไทป์กำหนดเสมอ
|
||||
- ห่อหุ้มข้อมูล (Encapsulate) ในไทป์แบบผสม (composite types)
|
||||
- ใช้ **immutability** (การไม่เปลี่ยนแปลงค่า) ด้วย readonly และ as const
|
||||
- ทำการตรวจสอบความถูกต้องของข้อมูล (Validations) ในคลาสหรือ DTOs ไม่ใช่ภายในฟังก์ชันทางธุรกิจ
|
||||
- ตรวจสอบความถูกต้องของข้อมูลโดยใช้ DTOs ที่มีไทป์กำหนดเสมอ
|
||||
|
||||
## **🧰 คลาส (Classes)**
|
||||
|
||||
* ปฏิบัติตามหลักการ **SOLID**
|
||||
* ควรใช้ **composition มากกว่า inheritance** (Prefer composition over inheritance)
|
||||
* กำหนด **interfaces** สำหรับสัญญา (contracts)
|
||||
* ให้คลาสมุ่งเน้นการทำงานเฉพาะอย่างและมีขนาดเล็ก (\< 200 บรรทัด, \< 10 เมธอด, \< 10 properties)
|
||||
- ปฏิบัติตามหลักการ **SOLID**
|
||||
- ควรใช้ **composition มากกว่า inheritance** (Prefer composition over inheritance)
|
||||
- กำหนด **interfaces** สำหรับสัญญา (contracts)
|
||||
- ให้คลาสมุ่งเน้นการทำงานเฉพาะอย่างและมีขนาดเล็ก (\< 200 บรรทัด, \< 10 เมธอด, \< 10 properties)
|
||||
|
||||
## **🚨 การจัดการข้อผิดพลาด (Error Handling)**
|
||||
|
||||
* ใช้ Exceptions สำหรับข้อผิดพลาดที่ไม่คาดคิด
|
||||
* ดักจับ (Catch) ข้อผิดพลาดเพื่อแก้ไขหรือเพิ่มบริบท (context) เท่านั้น; หากไม่เช่นนั้น ให้ใช้ global error handlers
|
||||
* ระบุข้อความข้อผิดพลาด (error messages) ที่มีความหมายเสมอ
|
||||
- ใช้ Exceptions สำหรับข้อผิดพลาดที่ไม่คาดคิด
|
||||
- ดักจับ (Catch) ข้อผิดพลาดเพื่อแก้ไขหรือเพิ่มบริบท (context) เท่านั้น; หากไม่เช่นนั้น ให้ใช้ global error handlers
|
||||
- ระบุข้อความข้อผิดพลาด (error messages) ที่มีความหมายเสมอ
|
||||
|
||||
## **🧪 การทดสอบ (ทั่วไป) (Testing (General))**
|
||||
|
||||
* ใช้รูปแบบ **Arrange–Act–Assert**
|
||||
* ใช้ชื่อตัวแปรในการทดสอบที่สื่อความหมาย (inputData, expectedOutput)
|
||||
* เขียน **unit tests** สำหรับ public methods ทั้งหมด
|
||||
* จำลอง (Mock) การพึ่งพาภายนอก (external dependencies)
|
||||
* เพิ่ม **acceptance tests** ต่อโมดูลโดยใช้รูปแบบ Given–When-Then
|
||||
- ใช้รูปแบบ **Arrange–Act–Assert**
|
||||
- ใช้ชื่อตัวแปรในการทดสอบที่สื่อความหมาย (inputData, expectedOutput)
|
||||
- เขียน **unit tests** สำหรับ public methods ทั้งหมด
|
||||
- จำลอง (Mock) การพึ่งพาภายนอก (external dependencies)
|
||||
- เพิ่ม **acceptance tests** ต่อโมดูลโดยใช้รูปแบบ Given–When-Then
|
||||
|
||||
# **🏗️ แบ็กเอนด์ (NestJS) (Backend (NestJS))**
|
||||
|
||||
### **หลักการ**
|
||||
|
||||
* **สถาปัตยกรรมแบบโมดูลาร์ (Modular architecture)**:
|
||||
* หนึ่งโมดูลต่อหนึ่งโดเมน
|
||||
* โครงสร้างแบบ Controller → Service → Repository (Model)
|
||||
* DTOs ที่ตรวจสอบความถูกต้องด้วย **class-validator**
|
||||
* ใช้ **MikroORM** (หรือ TypeORM/Prisma) สำหรับการคงอยู่ของข้อมูล (persistence) ซึ่งสอดคล้องกับสคีมา MariaDB
|
||||
* ห่อหุ้มโค้ดที่ใช้ซ้ำได้ไว้ใน **common module** (@app/common):
|
||||
* Configs, decorators, DTOs, guards, interceptors, notifications, shared services, types, validators
|
||||
- **สถาปัตยกรรมแบบโมดูลาร์ (Modular architecture)**:
|
||||
- หนึ่งโมดูลต่อหนึ่งโดเมน
|
||||
- โครงสร้างแบบ Controller → Service → Repository (Model)
|
||||
- DTOs ที่ตรวจสอบความถูกต้องด้วย **class-validator**
|
||||
- ใช้ **MikroORM** (หรือ TypeORM/Prisma) สำหรับการคงอยู่ของข้อมูล (persistence) ซึ่งสอดคล้องกับสคีมา MariaDB
|
||||
- ห่อหุ้มโค้ดที่ใช้ซ้ำได้ไว้ใน **common module** (@app/common):
|
||||
- Configs, decorators, DTOs, guards, interceptors, notifications, shared services, types, validators
|
||||
|
||||
### **ฟังก์ชันหลัก (Core Functionalities)**
|
||||
|
||||
* Global **filters** สำหรับการจัดการ exception
|
||||
* **Middlewares** สำหรับการจัดการ request
|
||||
* **Guards** สำหรับการอนุญาต (permissions) และ RBAC
|
||||
* **Interceptors** สำหรับการแปลงข้อมูล response และการบันทึก log
|
||||
- Global **filters** สำหรับการจัดการ exception
|
||||
- **Middlewares** สำหรับการจัดการ request
|
||||
- **Guards** สำหรับการอนุญาต (permissions) และ RBAC
|
||||
- **Interceptors** สำหรับการแปลงข้อมูล response และการบันทึก log
|
||||
|
||||
### **ข้อจำกัดในการ Deploy (QNAP Container Station)**
|
||||
|
||||
* **ห้ามใช้ไฟล์ .env** ในการตั้งค่า Environment Variables [cite: 2.1]
|
||||
* การตั้งค่าทั้งหมด (เช่น Database connection string, JWT secret) **จะต้องถูกกำหนดผ่าน Environment Variable ใน docker-compose.yml โดยตรง** [cite: 6.5] ซึ่งจะจัดการผ่าน UI ของ QNAP Container Station [cite: 2.1]
|
||||
- **ห้ามใช้ไฟล์ .env** ในการตั้งค่า Environment Variables [cite: 2.1]
|
||||
- การตั้งค่าทั้งหมด (เช่น Database connection string, JWT secret) **จะต้องถูกกำหนดผ่าน Environment Variable ใน docker-compose.yml โดยตรง** [cite: 6.5] ซึ่งจะจัดการผ่าน UI ของ QNAP Container Station [cite: 2.1]
|
||||
|
||||
### **โครงสร้างโมดูลตามโดเมน (Domain-Driven Module Structure)**
|
||||
|
||||
เพื่อให้สอดคล้องกับสคีมา SQL (LCBP3-DMS) เราจะใช้โครงสร้างโมดูลแบบ **Domain-Driven (แบ่งตามขอบเขตธุรกิจ)** แทนการแบ่งตามฟังก์ชัน:
|
||||
|
||||
1. **CoreModule / CommonModule:**
|
||||
* เก็บ Services ที่ใช้ร่วมกัน เช่น DatabaseModule, FileStorageService (จัดการไฟล์ใน QNAP), AuditLogService, NotificationService
|
||||
* NotificationService ต้องรองรับ Triggers ที่ระบุใน Requirement 6.7 [cite: 6.7]
|
||||
- เก็บ Services ที่ใช้ร่วมกัน เช่น DatabaseModule, FileStorageService (จัดการไฟล์ใน QNAP), AuditLogService, NotificationService
|
||||
- NotificationService ต้องรองรับ Triggers ที่ระบุใน Requirement 6.7 [cite: 6.7]
|
||||
2. **AuthModule / UserModule:**
|
||||
* จัดการ users, roles, permissions และการยืนยันตัวตน (JWT, Guards)
|
||||
* **(สำคัญ)** ต้องรับผิดชอบการตรวจสอบสิทธิ์ **3 ระดับ** [cite: 4.2]: สิทธิ์ระดับระบบ (Global Role), สิทธิ์ระดับโปรเจกต์ (Project Role), และ **สิทธิ์ระดับสัญญา (Contract Role)**
|
||||
* **(สำคัญ)** ต้องมี API สำหรับ **Admin Panel** เพื่อ:
|
||||
* สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก [cite: 4.3]
|
||||
* จัดการ Master Data (เช่น correspondence_types, tags) [cite: 4.5]
|
||||
* ให้ Superadmin สร้าง Organizations และกำหนด Org Admin ได้ [cite: 4.6]
|
||||
* ให้ Superadmin/Admin จัดการ document_number_formats (รูปแบบเลขที่เอกสาร) [cite: 3.10]
|
||||
- จัดการ users, roles, permissions และการยืนยันตัวตน (JWT, Guards)
|
||||
- **(สำคัญ)** ต้องรับผิดชอบการตรวจสอบสิทธิ์ **3 ระดับ** [cite: 4.2]: สิทธิ์ระดับระบบ (Global Role), สิทธิ์ระดับโปรเจกต์ (Project Role), และ **สิทธิ์ระดับสัญญา (Contract Role)**
|
||||
- **(สำคัญ)** ต้องมี API สำหรับ **Admin Panel** เพื่อ:
|
||||
- สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก [cite: 4.3]
|
||||
- จัดการ Master Data (เช่น correspondence_types, tags) [cite: 4.5]
|
||||
- ให้ Superadmin สร้าง Organizations และกำหนด Org Admin ได้ [cite: 4.6]
|
||||
- ให้ Superadmin/Admin จัดการ document_number_formats (รูปแบบเลขที่เอกสาร) [cite: 3.10]
|
||||
3. **ProjectModule:**
|
||||
* จัดการ projects, organizations, contracts, project_parties, contract_parties
|
||||
- จัดการ projects, organizations, contracts, project_parties, contract_parties
|
||||
4. **CorrespondenceModule (โมดูลศูนย์กลาง):**
|
||||
* จัดการ correspondences, correspondence\revisions
|
||||
* **(สำคัญ)** Service นี้ต้อง Inject DocumentNumberingService เพื่อขอเลขที่เอกสารใหม่ก่อนการสร้าง
|
||||
* **(สำคัญ)** ตรรกะการสร้าง/อัปเดต Revision จะอยู่ใน Service นี้
|
||||
* จัดการ correspondence_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
* รับผิดชอบเวิร์กโฟลว์ **"Correspondence Routings"** (correspondence\routings) สำหรับการส่งต่อเอกสารทั่วไประหว่างองค์กร
|
||||
- จัดการ correspondences, correspondence\revisions
|
||||
- **(สำคัญ)** Service นี้ต้อง Inject DocumentNumberingService เพื่อขอเลขที่เอกสารใหม่ก่อนการสร้าง
|
||||
- **(สำคัญ)** ตรรกะการสร้าง/อัปเดต Revision จะอยู่ใน Service นี้
|
||||
- จัดการ correspondence_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
- รับผิดชอบเวิร์กโฟลว์ **"Correspondence Routings"** (correspondence\routings) สำหรับการส่งต่อเอกสารทั่วไประหว่างองค์กร
|
||||
5. **RfaModule:**
|
||||
* จัดการ rfas, rfa_revisions, rfa_items
|
||||
* รับผิดชอบเวิร์กโฟลว์ **"RFA Workflows"** (rfa_workflows) สำหรับการอนุมัติเอกสารทางเทคนิค
|
||||
- จัดการ rfas, rfa_revisions, rfa_items
|
||||
- รับผิดชอบเวิร์กโฟลว์ **"RFA Workflows"** (rfa_workflows) สำหรับการอนุมัติเอกสารทางเทคนิค
|
||||
6. **DrawingModule:**
|
||||
* จัดการ shop_drawings, shop_drawing_revisions, contract_drawings และหมวดหมู่ต่างๆ
|
||||
* จัดการ shop_drawing_revision_attachments และ contract_drawing_attachments(ตารางเชื่อมไฟล์แนบ)
|
||||
- จัดการ shop_drawings, shop_drawing_revisions, contract_drawings และหมวดหมู่ต่างๆ
|
||||
- จัดการ shop_drawing_revision_attachments และ contract_drawing_attachments(ตารางเชื่อมไฟล์แนบ)
|
||||
7. **CirculationModule:**
|
||||
* จัดการ circulations, circulation_templates, circulation_assignees
|
||||
* จัดการ circulation_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
* รับผิดชอบเวิร์กโฟลว์ **"Circulations"** สำหรับการเวียนเอกสาร **ภายในองค์กร**
|
||||
8. **TransmittalModule:**
|
||||
* จัดการ transmittals และ transmittal_items
|
||||
- จัดการ circulations, circulation_templates, circulation_assignees
|
||||
- จัดการ circulation_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
- รับผิดชอบเวิร์กโฟลว์ **"Circulations"** สำหรับการเวียนเอกสาร **ภายในองค์กร**
|
||||
8. **TransmittalModule:**
|
||||
- จัดการ transmittals และ transmittal_items
|
||||
9. **SearchModule:**
|
||||
* ให้บริการค้นหาขั้นสูง (Advanced Search) [cite: 6.2] โดยใช้ **Elasticsearch** เพื่อรองรับการค้นหาแบบ Full-text จากชื่อเรื่อง, รายละเอียด, เลขที่เอกสาร, ประเภท, วันที่, และ Tags
|
||||
- ให้บริการค้นหาขั้นสูง (Advanced Search) [cite: 6.2] โดยใช้ **Elasticsearch** เพื่อรองรับการค้นหาแบบ Full-text จากชื่อเรื่อง, รายละเอียด, เลขที่เอกสาร, ประเภท, วันที่, และ Tags
|
||||
10. **DocumentNumberingModule:**
|
||||
* **สถานะ:** เป็น Module ภายใน (Internal Module) ไม่เปิด API สู่ภายนอก
|
||||
* **หน้าที่:** ให้บริการ DocumentNumberingService ที่ Module อื่น (เช่น CorrespondenceModule) จะ Inject ไปใช้งาน
|
||||
* **ตรรกะ:** รับผิดชอบการสร้างเลขที่เอกสาร โดยการเรียกใช้ Stored Procedure *sp_get_next_document_number** เพื่อป้องกัน Race Condition
|
||||
- **สถานะ:** เป็น Module ภายใน (Internal Module) ไม่เปิด API สู่ภายนอก
|
||||
- **หน้าที่:** ให้บริการ DocumentNumberingService ที่ Module อื่น (เช่น CorrespondenceModule) จะ Inject ไปใช้งาน
|
||||
- **ตรรกะ:** รับผิดชอบการสร้างเลขที่เอกสาร โดยการเรียกใช้ Stored Procedure \*sp_get_next_document_number\*\* เพื่อป้องกัน Race Condition
|
||||
|
||||
### **เครื่องมือและไลบรารีที่แนะนำ (Recommended Tools & Libraries)**
|
||||
|
||||
🔐 **Authentication & Authorization**
|
||||
|
||||
* @nestjs/passport
|
||||
* @nestjs/jwt
|
||||
* casl – สำหรับ RBAC (Role-Based Access Control)
|
||||
- @nestjs/passport
|
||||
- @nestjs/jwt
|
||||
- casl – สำหรับ RBAC (Role-Based Access Control)
|
||||
|
||||
🗃️ **Database & ORM**
|
||||
|
||||
* @nestjs/typeorm – ORM สำหรับ SQL (หรือ Prisma เป็นทางเลือก)
|
||||
* typeorm-seeding – สำหรับสร้างข้อมูลจำลอง (seeding)
|
||||
- @nestjs/typeorm – ORM สำหรับ SQL (หรือ Prisma เป็นทางเลือก)
|
||||
- typeorm-seeding – สำหรับสร้างข้อมูลจำลอง (seeding)
|
||||
|
||||
📦 **Validation & Transformation**
|
||||
|
||||
* class-validator
|
||||
* class-transformer
|
||||
- class-validator
|
||||
- class-transformer
|
||||
|
||||
📁 **File Upload & Storage**
|
||||
|
||||
* @nestjs/platform-express
|
||||
* multer – สำหรับจัดการไฟล์
|
||||
- @nestjs/platform-express
|
||||
- multer – สำหรับจัดการไฟล์
|
||||
|
||||
🔍 **Search**
|
||||
|
||||
* @nestjs/elasticsearch – สำหรับ Full-text search [cite: 6.2]
|
||||
- @nestjs/elasticsearch – สำหรับ Full-text search [cite: 6.2]
|
||||
|
||||
📬 **Notification**
|
||||
|
||||
* nodemailer – สำหรับส่งอีเมล
|
||||
* @nestjs/schedule – สำหรับ cron job หรือแจ้งเตือนตามเวลา
|
||||
- nodemailer – สำหรับส่งอีเมล
|
||||
- @nestjs/schedule – สำหรับ cron job หรือแจ้งเตือนตามเวลา
|
||||
|
||||
📊 **Logging & Monitoring**
|
||||
|
||||
* winston หรือ nestjs-pino – ระบบ log ที่ยืดหยุ่น
|
||||
* @nestjs/terminus – สำหรับ health check
|
||||
- winston หรือ nestjs-pino – ระบบ log ที่ยืดหยุ่น
|
||||
- @nestjs/terminus – สำหรับ health check
|
||||
|
||||
🧪 **Testing**
|
||||
|
||||
* @nestjs/testing
|
||||
* jest – สำหรับ unit/integration test
|
||||
- @nestjs/testing
|
||||
- jest – สำหรับ unit/integration test
|
||||
|
||||
🌐 **API Documentation**
|
||||
|
||||
* @nestjs/swagger – **(สำคัญมาก)** สร้าง Swagger UI อัตโนมัติ ต้องใช้ DTOs อย่างเคร่งครัดเพื่อความชัดเจนของ API สำหรับทีม Frontend
|
||||
- @nestjs/swagger – **(สำคัญมาก)** สร้าง Swagger UI อัตโนมัติ ต้องใช้ DTOs อย่างเคร่งครัดเพื่อความชัดเจนของ API สำหรับทีม Frontend
|
||||
|
||||
🛡️ **Security**
|
||||
|
||||
* helmet – ป้องกันช่องโหว่ HTTP
|
||||
* rate-limiter-flexible – ป้องกัน brute force
|
||||
- helmet – ป้องกันช่องโหว่ HTTP
|
||||
- rate-limiter-flexible – ป้องกัน brute force
|
||||
|
||||
### **🧪 Backend Testing**
|
||||
|
||||
เราจะแบ่งการทดสอบเป็น 3 ระดับ โดยใช้ **Jest** และ @nestjs/testing:
|
||||
|
||||
* **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
* **เป้าหมาย:** ทดสอบ Logic ภายใน Service, Guard, หรือ Pipe โดยจำลอง (Mock) Dependencies ทั้งหมด
|
||||
* **สิ่งที่ต้องทดสอบ:** Business Logic (เช่น การเปลี่ยนสถานะ Workflow, การตรวจสอบ Deadline) [cite: 2.9.1], ตรรกะการตรวจสอบสิทธิ์ (Auth Guard) ทั้ง 3 ระดับ
|
||||
* **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
* **เป้าหมาย:** ทดสอบการทำงานร่วมกันของ Controller -> Service -> Repository (Database)
|
||||
* **เทคนิค:** ใช้ **Test Database แยกต่างหาก** (ห้ามใช้ Dev DB) และใช้ supertest เพื่อยิง HTTP Request จริงไปยัง App
|
||||
* **สิ่งที่ต้องทดสอบ:** การเรียก sp\get\next\document\number [cite: 2.9.3] และการทำงานของ Views (เช่น v_user_tasks)
|
||||
* **E2E (End-to-End) Tests:**
|
||||
* **เป้าหมาย:** ทดสอบ API Contract ว่า Response Body Shape ตรงตามเอกสาร Swagger เพื่อรับประกันทีม Frontend
|
||||
- **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
- **เป้าหมาย:** ทดสอบ Logic ภายใน Service, Guard, หรือ Pipe โดยจำลอง (Mock) Dependencies ทั้งหมด
|
||||
- **สิ่งที่ต้องทดสอบ:** Business Logic (เช่น การเปลี่ยนสถานะ Workflow, การตรวจสอบ Deadline) [cite: 2.9.1], ตรรกะการตรวจสอบสิทธิ์ (Auth Guard) ทั้ง 3 ระดับ
|
||||
- **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
- **เป้าหมาย:** ทดสอบการทำงานร่วมกันของ Controller -> Service -> Repository (Database)
|
||||
- **เทคนิค:** ใช้ **Test Database แยกต่างหาก** (ห้ามใช้ Dev DB) และใช้ supertest เพื่อยิง HTTP Request จริงไปยัง App
|
||||
- **สิ่งที่ต้องทดสอบ:** การเรียก sp\get\next\document\number [cite: 2.9.3] และการทำงานของ Views (เช่น v_user_tasks)
|
||||
- **E2E (End-to-End) Tests:**
|
||||
- **เป้าหมาย:** ทดสอบ API Contract ว่า Response Body Shape ตรงตามเอกสาร Swagger เพื่อรับประกันทีม Frontend
|
||||
|
||||
### **🗄️ Backend State Management**
|
||||
|
||||
Backend (NestJS) ควรเป็น **Stateless** (ไม่เก็บสถานะ) "State" ทั้งหมดจะถูกจัดเก็บใน MariaDB
|
||||
|
||||
* **Request-Scoped State (สถานะภายใน Request เดียว):**
|
||||
* **ปัญหา:** จะส่งต่อข้อมูล (เช่น User ที่ล็อกอิน) ระหว่าง Guard และ Service ใน Request เดียวกันได้อย่างไร?
|
||||
* **วิธีแก้:** ใช้ **Request-Scoped Providers** ของ NestJS (เช่น AuthContextService) เพื่อเก็บข้อมูล User ปัจจุบันที่ได้จาก AuthGuard และให้ Service อื่น Inject ไปใช้
|
||||
* **Application-Scoped State (การ Caching):**
|
||||
* **ปัญหา:** ข้อมูล Master (เช่น roles, permissions, organizations) ถูกเรียกใช้บ่อย
|
||||
* **วิธีแก้:** ใช้ **Caching** (เช่น @nestjs/cache-manager) เพื่อ Caching ข้อมูลเหล่านี้ และลดภาระ Database
|
||||
- **Request-Scoped State (สถานะภายใน Request เดียว):**
|
||||
- **ปัญหา:** จะส่งต่อข้อมูล (เช่น User ที่ล็อกอิน) ระหว่าง Guard และ Service ใน Request เดียวกันได้อย่างไร?
|
||||
- **วิธีแก้:** ใช้ **Request-Scoped Providers** ของ NestJS (เช่น AuthContextService) เพื่อเก็บข้อมูล User ปัจจุบันที่ได้จาก AuthGuard และให้ Service อื่น Inject ไปใช้
|
||||
- **Application-Scoped State (การ Caching):**
|
||||
- **ปัญหา:** ข้อมูล Master (เช่น roles, permissions, organizations) ถูกเรียกใช้บ่อย
|
||||
- **วิธีแก้:** ใช้ **Caching** (เช่น @nestjs/cache-manager) เพื่อ Caching ข้อมูลเหล่านี้ และลดภาระ Database
|
||||
|
||||
# **🖥️ ฟรอนต์เอนด์ (NextJS / React / UI) (Frontend (NextJS / React / UI))**
|
||||
|
||||
@@ -217,76 +217,76 @@ Backend (NestJS) ควรเป็น **Stateless** (ไม่เก็บส
|
||||
|
||||
### **แนวทางการพัฒนาโค้ด (Code Implementation Guidelines)**
|
||||
|
||||
* ใช้ **early returns** เพื่อความชัดเจน
|
||||
* ใช้คลาสของ **TailwindCSS** ในการกำหนดสไตล์เสมอ
|
||||
* ควรใช้ class: syntax แบบมีเงื่อนไข (หรือ utility clsx) มากกว่าการใช้ ternary operators ใน class strings
|
||||
* ใช้ **const arrow functions** สำหรับ components และ handlers
|
||||
* Event handlers ให้ขึ้นต้นด้วย handle... (เช่น handleClick, handleSubmit)
|
||||
* รวมแอตทริบิวต์สำหรับการเข้าถึง (accessibility) ด้วย:
|
||||
- ใช้ **early returns** เพื่อความชัดเจน
|
||||
- ใช้คลาสของ **TailwindCSS** ในการกำหนดสไตล์เสมอ
|
||||
- ควรใช้ class: syntax แบบมีเงื่อนไข (หรือ utility clsx) มากกว่าการใช้ ternary operators ใน class strings
|
||||
- ใช้ **const arrow functions** สำหรับ components และ handlers
|
||||
- Event handlers ให้ขึ้นต้นด้วย handle... (เช่น handleClick, handleSubmit)
|
||||
- รวมแอตทริบิวต์สำหรับการเข้าถึง (accessibility) ด้วย:
|
||||
tabIndex="0", aria-label, onKeyDown, ฯลฯ
|
||||
* ตรวจสอบให้แน่ใจว่าโค้ดทั้งหมด **สมบูรณ์**, **ผ่านการทดสอบ**, และ **ไม่ซ้ำซ้อน (DRY)**
|
||||
* ต้อง import โมดูลที่จำเป็นต้องใช้อย่างชัดเจนเสมอ
|
||||
- ตรวจสอบให้แน่ใจว่าโค้ดทั้งหมด **สมบูรณ์**, **ผ่านการทดสอบ**, และ **ไม่ซ้ำซ้อน (DRY)**
|
||||
- ต้อง import โมดูลที่จำเป็นต้องใช้อย่างชัดเจนเสมอ
|
||||
|
||||
### **UI/UX ด้วย React**
|
||||
|
||||
* ใช้ **semantic HTML**
|
||||
* ใช้คลาสของ **Tailwind** ที่รองรับ responsive (sm:, md:, lg:)
|
||||
* รักษาลำดับชั้นของการมองเห็น (visual hierarchy) ด้วยการใช้ typography และ spacing
|
||||
* ใช้ **Shadcn** components (Button, Input, Card, ฯลฯ) เพื่อ UI ที่สอดคล้องกัน
|
||||
* ทำให้ components มีขนาดเล็กและมุ่งเน้นการทำงานเฉพาะอย่าง
|
||||
* ใช้ utility classes สำหรับการจัดสไตล์อย่างรวดเร็ว (spacing, colors, text, ฯลฯ)
|
||||
* ตรวจสอบให้แน่ใจว่าสอดคล้องกับ **ARIA** และใช้ semantic markup
|
||||
- ใช้ **semantic HTML**
|
||||
- ใช้คลาสของ **Tailwind** ที่รองรับ responsive (sm:, md:, lg:)
|
||||
- รักษาลำดับชั้นของการมองเห็น (visual hierarchy) ด้วยการใช้ typography และ spacing
|
||||
- ใช้ **Shadcn** components (Button, Input, Card, ฯลฯ) เพื่อ UI ที่สอดคล้องกัน
|
||||
- ทำให้ components มีขนาดเล็กและมุ่งเน้นการทำงานเฉพาะอย่าง
|
||||
- ใช้ utility classes สำหรับการจัดสไตล์อย่างรวดเร็ว (spacing, colors, text, ฯลฯ)
|
||||
- ตรวจสอบให้แน่ใจว่าสอดคล้องกับ **ARIA** และใช้ semantic markup
|
||||
|
||||
### **การตรวจสอบฟอร์มและข้อผิดพลาด (Form Validation & Errors)**
|
||||
|
||||
* ใช้ไลบรารีฝั่ง client เช่น zod และ react-hook-form
|
||||
* แสดงข้อผิดพลาดด้วย **alert components** หรือข้อความ inline
|
||||
* ต้องมี labels, placeholders, และข้อความ feedback
|
||||
- ใช้ไลบรารีฝั่ง client เช่น zod และ react-hook-form
|
||||
- แสดงข้อผิดพลาดด้วย **alert components** หรือข้อความ inline
|
||||
- ต้องมี labels, placeholders, และข้อความ feedback
|
||||
|
||||
### **🧪 Frontend Testing**
|
||||
|
||||
เราจะใช้ **React Testing Library (RTL)** สำหรับการทดสอบ Component และ **Playwright** สำหรับ E2E:
|
||||
|
||||
* **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
* **เครื่องมือ:** Vitest + RTL
|
||||
* **เป้าหมาย:** ทดสอบ Component ขนาดเล็ก (เช่น Buttons, Inputs) หรือ Utility functions
|
||||
* **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
* **เครื่องมือ:** RTL + **Mock Service Worker (MSW)**
|
||||
* **เป้าหมาย:** ทดสอบว่า Component หรือ Page ทำงานกับ API (ที่จำลองขึ้น) ได้ถูกต้อง
|
||||
* **เทคนิค:** ใช้ MSW เพื่อจำลอง NestJS API และทดสอบว่า Component แสดงผลข้อมูลจำลองได้ถูกต้องหรือไม่ (เช่น ทดสอบหน้า Dashboard [cite: 5.3] ที่ดึงข้อมูลจาก v_user_tasks)
|
||||
* **E2E (End-to-End) Tests:**
|
||||
* **เครื่องมือ:** **Playwright**
|
||||
* **เป้าหมาย:** ทดสอบ User Flow ทั้งระบบโดยอัตโนมัติ (เช่น ล็อกอิน -> สร้าง RFA -> ตรวจสอบ Workflow Visualization [cite: 5.6])
|
||||
- **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
- **เครื่องมือ:** Vitest + RTL
|
||||
- **เป้าหมาย:** ทดสอบ Component ขนาดเล็ก (เช่น Buttons, Inputs) หรือ Utility functions
|
||||
- **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
- **เครื่องมือ:** RTL + **Mock Service Worker (MSW)**
|
||||
- **เป้าหมาย:** ทดสอบว่า Component หรือ Page ทำงานกับ API (ที่จำลองขึ้น) ได้ถูกต้อง
|
||||
- **เทคนิค:** ใช้ MSW เพื่อจำลอง NestJS API และทดสอบว่า Component แสดงผลข้อมูลจำลองได้ถูกต้องหรือไม่ (เช่น ทดสอบหน้า Dashboard [cite: 5.3] ที่ดึงข้อมูลจาก v_user_tasks)
|
||||
- **E2E (End-to-End) Tests:**
|
||||
- **เครื่องมือ:** **Playwright**
|
||||
- **เป้าหมาย:** ทดสอบ User Flow ทั้งระบบโดยอัตโนมัติ (เช่น ล็อกอิน -> สร้าง RFA -> ตรวจสอบ Workflow Visualization [cite: 5.6])
|
||||
|
||||
### **🗄️ Frontend State Management**
|
||||
|
||||
สำหรับ Next.js App Router เราจะแบ่ง State เป็น 4 ระดับ:
|
||||
|
||||
1. **Local UI State (สถานะ UI ชั่วคราว):**
|
||||
* **เครื่องมือ:** useState, useReducer
|
||||
* **ใช้เมื่อ:** จัดการสถานะเล็กๆ ที่จบใน Component เดียว (เช่น Modal เปิด/ปิด, ค่าใน Input)
|
||||
- **เครื่องมือ:** useState, useReducer
|
||||
- **ใช้เมื่อ:** จัดการสถานะเล็กๆ ที่จบใน Component เดียว (เช่น Modal เปิด/ปิด, ค่าใน Input)
|
||||
2. **Server State (สถานะข้อมูลจากเซิร์ฟเวอร์):**
|
||||
* **เครื่องมือ:** **React Query (TanStack Query)** หรือ SWR
|
||||
* **ใช้เมื่อ:** จัดการข้อมูลที่ดึงมาจาก NestJS API (เช่น รายการ correspondences, rfas, drawings)
|
||||
* **ทำไม:** React Query เป็น "Cache" ที่จัดการ Caching, Re-fetching, และ Invalidation ให้โดยอัตโนมัติ
|
||||
- **เครื่องมือ:** **React Query (TanStack Query)** หรือ SWR
|
||||
- **ใช้เมื่อ:** จัดการข้อมูลที่ดึงมาจาก NestJS API (เช่น รายการ correspondences, rfas, drawings)
|
||||
- **ทำไม:** React Query เป็น "Cache" ที่จัดการ Caching, Re-fetching, และ Invalidation ให้โดยอัตโนมัติ
|
||||
3. **Global Client State (สถานะส่วนกลางฝั่ง Client):**
|
||||
* **เครื่องมือ:** **Zustand** (แนะนำ) หรือ Context API
|
||||
* **ใช้เมื่อ:** จัดการข้อมูลที่ต้องใช้ร่วมกันทั่วทั้งแอป และ *ไม่ใช่* ข้อมูลจากเซิร์ฟเวอร์ (เช่น ข้อมูล User ที่ล็อกอิน, สิทธิ์ Permissions)
|
||||
- **เครื่องมือ:** **Zustand** (แนะนำ) หรือ Context API
|
||||
- **ใช้เมื่อ:** จัดการข้อมูลที่ต้องใช้ร่วมกันทั่วทั้งแอป และ _ไม่ใช่_ ข้อมูลจากเซิร์ฟเวอร์ (เช่น ข้อมูล User ที่ล็อกอิน, สิทธิ์ Permissions)
|
||||
4. **Form State (สถานะของฟอร์ม):**
|
||||
* **เครื่องมือ:** **React Hook Form** + **Zod**
|
||||
* **ใช้เมื่อ:** จัดการฟอร์มที่ซับซ้อน (เช่น ฟอร์มสร้าง RFA, ฟอร์ม Circulation [cite: 3.7])
|
||||
- **เครื่องมือ:** **React Hook Form** + **Zod**
|
||||
- **ใช้เมื่อ:** จัดการฟอร์มที่ซับซ้อน (เช่น ฟอร์มสร้าง RFA, ฟอร์ม Circulation [cite: 3.7])
|
||||
|
||||
# **🔗 แนวทางการบูรณาการ Full Stack (Full Stack Integration Guidelines)**
|
||||
|
||||
| Aspect (แง่มุม) | Backend (NestJS) | Frontend (NextJS) | UI Layer (Tailwind/Shadcn) |
|
||||
| :---- | :---- | :---- | :---- |
|
||||
| API | REST / GraphQL Controllers | API hooks ผ่าน fetch/axios/SWR | Components ที่รับข้อมูล |
|
||||
| Validation (การตรวจสอบ) | class-validator DTOs | zod / react-hook-form | สถานะของฟอร์ม/input ใน Shadcn |
|
||||
| Auth (การยืนยันตัวตน) | Guards, JWT | NextAuth / cookies | สถานะ UI ของ Auth (loading, signed in) |
|
||||
| Errors (ข้อผิดพลาด) | Global filters | Toasts / modals | Alerts / ข้อความ feedback |
|
||||
| Testing (การทดสอบ) | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles (สไตล์) | Scoped modules (ถ้าจำเป็น) | Tailwind / Shadcn | Tailwind utilities |
|
||||
| Accessibility (การเข้าถึง) | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
| Aspect (แง่มุม) | Backend (NestJS) | Frontend (NextJS) | UI Layer (Tailwind/Shadcn) |
|
||||
| :------------------------- | :------------------------- | :----------------------------- | :------------------------------------- |
|
||||
| API | REST / GraphQL Controllers | API hooks ผ่าน fetch/axios/SWR | Components ที่รับข้อมูล |
|
||||
| Validation (การตรวจสอบ) | class-validator DTOs | zod / react-hook-form | สถานะของฟอร์ม/input ใน Shadcn |
|
||||
| Auth (การยืนยันตัวตน) | Guards, JWT | NextAuth / cookies | สถานะ UI ของ Auth (loading, signed in) |
|
||||
| Errors (ข้อผิดพลาด) | Global filters | Toasts / modals | Alerts / ข้อความ feedback |
|
||||
| Testing (การทดสอบ) | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles (สไตล์) | Scoped modules (ถ้าจำเป็น) | Tailwind / Shadcn | Tailwind utilities |
|
||||
| Accessibility (การเข้าถึง) | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
|
||||
# **🗂️ ข้อตกลงเฉพาะสำหรับ DMS (LCBP3-DMS)**
|
||||
|
||||
@@ -299,25 +299,25 @@ Backend (NestJS) ควรเป็น **Stateless** (ไม่เก็บส
|
||||
@RequirePermission('rfas.respond') // ต้องตรงกับ 'permission\code'
|
||||
@Put(':id')
|
||||
updateRFA(@Param('id') id: string) {
|
||||
return this.rfaService.update(id);
|
||||
return this.rfaService.update(id);
|
||||
}
|
||||
|
||||
### **Roles (บทบาท)**
|
||||
|
||||
* **Superadmin**: ไม่มีข้อจำกัดใดๆ [cite: 4.3]
|
||||
* **Admin**: มีสิทธิ์เต็มที่ในองค์กร [cite: 4.3]
|
||||
* **Document Control**: เพิ่ม/แก้ไข/ลบ เอกสารในองค์กร [cite: 4.3]
|
||||
* **Editor**: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนด [cite: 4.3]
|
||||
* **Viewer**: สามารถดู เอกสาร [cite: 4.3]
|
||||
- **Superadmin**: ไม่มีข้อจำกัดใดๆ [cite: 4.3]
|
||||
- **Admin**: มีสิทธิ์เต็มที่ในองค์กร [cite: 4.3]
|
||||
- **Document Control**: เพิ่ม/แก้ไข/ลบ เอกสารในองค์กร [cite: 4.3]
|
||||
- **Editor**: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนด [cite: 4.3]
|
||||
- **Viewer**: สามารถดู เอกสาร [cite: 4.3]
|
||||
|
||||
### **ตัวอย่าง Permissions (จากตาราง permissions)**
|
||||
|
||||
* rfas.view, rfas.create, rfas.respond, rfas.delete
|
||||
* drawings.view, drawings.upload, drawings.delete
|
||||
* corr.view, corr.manage
|
||||
* transmittals.manage
|
||||
* cirs.manage
|
||||
* project\parties.manage
|
||||
- rfas.view, rfas.create, rfas.respond, rfas.delete
|
||||
- drawings.view, drawings.upload, drawings.delete
|
||||
- corr.view, corr.manage
|
||||
- transmittals.manage
|
||||
- cirs.manage
|
||||
- project\parties.manage
|
||||
|
||||
การจับคู่ระหว่าง roles และ permissions **เริ่มต้น** จะถูก seed ผ่านสคริปต์ (ดังที่เห็นในไฟล์ SQL)**อย่างไรก็ตาม AuthModule/UserModule ต้องมี API สำหรับ Admin เพื่อสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลัง** [cite: 4.3]
|
||||
|
||||
@@ -325,33 +325,33 @@ updateRFA(@Param('id') id: string) {
|
||||
|
||||
บันทึกการดำเนินการ CRUD และการจับคู่ทั้งหมดลงในตาราง audit_logs
|
||||
|
||||
| Field (ฟิลด์) | Type (จาก SQL) | Description (คำอธิบาย) |
|
||||
| :---- | :---- | :---- |
|
||||
| audit_id | BIGINT | Primary Key |
|
||||
| user_id | INT | ผู้ใช้ที่ดำเนินการ (FK -> users) |
|
||||
| action | VARCHAR(100) | rfa.create, correspondence.update, login.success |
|
||||
| entity_type | VARCHAR(50) | ชื่อตาราง/โมดูล เช่น 'rfa', 'correspondence' |
|
||||
| entity_id | VARCHAR(50) | Primary ID ของระเบียนที่ได้รับผลกระทบ |
|
||||
| details_json | JSON | ข้อมูลบริบท (เช่น ฟิลด์ที่มีการเปลี่ยนแปลง) |
|
||||
| ip_address | VARCHAR(45) | IP address ของผู้ดำเนินการ |
|
||||
| user_agent | VARCHAR(255) | User Agent ของผู้ดำเนินการ |
|
||||
| created_at | TIMESTAMP | Timestamp (UTC) |
|
||||
| Field (ฟิลด์) | Type (จาก SQL) | Description (คำอธิบาย) |
|
||||
| :------------ | :------------- | :----------------------------------------------- |
|
||||
| audit_id | BIGINT | Primary Key |
|
||||
| user_id | INT | ผู้ใช้ที่ดำเนินการ (FK -> users) |
|
||||
| action | VARCHAR(100) | rfa.create, correspondence.update, login.success |
|
||||
| entity_type | VARCHAR(50) | ชื่อตาราง/โมดูล เช่น 'rfa', 'correspondence' |
|
||||
| entity_id | VARCHAR(50) | Primary ID ของระเบียนที่ได้รับผลกระทบ |
|
||||
| details_json | JSON | ข้อมูลบริบท (เช่น ฟิลด์ที่มีการเปลี่ยนแปลง) |
|
||||
| ip_address | VARCHAR(45) | IP address ของผู้ดำเนินการ |
|
||||
| user_agent | VARCHAR(255) | User Agent ของผู้ดำเนินการ |
|
||||
| created_at | TIMESTAMP | Timestamp (UTC) |
|
||||
|
||||
## **📂 การจัดการไฟล์ (File Handling) (ปรับปรุงใหม่)**
|
||||
|
||||
### **มาตรฐานการอัปโหลดไฟล์ (File Upload Standard)**
|
||||
|
||||
* **ตรรกะใหม่:** การอัปโหลดไฟล์ทั้งหมดจะถูกจัดการโดย FileStorageService และบันทึกข้อมูลไฟล์ลงในตาราง attachments (ตารางกลาง)
|
||||
* ไฟล์จะถูกเชื่อมโยงไปยัง Entity ที่ถูกต้องผ่าน **ตารางเชื่อม (Junction Tables)** เท่านั้น:
|
||||
* correspondence_attachments (เชื่อม Correspondence กับ Attachments)
|
||||
* circulation_attachments (เชื่อม Circulation กับ Attachments)
|
||||
* shop_drawing_revision_attachments (เชื่อม Shop Drawing Revision กับ Attachments)
|
||||
* contract_drawing_attachments (เชื่อม Contract Drawing กับ Attachments)
|
||||
* เส้นทางจัดเก็บไฟล์ (Upload path): อ้างอิงจาก Requirement 2.1 คือ /share/dms-data [cite: 2.1] โดย FileStorageService จะสร้างโฟลเดอร์ย่อยแบบรวมศูนย์ (เช่น /share/dms-data/uploads/{YYYY}/{MM}/[stored\filename])
|
||||
* ประเภทไฟล์ที่อนุญาต: pdf, dwg, docx, xlsx, zip
|
||||
* ขนาดสูงสุด: **50 MB**
|
||||
* จัดเก็บนอก webroot
|
||||
* ให้บริการไฟล์ผ่าน endpoint ที่ปลอดภัย /files/:attachment_id/download
|
||||
- **ตรรกะใหม่:** การอัปโหลดไฟล์ทั้งหมดจะถูกจัดการโดย FileStorageService และบันทึกข้อมูลไฟล์ลงในตาราง attachments (ตารางกลาง)
|
||||
- ไฟล์จะถูกเชื่อมโยงไปยัง Entity ที่ถูกต้องผ่าน **ตารางเชื่อม (Junction Tables)** เท่านั้น:
|
||||
- correspondence_attachments (เชื่อม Correspondence กับ Attachments)
|
||||
- circulation_attachments (เชื่อม Circulation กับ Attachments)
|
||||
- shop_drawing_revision_attachments (เชื่อม Shop Drawing Revision กับ Attachments)
|
||||
- contract_drawing_attachments (เชื่อม Contract Drawing กับ Attachments)
|
||||
- เส้นทางจัดเก็บไฟล์ (Upload path): อ้างอิงจาก Requirement 2.1 คือ /share/dms-data [cite: 2.1] โดย FileStorageService จะสร้างโฟลเดอร์ย่อยแบบรวมศูนย์ (เช่น /share/dms-data/uploads/{YYYY}/{MM}/[stored\filename])
|
||||
- ประเภทไฟล์ที่อนุญาต: pdf, dwg, docx, xlsx, zip
|
||||
- ขนาดสูงสุด: **50 MB**
|
||||
- จัดเก็บนอก webroot
|
||||
- ให้บริการไฟล์ผ่าน endpoint ที่ปลอดภัย /files/:attachment_id/download
|
||||
|
||||
### **การควบคุมการเข้าถึง (Access Control)**
|
||||
|
||||
@@ -363,15 +363,15 @@ updateRFA(@Param('id') id: string) {
|
||||
|
||||
## **🔟 การจัดการเลขที่เอกสาร (Document Numbering) [cite: 3.10]**
|
||||
|
||||
* **เป้าหมาย:** สร้างเลขที่เอกสาร (เช่น correspondence\number) โดยอัตโนมัติ ตามรูปแบบที่กำหนด
|
||||
* **ตรรกะการนับ:** การนับ Running number (SEQ) จะนับแยกตาม Key: **Project + Originator Organization + Document Type + Year**
|
||||
* **ตาราง SQL:**
|
||||
* document_number_formats: Admin ใช้กำหนด "รูปแบบ" (Template) ของเลขที่ (เช่น {ORG\CODE}-{TYPE\CODE}-{YEAR\SHORT}-{SEQ:4}) โดยกำหนดตาม **Project** และ **Document Type** [cite: 4.5]
|
||||
* document_number_counters: ระบบใช้เก็บ "ตัวนับ" ล่าสุดของ Key (Project+Org+Type+Year)
|
||||
* **การทำงาน (Backend):**
|
||||
* DocumentNumberingModule จะให้บริการ DocumentNumberingService
|
||||
* เมื่อ CorrespondenceModule ต้องการสร้างเอกสารใหม่, มันจะเรียก documentNumberingService.generateNextNumber(...)
|
||||
* Service นี้จะเรียกใช้ Stored Procedure **sp_get_next_document_number** [cite: 2.9.3] ซึ่ง Procedure นี้จะจัดการ Database Transaction และ Row Lock (FOR UPDATE) ภายใน DB เพื่อรับประกันการป้องกัน Race Condition
|
||||
- **เป้าหมาย:** สร้างเลขที่เอกสาร (เช่น correspondence\number) โดยอัตโนมัติ ตามรูปแบบที่กำหนด
|
||||
- **ตรรกะการนับ:** การนับ Running number (SEQ) จะนับแยกตาม Key: **Project + Originator Organization + Document Type + Year**
|
||||
- **ตาราง SQL:**
|
||||
- document_number_formats: Admin ใช้กำหนด "รูปแบบ" (Template) ของเลขที่ (เช่น {ORG\CODE}-{TYPE\CODE}-{YEAR\SHORT}-{SEQ:4}) โดยกำหนดตาม **Project** และ **Document Type** [cite: 4.5]
|
||||
- document_number_counters: ระบบใช้เก็บ "ตัวนับ" ล่าสุดของ Key (Project+Org+Type+Year)
|
||||
- **การทำงาน (Backend):**
|
||||
- DocumentNumberingModule จะให้บริการ DocumentNumberingService
|
||||
- เมื่อ CorrespondenceModule ต้องการสร้างเอกสารใหม่, มันจะเรียก documentNumberingService.generateNextNumber(...)
|
||||
- Service นี้จะเรียกใช้ Stored Procedure **sp_get_next_document_number** [cite: 2.9.3] ซึ่ง Procedure นี้จะจัดการ Database Transaction และ Row Lock (FOR UPDATE) ภายใน DB เพื่อรับประกันการป้องกัน Race Condition
|
||||
|
||||
## **📊 การรายงานและการส่งออก (Reporting & Exports)**
|
||||
|
||||
@@ -379,81 +379,81 @@ updateRFA(@Param('id') id: string) {
|
||||
|
||||
การรายงานควรสร้างขึ้นจาก Views ที่กำหนดไว้ล่วงหน้าในฐานข้อมูลเป็นหลัก:
|
||||
|
||||
* v_current_correspondences: สำหรับ revision ปัจจุบันทั้งหมดของเอกสารที่ไม่ใช่ RFA
|
||||
* v_current_rfas: สำหรับ revision ปัจจุบันทั้งหมดของ RFA และข้อมูล master
|
||||
* v_contract_parties_all: สำหรับการตรวจสอบความสัมพันธ์ของ project/contract/organization
|
||||
* v_user_tasks: สำหรับ Dashboard "งานของฉัน"
|
||||
* v_audit_log_details: สำหรับ Activity Feed
|
||||
- v_current_correspondences: สำหรับ revision ปัจจุบันทั้งหมดของเอกสารที่ไม่ใช่ RFA
|
||||
- v_current_rfas: สำหรับ revision ปัจจุบันทั้งหมดของ RFA และข้อมูล master
|
||||
- v_contract_parties_all: สำหรับการตรวจสอบความสัมพันธ์ของ project/contract/organization
|
||||
- v_user_tasks: สำหรับ Dashboard "งานของฉัน"
|
||||
- v_audit_log_details: สำหรับ Activity Feed
|
||||
|
||||
Views เหล่านี้ทำหน้าที่เป็นแหล่งข้อมูลหลักสำหรับการรายงานฝั่งเซิร์ฟเวอร์และการส่งออกข้อมูล
|
||||
|
||||
### **กฎการส่งออก (Export Rules)**
|
||||
|
||||
* Export formats: CSV, Excel, PDF.
|
||||
* จัดเตรียมมุมมองสำหรับพิมพ์ (Print view).
|
||||
* รวมลิงก์ไปยังต้นทาง (เช่น /rfas/:id).
|
||||
- Export formats: CSV, Excel, PDF.
|
||||
- จัดเตรียมมุมมองสำหรับพิมพ์ (Print view).
|
||||
- รวมลิงก์ไปยังต้นทาง (เช่น /rfas/:id).
|
||||
|
||||
## **🧮 ฟรอนต์เอนด์: รูปแบบ DataTable และฟอร์ม (Frontend: DataTable & Form Patterns)**
|
||||
|
||||
### **DataTable (Server‑Side)**
|
||||
|
||||
* Endpoint: /api/{module}?page=1\&pageSize=20\&sort=...\&filter=...
|
||||
* ต้องรองรับ: การแบ่งหน้า (pagination), การเรียงลำดับ (sorting), การค้นหา (search), การกรอง (filters)
|
||||
* แสดง revision ล่าสุดแบบ inline เสมอ (สำหรับ RFA/Drawing)
|
||||
- Endpoint: /api/{module}?page=1\&pageSize=20\&sort=...\&filter=...
|
||||
- ต้องรองรับ: การแบ่งหน้า (pagination), การเรียงลำดับ (sorting), การค้นหา (search), การกรอง (filters)
|
||||
- แสดง revision ล่าสุดแบบ inline เสมอ (สำหรับ RFA/Drawing)
|
||||
|
||||
### **มาตรฐานฟอร์ม (Form Standards)**
|
||||
|
||||
* ต้องมีการใช้งาน Dropdowns แบบขึ้นต่อกัน (Dependent dropdowns) (ตามที่สคีมารองรับ):
|
||||
* Project → Contract Drawing Volumes
|
||||
* Contract Drawing Category → Sub-Category
|
||||
* RFA (ประเภท Shop Drawing) → Shop Drawing Revisions ที่เชื่อมโยงได้
|
||||
* **(ใหม่)** การอัปโหลดไฟล์: ต้องรองรับ **Multi-file upload (Drag-and-Drop)** [cite: 5.7]
|
||||
* **(ใหม่)** UI ต้องอนุญาตให้ผู้ใช้กำหนดว่าไฟล์ใดเป็น **"เอกสารหลัก"** หรือ "เอกสารแนบประกอบ" [cite: 5.7]
|
||||
* ส่ง (Submit) ผ่าน API พร้อม feedback แบบ toast
|
||||
- ต้องมีการใช้งาน Dropdowns แบบขึ้นต่อกัน (Dependent dropdowns) (ตามที่สคีมารองรับ):
|
||||
- Project → Contract Drawing Volumes
|
||||
- Contract Drawing Category → Sub-Category
|
||||
- RFA (ประเภท Shop Drawing) → Shop Drawing Revisions ที่เชื่อมโยงได้
|
||||
- **(ใหม่)** การอัปโหลดไฟล์: ต้องรองรับ **Multi-file upload (Drag-and-Drop)** [cite: 5.7]
|
||||
- **(ใหม่)** UI ต้องอนุญาตให้ผู้ใช้กำหนดว่าไฟล์ใดเป็น **"เอกสารหลัก"** หรือ "เอกสารแนบประกอบ" [cite: 5.7]
|
||||
- ส่ง (Submit) ผ่าน API พร้อม feedback แบบ toast
|
||||
|
||||
### **ข้อกำหนด Component เฉพาะ (Specific UI Requirements)**
|
||||
|
||||
* **Dashboard \- My Tasks:** ต้องพัฒนา Component ตาราง "งานของฉัน" (My Tasks)ซึ่งดึงข้อมูลงานที่ผู้ใช้ล็อกอินอยู่ต้องรับผิดชอบ (Main/Action) จาก v\user\tasks [cite: 5.3]
|
||||
* **Workflow Visualization:** ต้องพัฒนา Component สำหรับแสดงผล Workflow (โดยเฉพาะ RFA)ที่แสดงขั้นตอนทั้งหมดเป็นลำดับ โดยขั้นตอนปัจจุบัน (active) เท่านั้นที่ดำเนินการได้ และขั้นตอนอื่นเป็น disabled [cite: 5.6] ต้องมีตรรกะสำหรับ Admin ในการ override หรือย้อนกลับขั้นตอนได้ [cite: 5.6]
|
||||
* ** Admin Panel:** ต้องมีหน้า UI สำหรับ Superadmin/Admin เพื่อจัดการข้อมูลหลัก (Master Data [cite: 4.5]), การเริ่มต้นใช้งาน (Onboarding [cite: 4.6]), และ **รูปแบบเลขที่เอกสาร (Numbering Formats [cite: 3.10])**
|
||||
- **Dashboard \- My Tasks:** ต้องพัฒนา Component ตาราง "งานของฉัน" (My Tasks)ซึ่งดึงข้อมูลงานที่ผู้ใช้ล็อกอินอยู่ต้องรับผิดชอบ (Main/Action) จาก v\user\tasks [cite: 5.3]
|
||||
- **Workflow Visualization:** ต้องพัฒนา Component สำหรับแสดงผล Workflow (โดยเฉพาะ RFA)ที่แสดงขั้นตอนทั้งหมดเป็นลำดับ โดยขั้นตอนปัจจุบัน (active) เท่านั้นที่ดำเนินการได้ และขั้นตอนอื่นเป็น disabled [cite: 5.6] ต้องมีตรรกะสำหรับ Admin ในการ override หรือย้อนกลับขั้นตอนได้ [cite: 5.6]
|
||||
- ** Admin Panel:** ต้องมีหน้า UI สำหรับ Superadmin/Admin เพื่อจัดการข้อมูลหลัก (Master Data [cite: 4.5]), การเริ่มต้นใช้งาน (Onboarding [cite: 4.6]), และ **รูปแบบเลขที่เอกสาร (Numbering Formats [cite: 3.10])**
|
||||
|
||||
## **🧭 แดชบอร์ดและฟีดกิจกรรม (Dashboard & Activity Feed)**
|
||||
|
||||
### **การ์ดบนแดชบอร์ด (Dashboard Cards)**
|
||||
|
||||
* แสดง Correspondences, RFAs, Circulations, Shop Drawing Revision ล่าสุด
|
||||
* รวมสรุป KPI (เช่น "RFAs ที่รอการอนุมัติ", "Shop Drawing ที่รอการอนุมัติ") [cite: 5.3]
|
||||
* รวมลิงก์ด่วนไปยังโมดูลต่างๆ
|
||||
- แสดง Correspondences, RFAs, Circulations, Shop Drawing Revision ล่าสุด
|
||||
- รวมสรุป KPI (เช่น "RFAs ที่รอการอนุมัติ", "Shop Drawing ที่รอการอนุมัติ") [cite: 5.3]
|
||||
- รวมลิงก์ด่วนไปยังโมดูลต่างๆ
|
||||
|
||||
### **ฟีดกิจกรรม (Activity Feed)**
|
||||
|
||||
* แสดงรายการ v\audit\log\details ล่าสุด (10 รายการ) ที่เกี่ยวข้องกับผู้ใช้
|
||||
- แสดงรายการ v\audit\log\details ล่าสุด (10 รายการ) ที่เกี่ยวข้องกับผู้ใช้
|
||||
|
||||
// ตัวอย่าง API response
|
||||
[
|
||||
{ user: 'editor01', action: 'Updated RFA (LCBP3-RFA-001)', time: '2025-11-04T09:30Z' }
|
||||
[
|
||||
{ user: 'editor01', action: 'Updated RFA (LCBP3-RFA-001)', time: '2025-11-04T09:30Z' }
|
||||
]
|
||||
|
||||
## **🛡️ ข้อกำหนดที่ไม่ใช่ฟังก์ชันการทำงาน (Non-Functional Requirements)**
|
||||
|
||||
ส่วนนี้สรุปข้อกำหนด Non-Functional จาก requirements.md เพื่อให้ทีมพัฒนาทราบ
|
||||
|
||||
* **Audit Log [cite: 6.1]:** ทุกการกระทำที่สำคัญ (C/U/D) ต้องถูกบันทึกใน audit_logs
|
||||
* **Performance [cite: 6.4]:** ต้องใช้ Caching สำหรับข้อมูลที่เรียกบ่อย และใช้ Pagination
|
||||
* **Security [cite: 6.5]:** ต้องมี Rate Limiting และจัดการ Secret ผ่าน docker-compose.yml (ไม่ใช่ .env)
|
||||
* **(ใหม่) Backup & Recovery [cite: 6.6]:** ต้องมีแผนสำรองข้อมูลทั้ง Database (MariaDB) และ File Storage (/share/dms-data) อย่างน้อยวันละ 1 ครั้ง
|
||||
* **(ใหม่) Notification Strategy [cite: 6.7]:** ระบบแจ้งเตือน (Email/Line) ต้องถูก Trigger เมื่อมีเอกสารใหม่ส่งถึง, มีการมอบหมายงานใหม่ (Circulation), หรือ (ทางเลือก) เมื่องานเสร็จ/ใกล้ถึงกำหนด
|
||||
- **Audit Log [cite: 6.1]:** ทุกการกระทำที่สำคัญ (C/U/D) ต้องถูกบันทึกใน audit_logs
|
||||
- **Performance [cite: 6.4]:** ต้องใช้ Caching สำหรับข้อมูลที่เรียกบ่อย และใช้ Pagination
|
||||
- **Security [cite: 6.5]:** ต้องมี Rate Limiting และจัดการ Secret ผ่าน docker-compose.yml (ไม่ใช่ .env)
|
||||
- **(ใหม่) Backup & Recovery [cite: 6.6]:** ต้องมีแผนสำรองข้อมูลทั้ง Database (MariaDB) และ File Storage (/share/dms-data) อย่างน้อยวันละ 1 ครั้ง
|
||||
- **(ใหม่) Notification Strategy [cite: 6.7]:** ระบบแจ้งเตือน (Email/Line) ต้องถูก Trigger เมื่อมีเอกสารใหม่ส่งถึง, มีการมอบหมายงานใหม่ (Circulation), หรือ (ทางเลือก) เมื่องานเสร็จ/ใกล้ถึงกำหนด
|
||||
|
||||
## **✅ มาตรฐานที่นำไปใช้แล้ว (จาก SQL v1.1.0) (Implemented Standards (from SQL v1.1.0))**
|
||||
|
||||
ส่วนนี้ยืนยันว่าแนวทางปฏิบัติที่ดีที่สุดต่อไปนี้เป็นส่วนหนึ่งของการออกแบบฐานข้อมูลอยู่แล้ว และควรถูกนำไปใช้ประโยชน์ ไม่ใช่สร้างขึ้นใหม่
|
||||
|
||||
* ✅ **Soft Delete:** นำไปใช้แล้วผ่านคอลัมน์ deleted_at ในตารางสำคัญ (เช่น correspondences, rfas, project_parties) ตรรกะการดึงข้อมูลต้องกรอง deleted_at IS NULL
|
||||
* ✅ **Database Indexes:** สคีมาได้มีการทำ index ไว้อย่างหนักหน่วงบน foreign keys และคอลัมน์ที่ใช้ค้นหาบ่อย (เช่น idx_rr_rfa, idx_cor_project, idx_cr_is_current) เพื่อประสิทธิภาพ
|
||||
* ✅ **โครงสร้าง RBAC:** มีระบบ users, roles, permissions, user_roles, และ user_project_roles ที่ครอบคลุมอยู่แล้ว
|
||||
* ✅ **Data Seeding:** ข้อมูล Master (roles, permissions, organization_roles, initial users, project parties) ถูกรวมอยู่ในสคริปต์สคีมาแล้ว
|
||||
- ✅ **Soft Delete:** นำไปใช้แล้วผ่านคอลัมน์ deleted_at ในตารางสำคัญ (เช่น correspondences, rfas, project_parties) ตรรกะการดึงข้อมูลต้องกรอง deleted_at IS NULL
|
||||
- ✅ **Database Indexes:** สคีมาได้มีการทำ index ไว้อย่างหนักหน่วงบน foreign keys และคอลัมน์ที่ใช้ค้นหาบ่อย (เช่น idx_rr_rfa, idx_cor_project, idx_cr_is_current) เพื่อประสิทธิภาพ
|
||||
- ✅ **โครงสร้าง RBAC:** มีระบบ users, roles, permissions, user_roles, และ user_project_roles ที่ครอบคลุมอยู่แล้ว
|
||||
- ✅ **Data Seeding:** ข้อมูล Master (roles, permissions, organization_roles, initial users, project parties) ถูกรวมอยู่ในสคริปต์สคีมาแล้ว
|
||||
|
||||
## **🧩 การปรับปรุงที่แนะนำ (สำหรับอนาคต) (Recommended Enhancements (Future))**
|
||||
|
||||
* ✅ สร้าง Background job (โดยใช้ **n8n** เพื่อเชื่อมต่อกับ **Line** [cite: 2.7] และ/หรือใช้สำหรับการแจ้งเตือน RFA ที่ใกล้ถึงกำหนด due_date [cite: 6.7])
|
||||
* ✅ เพิ่ม job ล้างข้อมูลเป็นระยะสำหรับ attachments ที่ไม่ถูกเชื่อมโยงกับ Entity ใดๆ เลย (ไฟล์กำพร้า)
|
||||
- ✅ สร้าง Background job (โดยใช้ **n8n** เพื่อเชื่อมต่อกับ **Line** [cite: 2.7] และ/หรือใช้สำหรับการแจ้งเตือน RFA ที่ใกล้ถึงกำหนด due_date [cite: 6.7])
|
||||
- ✅ เพิ่ม job ล้างข้อมูลเป็นระยะสำหรับ attachments ที่ไม่ถูกเชื่อมโยงกับ Entity ใดๆ เลย (ไฟล์กำพร้า)
|
||||
|
||||
@@ -4,207 +4,207 @@
|
||||
|
||||
สร้างเว็บแอปพลิเคชั่นสำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System)ที่สามารถจัดการและควบคุม การสื่อสารด้วยเอกสารที่ซับซ้อน อย่างมีประสิทธิภาพ
|
||||
|
||||
* มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
* ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
* เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
- มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
- ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
- เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
|
||||
## **🛠️ 2. สถาปัตยกรรมและเทคโนโลยี (System Architecture & Technology Stack)**
|
||||
|
||||
ใช้สถาปัตยกรรมแบบ Headless/API-First ที่ทันสมัย ทำงานทั้งหมดบน QNAP Server ผ่าน Container Station เพื่อความสะดวกในการจัดการและบำรุงรักษา, Domain: np-dms.work, มี fix ip, รัน docker command ใน application ของ Container Station ได้โดยตรง, ประกอบด้วย
|
||||
|
||||
* 2.1. Infrastructure & Environment:
|
||||
* Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
* Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
|
||||
* Development Environment: VS Code on Windows 11
|
||||
* Domain: np-dms.work, www.np-dms.work
|
||||
* ip: 159.192.126.103
|
||||
* Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
* Data Storage: /share/dms-data บน QNAP
|
||||
* ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
* 2.2. Code Hosting:
|
||||
* Application name: git
|
||||
* Service: Gitea (Self-hosted on QNAP)
|
||||
* Service name: gitea
|
||||
* Domain: git.np-dms.work
|
||||
* หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
|
||||
* 2.3. Backend / Data Platform:
|
||||
* Application name: lcbp3-backend
|
||||
* Service: NestJS
|
||||
* Service name: backend
|
||||
* Domain: backend.np-dms.work
|
||||
* Framework: NestJS (Node.js, TypeScript, ESM)
|
||||
* หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
|
||||
* 2.4. Database:
|
||||
* Application name: lcbp3-db
|
||||
* Service: mariadb:10.11
|
||||
* Service name: mariadb
|
||||
* Domain: db.np-dms.work
|
||||
* หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
|
||||
* Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
|
||||
* 2.5. Database management:
|
||||
* Application name: lcbp3-db
|
||||
* Service: phpmyadmin:5-apache
|
||||
* Service name: pma
|
||||
* Domain: pma.np-dms.work
|
||||
* หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
|
||||
* 2.6. Frontend:
|
||||
* Application name: lcbp3-frontend
|
||||
* Service: next.js
|
||||
* Service name: frontend
|
||||
* Domain: lcbp3.np-dms.work
|
||||
* Framework: Next.js (App Router, React, TypeScript, ESM)
|
||||
* Styling: Tailwind CSS + PostCSS
|
||||
* Component Library: shadcn/ui
|
||||
* หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
|
||||
* 2.7. Workflow automation:
|
||||
* Application name: lcbp3-n8n
|
||||
* Service: n8nio/n8n:latest
|
||||
* Service name: n8n
|
||||
* Domain: n8n.np-dms.work
|
||||
* หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
|
||||
* 2.8. Reverse Proxy:
|
||||
* Application name: lcbp3-npm
|
||||
* Service: Nginx Proxy Manager (nginx-proxy-manage: latest)
|
||||
* Service name: npm
|
||||
* Domain: npm.np-dms.work
|
||||
* หน้าที่: เป็นด่านหน้าในการรับ-ส่งข้อมูล จัดการโดเมนทั้งหมด, ทำหน้าที่เป็น Proxy ชี้ไปยัง Service ที่ถูกต้อง, และจัดการ SSL Certificate (HTTPS) ให้อัตโนมัติ
|
||||
* **2.9. การจัดการตรรกะทางธุรกิจ (Business Logic Implementation):**
|
||||
* 2.9.1. ตรรกะทางธุรกิจที่ซับซ้อนทั้งหมด (เช่น การเปลี่ยนสถานะ Workflow [cite: 3.5.4, 3.6.5], การบังคับใช้สิทธิ์ [cite: 4.4], การตรวจสอบ Deadline [cite: 3.2.5]) **จะถูกจัดการในฝั่ง Backend (NestJS)** [cite: 2.3] เพื่อให้สามารถบำรุงรักษาและทดสอบได้ง่าย (Testability)
|
||||
* 2.9.2. **จะไม่มีการใช้ SQL Triggers** เพื่อป้องกันตรรกะซ่อนเร้น (Hidden Logic) และความซับซ้อนในการดีบัก
|
||||
* 2.9.3. **ข้อยกเว้น:** ตรรกะเดียวที่จะอยู่ในฐานข้อมูลคือ **Stored Procedure** สำหรับการสร้างเลขที่เอกสาร (Document Numbering) [cite: 3.10] เพื่อป้องกันการซ้ำซ้อนของข้อมูล (Race Condition)
|
||||
- 2.1. Infrastructure & Environment:
|
||||
- Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
- Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
|
||||
- Development Environment: VS Code on Windows 11
|
||||
- Domain: np-dms.work, www.np-dms.work
|
||||
- ip: 159.192.126.103
|
||||
- Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
- Data Storage: /share/dms-data บน QNAP
|
||||
- ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
- 2.2. Code Hosting:
|
||||
- Application name: git
|
||||
- Service: Gitea (Self-hosted on QNAP)
|
||||
- Service name: gitea
|
||||
- Domain: git.np-dms.work
|
||||
- หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
|
||||
- 2.3. Backend / Data Platform:
|
||||
- Application name: lcbp3-backend
|
||||
- Service: NestJS
|
||||
- Service name: backend
|
||||
- Domain: backend.np-dms.work
|
||||
- Framework: NestJS (Node.js, TypeScript, ESM)
|
||||
- หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
|
||||
- 2.4. Database:
|
||||
- Application name: lcbp3-db
|
||||
- Service: mariadb:10.11
|
||||
- Service name: mariadb
|
||||
- Domain: db.np-dms.work
|
||||
- หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
|
||||
- Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
|
||||
- 2.5. Database management:
|
||||
- Application name: lcbp3-db
|
||||
- Service: phpmyadmin:5-apache
|
||||
- Service name: pma
|
||||
- Domain: pma.np-dms.work
|
||||
- หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
|
||||
- 2.6. Frontend:
|
||||
- Application name: lcbp3-frontend
|
||||
- Service: next.js
|
||||
- Service name: frontend
|
||||
- Domain: lcbp3.np-dms.work
|
||||
- Framework: Next.js (App Router, React, TypeScript, ESM)
|
||||
- Styling: Tailwind CSS + PostCSS
|
||||
- Component Library: shadcn/ui
|
||||
- หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
|
||||
- 2.7. Workflow automation:
|
||||
- Application name: lcbp3-n8n
|
||||
- Service: n8nio/n8n:latest
|
||||
- Service name: n8n
|
||||
- Domain: n8n.np-dms.work
|
||||
- หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
|
||||
- 2.8. Reverse Proxy:
|
||||
- Application name: lcbp3-npm
|
||||
- Service: Nginx Proxy Manager (nginx-proxy-manage: latest)
|
||||
- Service name: npm
|
||||
- Domain: npm.np-dms.work
|
||||
- หน้าที่: เป็นด่านหน้าในการรับ-ส่งข้อมูล จัดการโดเมนทั้งหมด, ทำหน้าที่เป็น Proxy ชี้ไปยัง Service ที่ถูกต้อง, และจัดการ SSL Certificate (HTTPS) ให้อัตโนมัติ
|
||||
- **2.9. การจัดการตรรกะทางธุรกิจ (Business Logic Implementation):**
|
||||
- 2.9.1. ตรรกะทางธุรกิจที่ซับซ้อนทั้งหมด (เช่น การเปลี่ยนสถานะ Workflow [cite: 3.5.4, 3.6.5], การบังคับใช้สิทธิ์ [cite: 4.4], การตรวจสอบ Deadline [cite: 3.2.5]) **จะถูกจัดการในฝั่ง Backend (NestJS)** [cite: 2.3] เพื่อให้สามารถบำรุงรักษาและทดสอบได้ง่าย (Testability)
|
||||
- 2.9.2. **จะไม่มีการใช้ SQL Triggers** เพื่อป้องกันตรรกะซ่อนเร้น (Hidden Logic) และความซับซ้อนในการดีบัก
|
||||
- 2.9.3. **ข้อยกเว้น:** ตรรกะเดียวที่จะอยู่ในฐานข้อมูลคือ **Stored Procedure** สำหรับการสร้างเลขที่เอกสาร (Document Numbering) [cite: 3.10] เพื่อป้องกันการซ้ำซ้อนของข้อมูล (Race Condition)
|
||||
|
||||
## **📦 3. ข้อกำหนดด้านฟังก์ชันการทำงาน (Functional Requirements)**
|
||||
|
||||
* 3.1. การจัดการโครงสร้างโครงการและองค์กร
|
||||
* 3.1.1. โครงการ (Projects): ระบบต้องสามารถจัดการเอกสารภายในหลายโครงการได้ (ปัจจุบันมี 4 โครงการ และจะเพิ่มขึ้นในอนาคต)
|
||||
* 3.1.2. สัญญา (Contracts): ระบบต้องสามารถจัดการเอกสารภายในแต่ละสัญญาได้ ในแต่ละโครงการ มีได้หลายสัญญา หรืออย่างน้อย 1 สัญญา
|
||||
* 3.1.3. องค์กร (Organizations):
|
||||
* มีหลายองค์กรในโครงการ องค์กรณ์ที่เป็น Owner, Designer และ Consultant สามารถอยู่ในหลายโครงการและหลายสัญญาได้
|
||||
* Contractor จะถือ 1 สัญญา และอยู่ใน 1 โครงการเท่านั้น
|
||||
* 3.2. การจัดการเอกสารโต้ตอบ (Correspondence Management)
|
||||
* 3.2.1. วัตถุประสงค์: เอกสารโต้ตอบ (correspondences) ระหว่างองกรณื-องกรณ์ ภายใน โครงการ (Projects) และระหว่าง องค์กร-องค์กร ภายนอก โครงการ (Projects), รองรับ To (ผู้รับหลัก) และ CC (ผู้รับสำเนา) หลายองค์กร
|
||||
* 3.2.2. ประเภทเอกสาร: ระบบต้องรองรับเอกสารรูปแบบ ไฟล์ PDF หลายประเภท (Types) เช่น จดหมาย (Letter), อีเมล์ (Email), Request for Information (RFI), และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
|
||||
* 3.2.3. การสร้างเอกสาร (Correspondence):
|
||||
* ผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารรอไว้ในสถานะ ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
|
||||
* เมื่อกด "Submitted" แล้ว การแก้ไข, ถอนเอกสารกลับไปสถานะ Draft, หรือยกเลิก (Cancel) จะต้องทำโดยผู้ใช้ระดับ Admin ขึ้นไป พร้อมระบุเหตุผล
|
||||
* 3.2.4. การอ้างอิงและจัดกลุ่ม:
|
||||
* เอกสารสามารถอ้างถึง (Reference) เอกสารฉบับก่อนหน้าได้หลายฉบับ
|
||||
* สามารถกำหนด Tag ได้หลาย Tag เพื่อจัดกลุ่มและใช้ในการค้นหาขั้นสูง
|
||||
* 3.2.5. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
* สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่เป็นผู้รับได้
|
||||
* มีระบบแจ้งเตือน ให้ผู้รับผิดชอบขององกรณ์ที่เป็น ผู้รับ/ผู้ส่ง ทราบ เมื่อมีเอกสารใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
* 3.3. การจัดกาแบบคู่สัญญา (Contract Drawing)
|
||||
* 3.3.1. วัตถุประสงค์: แบบคู่สัญญา (Contract Drawing) ใช้เพื่ออ้างอิงและใช้ในการตรวจสอบ
|
||||
* 3.3.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
* 3.3.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
* 3.3.4. การอ้างอิงและจัดกลุ่ม: ใช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Contract Drawing
|
||||
* 3.4. การจัดกาแบบก่อสร้าง (Shop Drawing)
|
||||
* 3.4.1. วัตถุประสงค์: แบบก่อสร้าง (Shop Drawing) ใช้เในการตรวจสอบ โดยจัดส่งด้วย Request for Approval (RFA)
|
||||
* 3.4.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
* 3.4.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
* 3.4.4. การอ้างอิงและจัดกลุ่ม: ช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Shop Drawings
|
||||
* 3.5. การจัดการเอกสารขออนุมัติ (Request for Approval & Workflow)
|
||||
* 3.5.1. วัตถุประสงค์: เอกสารขออนุมัติ (Request for Approval) ใช้ในการส่งเอกสารเพิอขออนุมัติ
|
||||
* 3.5.2. ประเภทเอกสาร: Request for Approval (RFA) เป็นชนิดหนึ่งของ Correspondence ที่มีลักษณะเฉพาะที่ต้องได้รับการอนุมัติ มีประเภทดังนี้:
|
||||
* Request for Drawing Approval (RFA_DWG)
|
||||
* Request for Document Approval (RFA_DOC)
|
||||
* Request for Method statement Approval (RFA_MES)
|
||||
* Request for Material Approval (RFA_MAT)
|
||||
* 3.5.2. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
* 3.5.4. การอ้างอิงและจัดกลุ่ม: การจัดการ Drawing (RFA_DWG):
|
||||
* เอกสาร RFA_DWG จะประกอบไปด้วย Shop Drawing (shop_drawings) หลายแผ่น ซึ่งแต่ละแผ่นมี Revision ของตัวเอง
|
||||
* Shop Drawing แต่ละ Revision สามารถอ้างอิงถึง Contract Drawing (Ccontract_drawings) หลายแผ่น หรือไม่อ้างถึงก็ได้
|
||||
* ระบบต้องมีส่วนสำหรับจัดการข้อมูล Master Data ของทั้ง Shop Drawing และ Contract Drawing แยกจากกัน
|
||||
* 3.6.5. Workflow การอนุมัติ: ต้องรองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น
|
||||
* ส่งจาก Originator -> Organization 1 -> Organization 2 -> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Workflow ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
|
||||
* 3.6.6. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
* สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ได้
|
||||
* มีระบบแจ้งเตือน ให้ผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ทราบ เมื่อมี RFA ใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
* 3.6.การจัดการเอกสารนำส่ง (Transmittals)
|
||||
* 3.6.1. วัตถุประสงค์: เอกสารนำส่ง ใช้สำหรับ นำส่ง Request for Approval (RFAS) หลายฉบับ ไปยังองค์กรอื่น
|
||||
* 3.6.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
* 3.6.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
* 3.6.4. การอ้างอิงและจัดกลุ่ม: เอกสารนำส่ง เป็นส่วนหนึ่งใน Correspondence
|
||||
* 3.7. ใบเวียนเอกสารภายใน (Internal Circulation Sheet)
|
||||
* 3.7.1. วัตถุประสงค์: การสื่อสาร เอกสาร (Correspondence) ทุกฉบับ จะมีใบเวียนเอกสารเพื่อควบคุมและมอบหมายงานภายในองค์กร (สามารถดูและแก้ไขได้เฉพาะคนในองค์กร)
|
||||
* 3.7.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
* 3.7.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ในองค์กรนั้น สามารถสร้างและแก้ไขได้
|
||||
* 3.7.4. การอ้างอิงและจัดกลุ่ม: การระบุผู้รับผิดชอบ:
|
||||
* ผู้รับผิดชอบหลัก (Main): มีได้หลายคน
|
||||
* ผู้ร่วมปฏิบัติงาน (Action): มีได้หลายคน
|
||||
* ผู้ที่ต้องรับทราบ (Information): มีได้หลายคน
|
||||
* 3.7.5. การติดตามงาน:
|
||||
* สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบประเภท Main และ Action ได้
|
||||
* มีระบบแจ้งเตือนเมื่อมี Circulation ใหม่ และแจ้งเตือนล่วงหน้าก่อนถึงวันแล้วเสร็จ
|
||||
* สามารถปิด Circulation ได้เมื่อดำเนินการตอบกลับไปยังองค์กรผู้ส่ง (Originator) แล้ว หรือ รับทราบแล้ว (For Information)
|
||||
* 3.8. ประวัติการแก้ไข (Revisions): ระบบจะเก็บประวัติการสร้างและแก้ไข เอกสารทั้งหมด
|
||||
* 3.9. การจัดเก็บ: (ปรับปรุงตามสถาปัตยกรรมใหม่)
|
||||
* เอกสารและไฟล์แนบทั้งหมดจะถูกจัดเก็บในโฟลเดอร์บน Server (/share/dms-data/) [cite: 2.1]
|
||||
* ข้อมูล Metadata ของไฟล์ (เช่น ชื่อไฟล์, ขนาด, path) จะถูกเก็บในตาราง attachments (ตารางกลาง)
|
||||
* ไฟล์จะถูกเชื่อมโยงกับเอกสารประเภทต่างๆ ผ่านตารางเชื่อม (Junction tables) เช่น correspondence_attachments, circulation_attachments, shop_drawing_revision_attachments ,และ contracy_drawing_attachments
|
||||
* สถาปัตยกรรมแบบรวมศูนย์นี้ *แทนที่* แนวคิดเดิมที่จะแยกโฟลเดอร์ตามประเภทเอกสาร เพื่อรองรับการขยายระบบที่ดีกว่า
|
||||
* 3.10. การจัดการเลขที่เอกสาร (Document Numbering):
|
||||
* 3.10.1. ระบบต้องสามารถสร้างเลขที่เอกสาร (เช่น correspondence_number) ได้โดยอัตโนมัติ
|
||||
* 3.10.2. การนับเลข Running Number (SEQ) จะต้องนับแยกตาม Key ดังนี้: **โครงการ (Project)**, **องค์กรผู้ส่ง (Originator Organization)**, **ประเภทเอกสาร (Document Type)** และ **ปีปัจจุบัน (Year)**
|
||||
* 3.10.3. ผู้ดูแลระบบ (Admin) ต้องสามารถกำหนด "รูปแบบ" (Format Template) ของเลขที่เอกสารได้ (เช่น {ORG_CODE}-{TYPE_CODE}-{YEAR_SHORT}-{SEQ:4}) โดยกำหนดแยกตามโครงการและประเภทเอกสาร
|
||||
- 3.1. การจัดการโครงสร้างโครงการและองค์กร
|
||||
- 3.1.1. โครงการ (Projects): ระบบต้องสามารถจัดการเอกสารภายในหลายโครงการได้ (ปัจจุบันมี 4 โครงการ และจะเพิ่มขึ้นในอนาคต)
|
||||
- 3.1.2. สัญญา (Contracts): ระบบต้องสามารถจัดการเอกสารภายในแต่ละสัญญาได้ ในแต่ละโครงการ มีได้หลายสัญญา หรืออย่างน้อย 1 สัญญา
|
||||
- 3.1.3. องค์กร (Organizations):
|
||||
- มีหลายองค์กรในโครงการ องค์กรณ์ที่เป็น Owner, Designer และ Consultant สามารถอยู่ในหลายโครงการและหลายสัญญาได้
|
||||
- Contractor จะถือ 1 สัญญา และอยู่ใน 1 โครงการเท่านั้น
|
||||
- 3.2. การจัดการเอกสารโต้ตอบ (Correspondence Management)
|
||||
- 3.2.1. วัตถุประสงค์: เอกสารโต้ตอบ (correspondences) ระหว่างองกรณื-องกรณ์ ภายใน โครงการ (Projects) และระหว่าง องค์กร-องค์กร ภายนอก โครงการ (Projects), รองรับ To (ผู้รับหลัก) และ CC (ผู้รับสำเนา) หลายองค์กร
|
||||
- 3.2.2. ประเภทเอกสาร: ระบบต้องรองรับเอกสารรูปแบบ ไฟล์ PDF หลายประเภท (Types) เช่น จดหมาย (Letter), อีเมล์ (Email), Request for Information (RFI), และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
|
||||
- 3.2.3. การสร้างเอกสาร (Correspondence):
|
||||
- ผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารรอไว้ในสถานะ ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
|
||||
- เมื่อกด "Submitted" แล้ว การแก้ไข, ถอนเอกสารกลับไปสถานะ Draft, หรือยกเลิก (Cancel) จะต้องทำโดยผู้ใช้ระดับ Admin ขึ้นไป พร้อมระบุเหตุผล
|
||||
- 3.2.4. การอ้างอิงและจัดกลุ่ม:
|
||||
- เอกสารสามารถอ้างถึง (Reference) เอกสารฉบับก่อนหน้าได้หลายฉบับ
|
||||
- สามารถกำหนด Tag ได้หลาย Tag เพื่อจัดกลุ่มและใช้ในการค้นหาขั้นสูง
|
||||
- 3.2.5. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่เป็นผู้รับได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบขององกรณ์ที่เป็น ผู้รับ/ผู้ส่ง ทราบ เมื่อมีเอกสารใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
- 3.3. การจัดกาแบบคู่สัญญา (Contract Drawing)
|
||||
- 3.3.1. วัตถุประสงค์: แบบคู่สัญญา (Contract Drawing) ใช้เพื่ออ้างอิงและใช้ในการตรวจสอบ
|
||||
- 3.3.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.3.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.3.4. การอ้างอิงและจัดกลุ่ม: ใช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Contract Drawing
|
||||
- 3.4. การจัดกาแบบก่อสร้าง (Shop Drawing)
|
||||
- 3.4.1. วัตถุประสงค์: แบบก่อสร้าง (Shop Drawing) ใช้เในการตรวจสอบ โดยจัดส่งด้วย Request for Approval (RFA)
|
||||
- 3.4.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.4.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.4.4. การอ้างอิงและจัดกลุ่ม: ช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Shop Drawings
|
||||
- 3.5. การจัดการเอกสารขออนุมัติ (Request for Approval & Workflow)
|
||||
- 3.5.1. วัตถุประสงค์: เอกสารขออนุมัติ (Request for Approval) ใช้ในการส่งเอกสารเพิอขออนุมัติ
|
||||
- 3.5.2. ประเภทเอกสาร: Request for Approval (RFA) เป็นชนิดหนึ่งของ Correspondence ที่มีลักษณะเฉพาะที่ต้องได้รับการอนุมัติ มีประเภทดังนี้:
|
||||
- Request for Drawing Approval (RFA_DWG)
|
||||
- Request for Document Approval (RFA_DOC)
|
||||
- Request for Method statement Approval (RFA_MES)
|
||||
- Request for Material Approval (RFA_MAT)
|
||||
- 3.5.2. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.5.4. การอ้างอิงและจัดกลุ่ม: การจัดการ Drawing (RFA_DWG):
|
||||
- เอกสาร RFA_DWG จะประกอบไปด้วย Shop Drawing (shop_drawings) หลายแผ่น ซึ่งแต่ละแผ่นมี Revision ของตัวเอง
|
||||
- Shop Drawing แต่ละ Revision สามารถอ้างอิงถึง Contract Drawing (Ccontract_drawings) หลายแผ่น หรือไม่อ้างถึงก็ได้
|
||||
- ระบบต้องมีส่วนสำหรับจัดการข้อมูล Master Data ของทั้ง Shop Drawing และ Contract Drawing แยกจากกัน
|
||||
- 3.6.5. Workflow การอนุมัติ: ต้องรองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น
|
||||
- ส่งจาก Originator -> Organization 1 -> Organization 2 -> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Workflow ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
|
||||
- 3.6.6. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ทราบ เมื่อมี RFA ใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
- 3.6.การจัดการเอกสารนำส่ง (Transmittals)
|
||||
- 3.6.1. วัตถุประสงค์: เอกสารนำส่ง ใช้สำหรับ นำส่ง Request for Approval (RFAS) หลายฉบับ ไปยังองค์กรอื่น
|
||||
- 3.6.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.6.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.6.4. การอ้างอิงและจัดกลุ่ม: เอกสารนำส่ง เป็นส่วนหนึ่งใน Correspondence
|
||||
- 3.7. ใบเวียนเอกสารภายใน (Internal Circulation Sheet)
|
||||
- 3.7.1. วัตถุประสงค์: การสื่อสาร เอกสาร (Correspondence) ทุกฉบับ จะมีใบเวียนเอกสารเพื่อควบคุมและมอบหมายงานภายในองค์กร (สามารถดูและแก้ไขได้เฉพาะคนในองค์กร)
|
||||
- 3.7.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.7.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ในองค์กรนั้น สามารถสร้างและแก้ไขได้
|
||||
- 3.7.4. การอ้างอิงและจัดกลุ่ม: การระบุผู้รับผิดชอบ:
|
||||
- ผู้รับผิดชอบหลัก (Main): มีได้หลายคน
|
||||
- ผู้ร่วมปฏิบัติงาน (Action): มีได้หลายคน
|
||||
- ผู้ที่ต้องรับทราบ (Information): มีได้หลายคน
|
||||
- 3.7.5. การติดตามงาน:
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบประเภท Main และ Action ได้
|
||||
- มีระบบแจ้งเตือนเมื่อมี Circulation ใหม่ และแจ้งเตือนล่วงหน้าก่อนถึงวันแล้วเสร็จ
|
||||
- สามารถปิด Circulation ได้เมื่อดำเนินการตอบกลับไปยังองค์กรผู้ส่ง (Originator) แล้ว หรือ รับทราบแล้ว (For Information)
|
||||
- 3.8. ประวัติการแก้ไข (Revisions): ระบบจะเก็บประวัติการสร้างและแก้ไข เอกสารทั้งหมด
|
||||
- 3.9. การจัดเก็บ: (ปรับปรุงตามสถาปัตยกรรมใหม่)
|
||||
- เอกสารและไฟล์แนบทั้งหมดจะถูกจัดเก็บในโฟลเดอร์บน Server (/share/dms-data/) [cite: 2.1]
|
||||
- ข้อมูล Metadata ของไฟล์ (เช่น ชื่อไฟล์, ขนาด, path) จะถูกเก็บในตาราง attachments (ตารางกลาง)
|
||||
- ไฟล์จะถูกเชื่อมโยงกับเอกสารประเภทต่างๆ ผ่านตารางเชื่อม (Junction tables) เช่น correspondence_attachments, circulation_attachments, shop_drawing_revision_attachments ,และ contracy_drawing_attachments
|
||||
- สถาปัตยกรรมแบบรวมศูนย์นี้ _แทนที่_ แนวคิดเดิมที่จะแยกโฟลเดอร์ตามประเภทเอกสาร เพื่อรองรับการขยายระบบที่ดีกว่า
|
||||
- 3.10. การจัดการเลขที่เอกสาร (Document Numbering):
|
||||
- 3.10.1. ระบบต้องสามารถสร้างเลขที่เอกสาร (เช่น correspondence_number) ได้โดยอัตโนมัติ
|
||||
- 3.10.2. การนับเลข Running Number (SEQ) จะต้องนับแยกตาม Key ดังนี้: **โครงการ (Project)**, **องค์กรผู้ส่ง (Originator Organization)**, **ประเภทเอกสาร (Document Type)** และ **ปีปัจจุบัน (Year)**
|
||||
- 3.10.3. ผู้ดูแลระบบ (Admin) ต้องสามารถกำหนด "รูปแบบ" (Format Template) ของเลขที่เอกสารได้ (เช่น {ORG_CODE}-{TYPE_CODE}-{YEAR_SHORT}-{SEQ:4}) โดยกำหนดแยกตามโครงการและประเภทเอกสาร
|
||||
|
||||
## **🔐 4. ข้อกำหนดด้านสิทธิ์และการเข้าถึง (Access Control Requirements)**
|
||||
|
||||
* 4.1. ภาพรวม: ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
|
||||
* 4.2. ระดับของสิทธิ์:
|
||||
* Global Roles: สิทธิ์ในภาพรวมของระบบ
|
||||
* Project-Specific Roles: สิทธิ์ที่ถูกกำหนดให้ผู้ใช้สำหรับโครงการนั้นๆ โดยเฉพาะ (เช่น เป็น Editor ในโครงการ A แต่เป็น Viewer ในโครงการ B)
|
||||
* 4.3. บทบาท (Roles) พื้นฐาน:
|
||||
* Superadmin: ไม่มีข้อจำกัดใดๆ สามารถจัดการได้ทุกอย่างข้ามองค์กรณ์
|
||||
* Admin: มีสิทธิ์เต็มที่ แต่จำกัดเฉพาะในองค์กรที่ตัวเองสังกัด สามารถจัดการผู้ใช้ในองค์กรณ์ได้ สามารถสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลังผ่านหน้า Admin
|
||||
* Document Control สามารถ เพิ่ม/แก้ไข/ลบ เอกสาร เฉพาะในองค์กรณ์ที่ตัวเองสังกัด ไม่สามารถจัดการผู้ใช้ได้
|
||||
* Editor: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนดไว้ เฉพาะในองค์กรณ์ที่ตัวเองสังกัด
|
||||
* Viewer: สามารถดู เอกสาร เฉพาะในองค์กรณ์ที่ตัวเองสังกัด
|
||||
* 4.4. การบังคับใช้สิทธิ์: สิทธิ์ขององค์กรจะครอบคลุมสิทธิ์ของผู้ใช้ และการเข้าถึงข้อมูลที่เกี่ยวข้องกับโครงการ (เช่น การแก้ไขเอกสาร) จะถูกตรวจสอบเทียบกับสิทธิ์ที่ผู้ใช้มีในโครงการนั้นๆ โดยเฉพาะ
|
||||
* 4.5. (ใหม่) การจัดการข้อมูลหลัก (Master Data Management):
|
||||
* ระบบจะต้องมีส่วน "Admin Panel" (สำหรับ Superadmin และ Admin) เพื่อใช้จัดการข้อมูลหลัก (Master Data) ของระบบ
|
||||
* ข้อมูลหลักที่ต้องจัดการได้เป็นอย่างน้อย:
|
||||
* ประเภทเอกสาร (เช่น correspondence_types, rfa_types)
|
||||
* หมวดหมู่แบบ (เช่น shop_drawing_categories)
|
||||
* Tags ที่ใช้ในระบบ
|
||||
* สถานะเอกสาร (หากจำเป็นต้องเพิ่มในอนาคต)
|
||||
* 4.6. (ใหม่) การเริ่มต้นใช้งาน (User & Organization Onboarding):
|
||||
* การเพิ่มองค์กรณ์ใหม่ (Organizations) เข้าสู่ระบบ จะต้องดำเนินการโดย Superadmin เท่านั้น
|
||||
* เมื่อ Superadmin สร้างองค์กรณ์ใหม่ จะต้องสามารถกำหนดผู้ใช้ (User) อย่างน้อย 1 คน ให้เป็น "Admin" ประจำองค์กรณ์นั้นๆ
|
||||
* Admin ประจำองค์กณ์รจึงจะสามารถเพิ่มผู้ใช้ (Editor, Viewer, Document Control) คนอื่นๆ เข้าสู่องค์กรของตนเองได้
|
||||
- 4.1. ภาพรวม: ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
|
||||
- 4.2. ระดับของสิทธิ์:
|
||||
- Global Roles: สิทธิ์ในภาพรวมของระบบ
|
||||
- Project-Specific Roles: สิทธิ์ที่ถูกกำหนดให้ผู้ใช้สำหรับโครงการนั้นๆ โดยเฉพาะ (เช่น เป็น Editor ในโครงการ A แต่เป็น Viewer ในโครงการ B)
|
||||
- 4.3. บทบาท (Roles) พื้นฐาน:
|
||||
- Superadmin: ไม่มีข้อจำกัดใดๆ สามารถจัดการได้ทุกอย่างข้ามองค์กรณ์
|
||||
- Admin: มีสิทธิ์เต็มที่ แต่จำกัดเฉพาะในองค์กรที่ตัวเองสังกัด สามารถจัดการผู้ใช้ในองค์กรณ์ได้ สามารถสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลังผ่านหน้า Admin
|
||||
- Document Control สามารถ เพิ่ม/แก้ไข/ลบ เอกสาร เฉพาะในองค์กรณ์ที่ตัวเองสังกัด ไม่สามารถจัดการผู้ใช้ได้
|
||||
- Editor: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนดไว้ เฉพาะในองค์กรณ์ที่ตัวเองสังกัด
|
||||
- Viewer: สามารถดู เอกสาร เฉพาะในองค์กรณ์ที่ตัวเองสังกัด
|
||||
- 4.4. การบังคับใช้สิทธิ์: สิทธิ์ขององค์กรจะครอบคลุมสิทธิ์ของผู้ใช้ และการเข้าถึงข้อมูลที่เกี่ยวข้องกับโครงการ (เช่น การแก้ไขเอกสาร) จะถูกตรวจสอบเทียบกับสิทธิ์ที่ผู้ใช้มีในโครงการนั้นๆ โดยเฉพาะ
|
||||
- 4.5. (ใหม่) การจัดการข้อมูลหลัก (Master Data Management):
|
||||
- ระบบจะต้องมีส่วน "Admin Panel" (สำหรับ Superadmin และ Admin) เพื่อใช้จัดการข้อมูลหลัก (Master Data) ของระบบ
|
||||
- ข้อมูลหลักที่ต้องจัดการได้เป็นอย่างน้อย:
|
||||
- ประเภทเอกสาร (เช่น correspondence_types, rfa_types)
|
||||
- หมวดหมู่แบบ (เช่น shop_drawing_categories)
|
||||
- Tags ที่ใช้ในระบบ
|
||||
- สถานะเอกสาร (หากจำเป็นต้องเพิ่มในอนาคต)
|
||||
- 4.6. (ใหม่) การเริ่มต้นใช้งาน (User & Organization Onboarding):
|
||||
- การเพิ่มองค์กรณ์ใหม่ (Organizations) เข้าสู่ระบบ จะต้องดำเนินการโดย Superadmin เท่านั้น
|
||||
- เมื่อ Superadmin สร้างองค์กรณ์ใหม่ จะต้องสามารถกำหนดผู้ใช้ (User) อย่างน้อย 1 คน ให้เป็น "Admin" ประจำองค์กรณ์นั้นๆ
|
||||
- Admin ประจำองค์กณ์รจึงจะสามารถเพิ่มผู้ใช้ (Editor, Viewer, Document Control) คนอื่นๆ เข้าสู่องค์กรของตนเองได้
|
||||
|
||||
## **👥 5\. ข้อกำหนดด้านผู้ใช้งาน (User Interface & Experience)**
|
||||
|
||||
* 5.1. Layout หลัก: หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย:
|
||||
* Navbar (ส่วนบน): แสดงชื่อระบบ, เมนูผู้ใช้ (Profile), เมนูสำหรับ Admin/Superadmin (จัดการผู้ใช้, จัดการสิทธิ์), และปุ่ม Login/Logout
|
||||
* Sidebar (ด้านข้าง): เป็นเมนูหลักสำหรับเข้าถึงส่วนที่เกี่ยวกับเอกสารทั้งหมด เช่น Dashboard, Correspondences, RFA, Drawings
|
||||
* Main Content Area: พื้นที่สำหรับแสดงเนื้อหาหลักของหน้าที่เลือก
|
||||
* 5.2. หน้า Landing Page: เป็นหน้าแรกที่แสดงข้อมูลบางส่วนของโครงการสำหรับผู้ใช้ที่ยังไม่ได้ล็อกอิน
|
||||
* 5.3. หน้า Dashboard: เป็นหน้าแรกหลังจากล็อกอิน ประกอบด้วย:
|
||||
* การ์ดสรุปภาพรวม (KPI Cards): แสดงข้อมูลสรุปที่สำคัญขององค์กร เช่น จำนวนเอกสาร, งานที่เกินกำหนด
|
||||
* ตาราง "งานของฉัน" (My Tasks Table): แสดงรายการงานทั้งหมดจาก Circulation ที่ผู้ใช้ต้องดำเนินการ
|
||||
* 5.4. การติดตามสถานะ: องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
|
||||
* 5.5. การจัดการข้อมูลส่วนตัว (Profile Page): ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้
|
||||
* 5.6. การจัดการเอกสารทางเทคนิค (Technical Documents & Workflow): ผู้ใช้สามารถดู Technical Document ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว, ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ admin ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ admin ขึ้นไป
|
||||
* 5.7. ข้อกำหนด UI/UX การแนบไฟล์ (File Attachment UX):
|
||||
* ระบบต้องรองรับการอัปโหลดไฟล์หลายไฟล์พร้อมกัน (Multi-file upload) เช่น การลากและวาง (Drag-and-Drop)
|
||||
* ในหน้าอัปโหลด (เช่น สร้าง RFA หรือ Correspondence) ผู้ใช้ต้องสามารถกำหนดได้ว่าไฟล์ใดเป็น "เอกสารหลัก" (Main Document เช่น PDF) และไฟล์ใดเป็น "เอกสารแนบประกอบ" (Supporting Attachments เช่น .dwg, .docx, .zip)
|
||||
- 5.1. Layout หลัก: หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย:
|
||||
- Navbar (ส่วนบน): แสดงชื่อระบบ, เมนูผู้ใช้ (Profile), เมนูสำหรับ Admin/Superadmin (จัดการผู้ใช้, จัดการสิทธิ์), และปุ่ม Login/Logout
|
||||
- Sidebar (ด้านข้าง): เป็นเมนูหลักสำหรับเข้าถึงส่วนที่เกี่ยวกับเอกสารทั้งหมด เช่น Dashboard, Correspondences, RFA, Drawings
|
||||
- Main Content Area: พื้นที่สำหรับแสดงเนื้อหาหลักของหน้าที่เลือก
|
||||
- 5.2. หน้า Landing Page: เป็นหน้าแรกที่แสดงข้อมูลบางส่วนของโครงการสำหรับผู้ใช้ที่ยังไม่ได้ล็อกอิน
|
||||
- 5.3. หน้า Dashboard: เป็นหน้าแรกหลังจากล็อกอิน ประกอบด้วย:
|
||||
- การ์ดสรุปภาพรวม (KPI Cards): แสดงข้อมูลสรุปที่สำคัญขององค์กร เช่น จำนวนเอกสาร, งานที่เกินกำหนด
|
||||
- ตาราง "งานของฉัน" (My Tasks Table): แสดงรายการงานทั้งหมดจาก Circulation ที่ผู้ใช้ต้องดำเนินการ
|
||||
- 5.4. การติดตามสถานะ: องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
|
||||
- 5.5. การจัดการข้อมูลส่วนตัว (Profile Page): ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้
|
||||
- 5.6. การจัดการเอกสารทางเทคนิค (Technical Documents & Workflow): ผู้ใช้สามารถดู Technical Document ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว, ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ admin ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ admin ขึ้นไป
|
||||
- 5.7. ข้อกำหนด UI/UX การแนบไฟล์ (File Attachment UX):
|
||||
- ระบบต้องรองรับการอัปโหลดไฟล์หลายไฟล์พร้อมกัน (Multi-file upload) เช่น การลากและวาง (Drag-and-Drop)
|
||||
- ในหน้าอัปโหลด (เช่น สร้าง RFA หรือ Correspondence) ผู้ใช้ต้องสามารถกำหนดได้ว่าไฟล์ใดเป็น "เอกสารหลัก" (Main Document เช่น PDF) และไฟล์ใดเป็น "เอกสารแนบประกอบ" (Supporting Attachments เช่น .dwg, .docx, .zip)
|
||||
|
||||
## **6. ข้อกำหนดที่ไม่ใช่ฟังก์ชันการทำงาน (Non-Functional Requirements)**
|
||||
|
||||
* 6.1. การบันทึกการกระทำ (Audit Log): ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน audit_logs เพื่อการตรวจสอบย้อนหลัง
|
||||
* 6.2. การค้นหา (Search): ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสาร **correspondence**, **rfa**, **shop_drawing**, **contract-drawing**, **transmittal** และ **ใบเวียน (Circulations)** จากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
|
||||
* 6.3. การทำรายงาน (Reporting): สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
|
||||
* 6.4. ประสิทธิภาพ (Performance): มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
* 6.5. ความปลอดภัย (Security):
|
||||
* มีระบบ Rate Limiting เพื่อป้องกันการโจมตีแบบ Brute-force
|
||||
* การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด
|
||||
* 6.6. (ใหม่) การสำรองข้อมูลและการกู้คืน (Backup & Recovery):
|
||||
* ระบบจะต้องมีกลไกการสำรองข้อมูลอัตโนมัติสำหรับฐานข้อมูล MariaDB [cite: 2.4] และไฟล์เอกสารทั้งหมดใน /share/dms-data [cite: 2.1] (เช่น ใช้ HBS 3 ของ QNAP หรือสคริปต์สำรองข้อมูล) อย่างน้อยวันละ 1 ครั้ง
|
||||
* ต้องมีแผนการกู้คืนระบบ (Disaster Recovery Plan) ในกรณีที่ Server หลัก (QNAP) ใช้งานไม่ได้
|
||||
* 6.7. (ใหม่) กลยุทธ์การแจ้งเตือน (Notification Strategy):
|
||||
* ระบบจะส่งการแจ้งเตือน (ผ่าน Email หรือ Line [cite: 2.7]) เมื่อมีการกระทำที่สำคัญ ดังนี้:
|
||||
- 6.1. การบันทึกการกระทำ (Audit Log): ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน audit_logs เพื่อการตรวจสอบย้อนหลัง
|
||||
- 6.2. การค้นหา (Search): ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสาร **correspondence**, **rfa**, **shop_drawing**, **contract-drawing**, **transmittal** และ **ใบเวียน (Circulations)** จากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
|
||||
- 6.3. การทำรายงาน (Reporting): สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
|
||||
- 6.4. ประสิทธิภาพ (Performance): มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
- 6.5. ความปลอดภัย (Security):
|
||||
- มีระบบ Rate Limiting เพื่อป้องกันการโจมตีแบบ Brute-force
|
||||
- การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด
|
||||
- 6.6. (ใหม่) การสำรองข้อมูลและการกู้คืน (Backup & Recovery):
|
||||
- ระบบจะต้องมีกลไกการสำรองข้อมูลอัตโนมัติสำหรับฐานข้อมูล MariaDB [cite: 2.4] และไฟล์เอกสารทั้งหมดใน /share/dms-data [cite: 2.1] (เช่น ใช้ HBS 3 ของ QNAP หรือสคริปต์สำรองข้อมูล) อย่างน้อยวันละ 1 ครั้ง
|
||||
- ต้องมีแผนการกู้คืนระบบ (Disaster Recovery Plan) ในกรณีที่ Server หลัก (QNAP) ใช้งานไม่ได้
|
||||
- 6.7. (ใหม่) กลยุทธ์การแจ้งเตือน (Notification Strategy):
|
||||
- ระบบจะส่งการแจ้งเตือน (ผ่าน Email หรือ Line [cite: 2.7]) เมื่อมีการกระทำที่สำคัญ ดังนี้:
|
||||
1. เมื่อมีเอกสารใหม่ (Correspondence, RFA) ถูกส่งมาถึงองค์กรณ์ของเรา
|
||||
2. เมื่อมีใบเวียน (Circulation) ใหม่ มอบหมายงานมาที่เรา
|
||||
3. (ทางเลือก) เมื่อเอกสารที่เราส่งไป ถูกดำเนินการ (เช่น อนุมัติ/ปฏิเสธ)
|
||||
4. (ทางเลือก) เมื่อใกล้ถึงวันครบกำหนด (Deadline) [cite: 3.2.5, 3.6.6, 3.7.5]
|
||||
4. (ทางเลือก) เมื่อใกล้ถึงวันครบกำหนด (Deadline) [cite: 3.2.5, 3.6.6, 3.7.5]
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -8,140 +8,140 @@
|
||||
|
||||
### **หลักการพื้นฐาน**
|
||||
|
||||
* ใช้ **ภาษาอังกฤษ** สำหรับโค้ด
|
||||
* ใช้ **ภาษาไทย** สำหรับ comment และเอกสารทั้งหมด
|
||||
* กำหนดไทป์ (type) อย่างชัดเจนสำหรับตัวแปร, พารามิเตอร์ และค่าที่ส่งกลับ (return values) ทั้งหมด
|
||||
* หลีกเลี่ยงการใช้ any; ให้สร้างไทป์ (types) หรืออินเทอร์เฟซ (interfaces) ที่กำหนดเอง
|
||||
* ใช้ **JSDoc** สำหรับคลาส (classes) และเมธอด (methods) ที่เป็น public
|
||||
* ส่งออก (Export) **สัญลักษณ์หลัก (main symbol) เพียงหนึ่งเดียว** ต่อไฟล์
|
||||
* หลีกเลี่ยงบรรทัดว่างภายในฟังก์ชัน
|
||||
* ระบุ // File: path/filename ในบรรทัดแรกของทุกไฟล์
|
||||
* ระบุ // บันทึกการแก้ไข, หากมีการแก้ไขเพิ่มในอนาคต ให้เพิ่มบันทึก
|
||||
- ใช้ **ภาษาอังกฤษ** สำหรับโค้ด
|
||||
- ใช้ **ภาษาไทย** สำหรับ comment และเอกสารทั้งหมด
|
||||
- กำหนดไทป์ (type) อย่างชัดเจนสำหรับตัวแปร, พารามิเตอร์ และค่าที่ส่งกลับ (return values) ทั้งหมด
|
||||
- หลีกเลี่ยงการใช้ any; ให้สร้างไทป์ (types) หรืออินเทอร์เฟซ (interfaces) ที่กำหนดเอง
|
||||
- ใช้ **JSDoc** สำหรับคลาส (classes) และเมธอด (methods) ที่เป็น public
|
||||
- ส่งออก (Export) **สัญลักษณ์หลัก (main symbol) เพียงหนึ่งเดียว** ต่อไฟล์
|
||||
- หลีกเลี่ยงบรรทัดว่างภายในฟังก์ชัน
|
||||
- ระบุ // File: path/filename ในบรรทัดแรกของทุกไฟล์
|
||||
- ระบุ // บันทึกการแก้ไข, หากมีการแก้ไขเพิ่มในอนาคต ให้เพิ่มบันทึก
|
||||
|
||||
### **ข้อตกลงในการตั้งชื่อ (Naming Conventions)**
|
||||
|
||||
| Entity (สิ่งที่ตั้งชื่อ) | Convention (รูปแบบ) | Example (ตัวอย่าง) |
|
||||
| :---- | :---- | :---- |
|
||||
| Classes | PascalCase | UserService |
|
||||
| Property | snake_sase | user_id |
|
||||
| Variables & Functions | camelCase | getUserInfo |
|
||||
| Files & Folders | kebab-case | user-service.ts |
|
||||
| Environment Variables | UPPERCASE | DATABASE\URL |
|
||||
| Booleans | Verb \+ Noun | isActive, canDelete, hasPermission |
|
||||
| Entity (สิ่งที่ตั้งชื่อ) | Convention (รูปแบบ) | Example (ตัวอย่าง) |
|
||||
| :----------------------- | :------------------ | :--------------------------------- |
|
||||
| Classes | PascalCase | UserService |
|
||||
| Property | snake_sase | user_id |
|
||||
| Variables & Functions | camelCase | getUserInfo |
|
||||
| Files & Folders | kebab-case | user-service.ts |
|
||||
| Environment Variables | UPPERCASE | DATABASE\URL |
|
||||
| Booleans | Verb \+ Noun | isActive, canDelete, hasPermission |
|
||||
|
||||
ใช้คำเต็ม — ไม่ใช้อักษรย่อ — ยกเว้นคำมาตรฐาน (เช่น API, URL, req, res, err, ctx)
|
||||
|
||||
## **🧩 ฟังก์ชัน (Functions)**
|
||||
|
||||
* เขียนฟังก์ชันให้สั้น และทำ **หน้าที่เพียงอย่างเดียว** (single-purpose) (\< 20 บรรทัด)
|
||||
* ใช้ **early returns** เพื่อลดการซ้อน (nesting) ของโค้ด
|
||||
* ใช้ **map**, **filter**, **reduce** แทนการใช้ loops เมื่อเหมาะสม
|
||||
* ควรใช้ **arrow functions** สำหรับตรรกะสั้นๆ, และใช้ **named functions** ในกรณีอื่น
|
||||
* ใช้ **default parameters** แทนการตรวจสอบค่า null
|
||||
* จัดกลุ่มพารามิเตอร์หลายตัวให้เป็นอ็อบเจกต์เดียว (RO-RO pattern)
|
||||
* ส่งค่ากลับ (Return) เป็นอ็อบเจกต์ที่มีไทป์กำหนด (typed objects) ไม่ใช่ค่าพื้นฐาน (primitives)
|
||||
* รักษาระดับของสิ่งที่เป็นนามธรรม (abstraction level) ให้เป็นระดับเดียวในแต่ละฟังก์ชัน
|
||||
- เขียนฟังก์ชันให้สั้น และทำ **หน้าที่เพียงอย่างเดียว** (single-purpose) (\< 20 บรรทัด)
|
||||
- ใช้ **early returns** เพื่อลดการซ้อน (nesting) ของโค้ด
|
||||
- ใช้ **map**, **filter**, **reduce** แทนการใช้ loops เมื่อเหมาะสม
|
||||
- ควรใช้ **arrow functions** สำหรับตรรกะสั้นๆ, และใช้ **named functions** ในกรณีอื่น
|
||||
- ใช้ **default parameters** แทนการตรวจสอบค่า null
|
||||
- จัดกลุ่มพารามิเตอร์หลายตัวให้เป็นอ็อบเจกต์เดียว (RO-RO pattern)
|
||||
- ส่งค่ากลับ (Return) เป็นอ็อบเจกต์ที่มีไทป์กำหนด (typed objects) ไม่ใช่ค่าพื้นฐาน (primitives)
|
||||
- รักษาระดับของสิ่งที่เป็นนามธรรม (abstraction level) ให้เป็นระดับเดียวในแต่ละฟังก์ชัน
|
||||
|
||||
## **🧱 การจัดการข้อมูล (Data Handling)**
|
||||
|
||||
* ห่อหุ้มข้อมูล (Encapsulate) ในไทป์แบบผสม (composite types)
|
||||
* ใช้ **immutability** (การไม่เปลี่ยนแปลงค่า) ด้วย readonly และ as const
|
||||
* ทำการตรวจสอบความถูกต้องของข้อมูล (Validations) ในคลาสหรือ DTOs ไม่ใช่ภายในฟังก์ชันทางธุรกิจ
|
||||
* ตรวจสอบความถูกต้องของข้อมูลโดยใช้ DTOs ที่มีไทป์กำหนดเสมอ
|
||||
- ห่อหุ้มข้อมูล (Encapsulate) ในไทป์แบบผสม (composite types)
|
||||
- ใช้ **immutability** (การไม่เปลี่ยนแปลงค่า) ด้วย readonly และ as const
|
||||
- ทำการตรวจสอบความถูกต้องของข้อมูล (Validations) ในคลาสหรือ DTOs ไม่ใช่ภายในฟังก์ชันทางธุรกิจ
|
||||
- ตรวจสอบความถูกต้องของข้อมูลโดยใช้ DTOs ที่มีไทป์กำหนดเสมอ
|
||||
|
||||
## **🧰 คลาส (Classes)**
|
||||
|
||||
* ปฏิบัติตามหลักการ **SOLID**
|
||||
* ควรใช้ **composition มากกว่า inheritance** (Prefer composition over inheritance)
|
||||
* กำหนด **interfaces** สำหรับสัญญา (contracts)
|
||||
* ให้คลาสมุ่งเน้นการทำงานเฉพาะอย่างและมีขนาดเล็ก (\< 200 บรรทัด, \< 10 เมธอด, \< 10 properties)
|
||||
- ปฏิบัติตามหลักการ **SOLID**
|
||||
- ควรใช้ **composition มากกว่า inheritance** (Prefer composition over inheritance)
|
||||
- กำหนด **interfaces** สำหรับสัญญา (contracts)
|
||||
- ให้คลาสมุ่งเน้นการทำงานเฉพาะอย่างและมีขนาดเล็ก (\< 200 บรรทัด, \< 10 เมธอด, \< 10 properties)
|
||||
|
||||
## **🚨 การจัดการข้อผิดพลาด (Error Handling)**
|
||||
|
||||
* ใช้ Exceptions สำหรับข้อผิดพลาดที่ไม่คาดคิด
|
||||
* ดักจับ (Catch) ข้อผิดพลาดเพื่อแก้ไขหรือเพิ่มบริบท (context) เท่านั้น; หากไม่เช่นนั้น ให้ใช้ global error handlers
|
||||
* ระบุข้อความข้อผิดพลาด (error messages) ที่มีความหมายเสมอ
|
||||
- ใช้ Exceptions สำหรับข้อผิดพลาดที่ไม่คาดคิด
|
||||
- ดักจับ (Catch) ข้อผิดพลาดเพื่อแก้ไขหรือเพิ่มบริบท (context) เท่านั้น; หากไม่เช่นนั้น ให้ใช้ global error handlers
|
||||
- ระบุข้อความข้อผิดพลาด (error messages) ที่มีความหมายเสมอ
|
||||
|
||||
## **🧪 การทดสอบ (ทั่วไป) (Testing (General))**
|
||||
|
||||
* ใช้รูปแบบ **Arrange–Act–Assert**
|
||||
* ใช้ชื่อตัวแปรในการทดสอบที่สื่อความหมาย (inputData, expectedOutput)
|
||||
* เขียน **unit tests** สำหรับ public methods ทั้งหมด
|
||||
* จำลอง (Mock) การพึ่งพาภายนอก (external dependencies)
|
||||
* เพิ่ม **acceptance tests** ต่อโมดูลโดยใช้รูปแบบ Given–When-Then
|
||||
- ใช้รูปแบบ **Arrange–Act–Assert**
|
||||
- ใช้ชื่อตัวแปรในการทดสอบที่สื่อความหมาย (inputData, expectedOutput)
|
||||
- เขียน **unit tests** สำหรับ public methods ทั้งหมด
|
||||
- จำลอง (Mock) การพึ่งพาภายนอก (external dependencies)
|
||||
- เพิ่ม **acceptance tests** ต่อโมดูลโดยใช้รูปแบบ Given–When-Then
|
||||
|
||||
## **🏗️ แบ็กเอนด์ (NestJS) (Backend (NestJS))**
|
||||
|
||||
### **หลักการ**
|
||||
|
||||
* **สถาปัตยกรรมแบบโมดูลาร์ (Modular architecture)**:
|
||||
* หนึ่งโมดูลต่อหนึ่งโดเมน
|
||||
* โครงสร้างแบบ Controller → Service → Repository (Model)
|
||||
* API-First: มุ่งเน้นการสร้าง API ที่มีคุณภาพสูง มีเอกสารประกอบ (Swagger) ที่ชัดเจนสำหรับ Frontend Team
|
||||
* DTOs ที่ตรวจสอบความถูกต้องด้วย **class-validator**
|
||||
* ใช้ **MikroORM** (หรือ TypeORM/Prisma) สำหรับการคงอยู่ของข้อมูล (persistence) ซึ่งสอดคล้องกับสคีมา MariaDB
|
||||
* ห่อหุ้มโค้ดที่ใช้ซ้ำได้ไว้ใน **common module** (@app/common):
|
||||
* Configs, decorators, DTOs, guards, interceptors, notifications, shared services, types, validators
|
||||
- **สถาปัตยกรรมแบบโมดูลาร์ (Modular architecture)**:
|
||||
- หนึ่งโมดูลต่อหนึ่งโดเมน
|
||||
- โครงสร้างแบบ Controller → Service → Repository (Model)
|
||||
- API-First: มุ่งเน้นการสร้าง API ที่มีคุณภาพสูง มีเอกสารประกอบ (Swagger) ที่ชัดเจนสำหรับ Frontend Team
|
||||
- DTOs ที่ตรวจสอบความถูกต้องด้วย **class-validator**
|
||||
- ใช้ **MikroORM** (หรือ TypeORM/Prisma) สำหรับการคงอยู่ของข้อมูล (persistence) ซึ่งสอดคล้องกับสคีมา MariaDB
|
||||
- ห่อหุ้มโค้ดที่ใช้ซ้ำได้ไว้ใน **common module** (@app/common):
|
||||
- Configs, decorators, DTOs, guards, interceptors, notifications, shared services, types, validators
|
||||
|
||||
### **ฟังก์ชันหลัก (Core Functionalities)**
|
||||
|
||||
* Global **filters** สำหรับการจัดการ exception
|
||||
* **Middlewares** สำหรับการจัดการ request
|
||||
* **Guards** สำหรับการอนุญาต (permissions) และ RBAC
|
||||
* **Interceptors** สำหรับการแปลงข้อมูล response และการบันทึก log
|
||||
- Global **filters** สำหรับการจัดการ exception
|
||||
- **Middlewares** สำหรับการจัดการ request
|
||||
- **Guards** สำหรับการอนุญาต (permissions) และ RBAC
|
||||
- **Interceptors** สำหรับการแปลงข้อมูล response และการบันทึก log
|
||||
|
||||
### **ข้อจำกัดในการ Deploy (QNAP Container Station)**
|
||||
|
||||
* **ห้ามใช้ไฟล์ .env** ในการตั้งค่า Environment Variables [cite: 2.1]
|
||||
* การตั้งค่าทั้งหมด (เช่น Database connection string, JWT secret) **จะต้องถูกกำหนดผ่าน Environment Variable ใน docker-compose.yml โดยตรง** [cite: 6.5] ซึ่งจะจัดการผ่าน UI ของ QNAP Container Station [cite: 2.1]
|
||||
- **ห้ามใช้ไฟล์ .env** ในการตั้งค่า Environment Variables [cite: 2.1]
|
||||
- การตั้งค่าทั้งหมด (เช่น Database connection string, JWT secret) **จะต้องถูกกำหนดผ่าน Environment Variable ใน docker-compose.yml โดยตรง** [cite: 6.5] ซึ่งจะจัดการผ่าน UI ของ QNAP Container Station [cite: 2.1]
|
||||
|
||||
### **โครงสร้างโมดูลตามโดเมน (Domain-Driven Module Structure)**
|
||||
|
||||
เพื่อให้สอดคล้องกับสคีมา SQL (LCBP3-DMS) เราจะใช้โครงสร้างโมดูลแบบ **Domain-Driven (แบ่งตามขอบเขตธุรกิจ)** แทนการแบ่งตามฟังก์ชัน:
|
||||
|
||||
1. **CommonModule:**
|
||||
* เก็บ Services ที่ใช้ร่วมกัน เช่น DatabaseModule, FileStorageService (จัดการไฟล์ใน QNAP), AuditLogService, NotificationService
|
||||
* จัดการ audit_logs
|
||||
* NotificationService ต้องรองรับ Triggers ที่ระบุใน Requirement 6.7 [cite: 6.7]
|
||||
- เก็บ Services ที่ใช้ร่วมกัน เช่น DatabaseModule, FileStorageService (จัดการไฟล์ใน QNAP), AuditLogService, NotificationService
|
||||
- จัดการ audit_logs
|
||||
- NotificationService ต้องรองรับ Triggers ที่ระบุใน Requirement 6.7 [cite: 6.7]
|
||||
2. **AuthModule:**
|
||||
* จัดการะการยืนยันตัวตน (JWT, Guards)
|
||||
* **(สำคัญ)** ต้องรับผิดชอบการตรวจสอบสิทธิ์ **3 ระดับ** [cite: 4.2]: สิทธิ์ระดับระบบ (Global Role), สิทธิ์ระดับโปรเจกต์ (Project Role), และ **สิทธิ์ระดับสัญญา (Contract Role)**
|
||||
* **(สำคัญ)** ต้องมี API สำหรับ **Admin Panel** เพื่อ:
|
||||
* สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก [cite: 4.3]
|
||||
* ให้ Superadmin สร้าง Organizations และกำหนด Org Admin ได้ [cite: 4.6]
|
||||
* ให้ Superadmin/Admin จัดการ document_number_formats (รูปแบบเลขที่เอกสาร), document_number_counters (Running Number) [cite: 3.10]
|
||||
- จัดการะการยืนยันตัวตน (JWT, Guards)
|
||||
- **(สำคัญ)** ต้องรับผิดชอบการตรวจสอบสิทธิ์ **3 ระดับ** [cite: 4.2]: สิทธิ์ระดับระบบ (Global Role), สิทธิ์ระดับโปรเจกต์ (Project Role), และ **สิทธิ์ระดับสัญญา (Contract Role)**
|
||||
- **(สำคัญ)** ต้องมี API สำหรับ **Admin Panel** เพื่อ:
|
||||
- สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก [cite: 4.3]
|
||||
- ให้ Superadmin สร้าง Organizations และกำหนด Org Admin ได้ [cite: 4.6]
|
||||
- ให้ Superadmin/Admin จัดการ document_number_formats (รูปแบบเลขที่เอกสาร), document_number_counters (Running Number) [cite: 3.10]
|
||||
3. **UserModule:**
|
||||
* จัดการ users, roles, permissions, global_default_roles, role_permissions, user_roles, user_project_roles
|
||||
* **(สำคัญ)** ต้องมี API สำหรับ **Admin Panel** เพื่อ:
|
||||
* สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก [cite: 4.3]
|
||||
- จัดการ users, roles, permissions, global_default_roles, role_permissions, user_roles, user_project_roles
|
||||
- **(สำคัญ)** ต้องมี API สำหรับ **Admin Panel** เพื่อ:
|
||||
- สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก [cite: 4.3]
|
||||
4. **ProjectModule:**
|
||||
* จัดการ projects, organizations, contracts, project_parties, contract_parties
|
||||
- จัดการ projects, organizations, contracts, project_parties, contract_parties
|
||||
5. **MasterModule:**
|
||||
* จัดการ master data (correspondence_types, rfa_types, rfa_status_codes, rfa_approve_codes, circulation_status_codes, correspondence_types, correspondence_status, tags) [cite: 4.5]
|
||||
- จัดการ master data (correspondence_types, rfa_types, rfa_status_codes, rfa_approve_codes, circulation_status_codes, correspondence_types, correspondence_status, tags) [cite: 4.5]
|
||||
6. **CorrespondenceModule (โมดูลศูนย์กลาง):**
|
||||
* จัดการ correspondences, correspondence_revisions, correspondence_tags
|
||||
* **(สำคัญ)** Service นี้ต้อง Inject DocumentNumberingService เพื่อขอเลขที่เอกสารใหม่ก่อนการสร้าง
|
||||
* **(สำคัญ)** ตรรกะการสร้าง/อัปเดต Revision จะอยู่ใน Service นี้
|
||||
* จัดการ correspondence_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
* รับผิดชอบเวิร์กโฟลว์ **"Correspondence Routings"** (correspondence_routings, correspondence_routing_templates) สำหรับการส่งต่อเอกสารทั่วไประหว่างองค์กร
|
||||
- จัดการ correspondences, correspondence_revisions, correspondence_tags
|
||||
- **(สำคัญ)** Service นี้ต้อง Inject DocumentNumberingService เพื่อขอเลขที่เอกสารใหม่ก่อนการสร้าง
|
||||
- **(สำคัญ)** ตรรกะการสร้าง/อัปเดต Revision จะอยู่ใน Service นี้
|
||||
- จัดการ correspondence_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
- รับผิดชอบเวิร์กโฟลว์ **"Correspondence Routings"** (correspondence_routings, correspondence_routing_templates) สำหรับการส่งต่อเอกสารทั่วไประหว่างองค์กร
|
||||
7. **RfaModule:**
|
||||
* จัดการ rfas, rfa_revisions, rfa_items
|
||||
* รับผิดชอบเวิร์กโฟลว์ **"RFA Workflows"** (rfa_workflows, rfa_workflow_templates, rfa_workflow_template_steps, rfa_status_transitions) สำหรับการอนุมัติเอกสารทางเทคนิค
|
||||
- จัดการ rfas, rfa_revisions, rfa_items
|
||||
- รับผิดชอบเวิร์กโฟลว์ **"RFA Workflows"** (rfa_workflows, rfa_workflow_templates, rfa_workflow_template_steps, rfa_status_transitions) สำหรับการอนุมัติเอกสารทางเทคนิค
|
||||
8. **DrawingModule:**
|
||||
* จัดการ shop_drawings, shop_drawing_revisions, contract_drawings, contract_drawing_volumes, contract_drawing_cats, contract_drawing_sub_cats, shop_drawing_main_categories, shop_drawing_sub_categories, contract_drawing_subcat_cat_maps, shop_drawing_revision_contract_refs
|
||||
* จัดการ shop_drawing_revision_attachments และ contract_drawing_attachments(ตารางเชื่อมไฟล์แนบ)
|
||||
- จัดการ shop_drawings, shop_drawing_revisions, contract_drawings, contract_drawing_volumes, contract_drawing_cats, contract_drawing_sub_cats, shop_drawing_main_categories, shop_drawing_sub_categories, contract_drawing_subcat_cat_maps, shop_drawing_revision_contract_refs
|
||||
- จัดการ shop_drawing_revision_attachments และ contract_drawing_attachments(ตารางเชื่อมไฟล์แนบ)
|
||||
9. **CirculationModule:**
|
||||
* จัดการ circulations, circulation_templates, circulation_assignees
|
||||
* จัดการ circulation_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
* รับผิดชอบเวิร์กโฟลว์ **"Circulations"** (circulation_status_transitions, circulation_template_assignees, circulation_assignees, circulation_recipients, circulation_actions, circulation_action_documents)สำหรับการเวียนเอกสาร **ภายในองค์กร**
|
||||
- จัดการ circulations, circulation_templates, circulation_assignees
|
||||
- จัดการ circulation_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
- รับผิดชอบเวิร์กโฟลว์ **"Circulations"** (circulation_status_transitions, circulation_template_assignees, circulation_assignees, circulation_recipients, circulation_actions, circulation_action_documents)สำหรับการเวียนเอกสาร **ภายในองค์กร**
|
||||
10. **TransmittalModule:**
|
||||
* จัดการ transmittals และ transmittal_items
|
||||
- จัดการ transmittals และ transmittal_items
|
||||
11. **SearchModule:**
|
||||
* ให้บริการค้นหาขั้นสูง (Advanced Search) [cite: 6.2] โดยใช้ **Elasticsearch** เพื่อรองรับการค้นหาแบบ Full-text จากชื่อเรื่อง, รายละเอียด, เลขที่เอกสาร, ประเภท, วันที่, และ Tags
|
||||
- ให้บริการค้นหาขั้นสูง (Advanced Search) [cite: 6.2] โดยใช้ **Elasticsearch** เพื่อรองรับการค้นหาแบบ Full-text จากชื่อเรื่อง, รายละเอียด, เลขที่เอกสาร, ประเภท, วันที่, และ Tags
|
||||
12. **DocumentNumberingModule:**
|
||||
* **สถานะ:** เป็น Module ภายใน (Internal Module) ไม่เปิด API สู่ภายนอก
|
||||
* **หน้าที่:** ให้บริการ DocumentNumberingService ที่ Module อื่น (เช่น CorrespondenceModule) จะ Inject ไปใช้งาน
|
||||
* **ตรรกะ:** รับผิดชอบการสร้างเลขที่เอกสาร โดยการเรียกใช้ Stored Procedure *sp_get_next_document_number** เพื่อป้องกัน Race Condition
|
||||
- **สถานะ:** เป็น Module ภายใน (Internal Module) ไม่เปิด API สู่ภายนอก
|
||||
- **หน้าที่:** ให้บริการ DocumentNumberingService ที่ Module อื่น (เช่น CorrespondenceModule) จะ Inject ไปใช้งาน
|
||||
- **ตรรกะ:** รับผิดชอบการสร้างเลขที่เอกสาร โดยการเรียกใช้ Stored Procedure \*sp_get_next_document_number\*\* เพื่อป้องกัน Race Condition
|
||||
|
||||
### **สถาปัตยกรรมระบบ (System Architecture)**
|
||||
|
||||
@@ -176,46 +176,46 @@
|
||||
|
||||
### **เเทคโนโลยีที่ใช้ (Technology Stack)**
|
||||
|
||||
| ส่วน | Library/Tool | หมายเหตุ |
|
||||
|---|---|---|
|
||||
| **Framework** | `@nestjs/core`, `@nestjs/common` | Core Framework |
|
||||
| **Language** | `TypeScript` | ใช้ TypeScript ทั้งระบบ |
|
||||
| **Database** | `MariaDB 10.11` | ฐานข้อมูลหลัก |
|
||||
| **ORM** | `@nestjs/typeorm`, `typeorm` | 🗃️จัดการการเชื่อมต่อและ Query ฐานข้อมูล |
|
||||
| **Validation** | `class-validator`, `class-transformer` | 📦ตรวจสอบและแปลงข้อมูลใน DTO |
|
||||
| **Auth** | `@nestjs/jwt`, `@nestjs/passport`, `passport-jwt` | 🔐การยืนยันตัวตนด้วย JWT |
|
||||
|**Authorization** | `casl` | 🔐จัดการสิทธิ์แบบ RBAC |
|
||||
| **File Upload** | `multer` | 📁จัดการการอัปโหลดไฟล์ |
|
||||
| **Search** | `@nestjs/elasticsearch` | 🔍สำหรับการค้นหาขั้นสูง |
|
||||
| **Notification** | `nodemailer` | 📬ส่งอีเมลแจ้งเตือน |
|
||||
| **Scheduling** | `@nestjs/schedule` | 📬สำหรับ Cron Jobs (เช่น แจ้งเตือน Deadline) |
|
||||
| **Logging** | `winston` | 📊บันทึก Log ที่มีประสิทธิภาพ |
|
||||
| **Testing** | `@nestjs/testing`, `jest`, `supertest` | 🧪ทดสอบ Unit, Integration และ E2E |
|
||||
| **Documentation** | `@nestjs/swagger` | 🌐สร้าง API Documentation อัตโนมัติ |
|
||||
| **Security** | `helmet`, `rate-limiter-flexible` | 🛡️เพิ่มความปลอดภัยให้ API |
|
||||
| ส่วน | Library/Tool | หมายเหตุ |
|
||||
| ----------------- | ------------------------------------------------- | -------------------------------------------- |
|
||||
| **Framework** | `@nestjs/core`, `@nestjs/common` | Core Framework |
|
||||
| **Language** | `TypeScript` | ใช้ TypeScript ทั้งระบบ |
|
||||
| **Database** | `MariaDB 10.11` | ฐานข้อมูลหลัก |
|
||||
| **ORM** | `@nestjs/typeorm`, `typeorm` | 🗃️จัดการการเชื่อมต่อและ Query ฐานข้อมูล |
|
||||
| **Validation** | `class-validator`, `class-transformer` | 📦ตรวจสอบและแปลงข้อมูลใน DTO |
|
||||
| **Auth** | `@nestjs/jwt`, `@nestjs/passport`, `passport-jwt` | 🔐การยืนยันตัวตนด้วย JWT |
|
||||
| **Authorization** | `casl` | 🔐จัดการสิทธิ์แบบ RBAC |
|
||||
| **File Upload** | `multer` | 📁จัดการการอัปโหลดไฟล์ |
|
||||
| **Search** | `@nestjs/elasticsearch` | 🔍สำหรับการค้นหาขั้นสูง |
|
||||
| **Notification** | `nodemailer` | 📬ส่งอีเมลแจ้งเตือน |
|
||||
| **Scheduling** | `@nestjs/schedule` | 📬สำหรับ Cron Jobs (เช่น แจ้งเตือน Deadline) |
|
||||
| **Logging** | `winston` | 📊บันทึก Log ที่มีประสิทธิภาพ |
|
||||
| **Testing** | `@nestjs/testing`, `jest`, `supertest` | 🧪ทดสอบ Unit, Integration และ E2E |
|
||||
| **Documentation** | `@nestjs/swagger` | 🌐สร้าง API Documentation อัตโนมัติ |
|
||||
| **Security** | `helmet`, `rate-limiter-flexible` | 🛡️เพิ่มความปลอดภัยให้ API |
|
||||
|
||||
เราจะแบ่งการทดสอบเป็น 3 ระดับ โดยใช้ **Jest** และ @nestjs/testing:
|
||||
|
||||
* **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
* **เป้าหมาย:** ทดสอบ Logic ภายใน Service, Guard, หรือ Pipe โดยจำลอง (Mock) Dependencies ทั้งหมด
|
||||
* **สิ่งที่ต้องทดสอบ:** Business Logic (เช่น การเปลี่ยนสถานะ Workflow, การตรวจสอบ Deadline) [cite: 2.9.1], ตรรกะการตรวจสอบสิทธิ์ (Auth Guard) ทั้ง 3 ระดับ
|
||||
* **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
* **เป้าหมาย:** ทดสอบการทำงานร่วมกันของ Controller -> Service -> Repository (Database)
|
||||
* **เทคนิค:** ใช้ **Test Database แยกต่างหาก** (ห้ามใช้ Dev DB) และใช้ supertest เพื่อยิง HTTP Request จริงไปยัง App
|
||||
* **สิ่งที่ต้องทดสอบ:** การเรียก sp\get\next\document\number [cite: 2.9.3] และการทำงานของ Views (เช่น v_user_tasks)
|
||||
* **E2E (End-to-End) Tests:**
|
||||
* **เป้าหมาย:** ทดสอบ API Contract ว่า Response Body Shape ตรงตามเอกสาร Swagger เพื่อรับประกันทีม Frontend
|
||||
- **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
- **เป้าหมาย:** ทดสอบ Logic ภายใน Service, Guard, หรือ Pipe โดยจำลอง (Mock) Dependencies ทั้งหมด
|
||||
- **สิ่งที่ต้องทดสอบ:** Business Logic (เช่น การเปลี่ยนสถานะ Workflow, การตรวจสอบ Deadline) [cite: 2.9.1], ตรรกะการตรวจสอบสิทธิ์ (Auth Guard) ทั้ง 3 ระดับ
|
||||
- **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
- **เป้าหมาย:** ทดสอบการทำงานร่วมกันของ Controller -> Service -> Repository (Database)
|
||||
- **เทคนิค:** ใช้ **Test Database แยกต่างหาก** (ห้ามใช้ Dev DB) และใช้ supertest เพื่อยิง HTTP Request จริงไปยัง App
|
||||
- **สิ่งที่ต้องทดสอบ:** การเรียก sp\get\next\document\number [cite: 2.9.3] และการทำงานของ Views (เช่น v_user_tasks)
|
||||
- **E2E (End-to-End) Tests:**
|
||||
- **เป้าหมาย:** ทดสอบ API Contract ว่า Response Body Shape ตรงตามเอกสาร Swagger เพื่อรับประกันทีม Frontend
|
||||
|
||||
### **🗄️ Backend State Management**
|
||||
|
||||
Backend (NestJS) ควรเป็น **Stateless** (ไม่เก็บสถานะ) "State" ทั้งหมดจะถูกจัดเก็บใน MariaDB
|
||||
|
||||
* **Request-Scoped State (สถานะภายใน Request เดียว):**
|
||||
* **ปัญหา:** จะส่งต่อข้อมูล (เช่น User ที่ล็อกอิน) ระหว่าง Guard และ Service ใน Request เดียวกันได้อย่างไร?
|
||||
* **วิธีแก้:** ใช้ **Request-Scoped Providers** ของ NestJS (เช่น AuthContextService) เพื่อเก็บข้อมูล User ปัจจุบันที่ได้จาก AuthGuard และให้ Service อื่น Inject ไปใช้
|
||||
* **Application-Scoped State (การ Caching):**
|
||||
* **ปัญหา:** ข้อมูล Master (เช่น roles, permissions, organizations) ถูกเรียกใช้บ่อย
|
||||
* **วิธีแก้:** ใช้ **Caching** (เช่น @nestjs/cache-manager) เพื่อ Caching ข้อมูลเหล่านี้ และลดภาระ Database
|
||||
- **Request-Scoped State (สถานะภายใน Request เดียว):**
|
||||
- **ปัญหา:** จะส่งต่อข้อมูล (เช่น User ที่ล็อกอิน) ระหว่าง Guard และ Service ใน Request เดียวกันได้อย่างไร?
|
||||
- **วิธีแก้:** ใช้ **Request-Scoped Providers** ของ NestJS (เช่น AuthContextService) เพื่อเก็บข้อมูล User ปัจจุบันที่ได้จาก AuthGuard และให้ Service อื่น Inject ไปใช้
|
||||
- **Application-Scoped State (การ Caching):**
|
||||
- **ปัญหา:** ข้อมูล Master (เช่น roles, permissions, organizations) ถูกเรียกใช้บ่อย
|
||||
- **วิธีแก้:** ใช้ **Caching** (เช่น @nestjs/cache-manager) เพื่อ Caching ข้อมูลเหล่านี้ และลดภาระ Database
|
||||
|
||||
### **การไหลของข้อมูล (Data Flow)**
|
||||
|
||||
@@ -236,76 +236,76 @@ Backend (NestJS) ควรเป็น **Stateless** (ไม่เก็บส
|
||||
|
||||
### **แนวทางการพัฒนาโค้ด (Code Implementation Guidelines)**
|
||||
|
||||
* ใช้ **early returns** เพื่อความชัดเจน
|
||||
* ใช้คลาสของ **TailwindCSS** ในการกำหนดสไตล์เสมอ
|
||||
* ควรใช้ class: syntax แบบมีเงื่อนไข (หรือ utility clsx) มากกว่าการใช้ ternary operators ใน class strings
|
||||
* ใช้ **const arrow functions** สำหรับ components และ handlers
|
||||
* Event handlers ให้ขึ้นต้นด้วย handle... (เช่น handleClick, handleSubmit)
|
||||
* รวมแอตทริบิวต์สำหรับการเข้าถึง (accessibility) ด้วย:
|
||||
- ใช้ **early returns** เพื่อความชัดเจน
|
||||
- ใช้คลาสของ **TailwindCSS** ในการกำหนดสไตล์เสมอ
|
||||
- ควรใช้ class: syntax แบบมีเงื่อนไข (หรือ utility clsx) มากกว่าการใช้ ternary operators ใน class strings
|
||||
- ใช้ **const arrow functions** สำหรับ components และ handlers
|
||||
- Event handlers ให้ขึ้นต้นด้วย handle... (เช่น handleClick, handleSubmit)
|
||||
- รวมแอตทริบิวต์สำหรับการเข้าถึง (accessibility) ด้วย:
|
||||
tabIndex="0", aria-label, onKeyDown, ฯลฯ
|
||||
* ตรวจสอบให้แน่ใจว่าโค้ดทั้งหมด **สมบูรณ์**, **ผ่านการทดสอบ**, และ **ไม่ซ้ำซ้อน (DRY)**
|
||||
* ต้อง import โมดูลที่จำเป็นต้องใช้อย่างชัดเจนเสมอ
|
||||
- ตรวจสอบให้แน่ใจว่าโค้ดทั้งหมด **สมบูรณ์**, **ผ่านการทดสอบ**, และ **ไม่ซ้ำซ้อน (DRY)**
|
||||
- ต้อง import โมดูลที่จำเป็นต้องใช้อย่างชัดเจนเสมอ
|
||||
|
||||
### **UI/UX ด้วย React**
|
||||
|
||||
* ใช้ **semantic HTML**
|
||||
* ใช้คลาสของ **Tailwind** ที่รองรับ responsive (sm:, md:, lg:)
|
||||
* รักษาลำดับชั้นของการมองเห็น (visual hierarchy) ด้วยการใช้ typography และ spacing
|
||||
* ใช้ **Shadcn** components (Button, Input, Card, ฯลฯ) เพื่อ UI ที่สอดคล้องกัน
|
||||
* ทำให้ components มีขนาดเล็กและมุ่งเน้นการทำงานเฉพาะอย่าง
|
||||
* ใช้ utility classes สำหรับการจัดสไตล์อย่างรวดเร็ว (spacing, colors, text, ฯลฯ)
|
||||
* ตรวจสอบให้แน่ใจว่าสอดคล้องกับ **ARIA** และใช้ semantic markup
|
||||
- ใช้ **semantic HTML**
|
||||
- ใช้คลาสของ **Tailwind** ที่รองรับ responsive (sm:, md:, lg:)
|
||||
- รักษาลำดับชั้นของการมองเห็น (visual hierarchy) ด้วยการใช้ typography และ spacing
|
||||
- ใช้ **Shadcn** components (Button, Input, Card, ฯลฯ) เพื่อ UI ที่สอดคล้องกัน
|
||||
- ทำให้ components มีขนาดเล็กและมุ่งเน้นการทำงานเฉพาะอย่าง
|
||||
- ใช้ utility classes สำหรับการจัดสไตล์อย่างรวดเร็ว (spacing, colors, text, ฯลฯ)
|
||||
- ตรวจสอบให้แน่ใจว่าสอดคล้องกับ **ARIA** และใช้ semantic markup
|
||||
|
||||
### **การตรวจสอบฟอร์มและข้อผิดพลาด (Form Validation & Errors)**
|
||||
|
||||
* ใช้ไลบรารีฝั่ง client เช่น zod และ react-hook-form
|
||||
* แสดงข้อผิดพลาดด้วย **alert components** หรือข้อความ inline
|
||||
* ต้องมี labels, placeholders, และข้อความ feedback
|
||||
- ใช้ไลบรารีฝั่ง client เช่น zod และ react-hook-form
|
||||
- แสดงข้อผิดพลาดด้วย **alert components** หรือข้อความ inline
|
||||
- ต้องมี labels, placeholders, และข้อความ feedback
|
||||
|
||||
### **🧪 Frontend Testing**
|
||||
|
||||
เราจะใช้ **React Testing Library (RTL)** สำหรับการทดสอบ Component และ **Playwright** สำหรับ E2E:
|
||||
|
||||
* **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
* **เครื่องมือ:** Vitest + RTL
|
||||
* **เป้าหมาย:** ทดสอบ Component ขนาดเล็ก (เช่น Buttons, Inputs) หรือ Utility functions
|
||||
* **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
* **เครื่องมือ:** RTL + **Mock Service Worker (MSW)**
|
||||
* **เป้าหมาย:** ทดสอบว่า Component หรือ Page ทำงานกับ API (ที่จำลองขึ้น) ได้ถูกต้อง
|
||||
* **เทคนิค:** ใช้ MSW เพื่อจำลอง NestJS API และทดสอบว่า Component แสดงผลข้อมูลจำลองได้ถูกต้องหรือไม่ (เช่น ทดสอบหน้า Dashboard [cite: 5.3] ที่ดึงข้อมูลจาก v_user_tasks)
|
||||
* **E2E (End-to-End) Tests:**
|
||||
* **เครื่องมือ:** **Playwright**
|
||||
* **เป้าหมาย:** ทดสอบ User Flow ทั้งระบบโดยอัตโนมัติ (เช่น ล็อกอิน -> สร้าง RFA -> ตรวจสอบ Workflow Visualization [cite: 5.6])
|
||||
- **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
- **เครื่องมือ:** Vitest + RTL
|
||||
- **เป้าหมาย:** ทดสอบ Component ขนาดเล็ก (เช่น Buttons, Inputs) หรือ Utility functions
|
||||
- **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
- **เครื่องมือ:** RTL + **Mock Service Worker (MSW)**
|
||||
- **เป้าหมาย:** ทดสอบว่า Component หรือ Page ทำงานกับ API (ที่จำลองขึ้น) ได้ถูกต้อง
|
||||
- **เทคนิค:** ใช้ MSW เพื่อจำลอง NestJS API และทดสอบว่า Component แสดงผลข้อมูลจำลองได้ถูกต้องหรือไม่ (เช่น ทดสอบหน้า Dashboard [cite: 5.3] ที่ดึงข้อมูลจาก v_user_tasks)
|
||||
- **E2E (End-to-End) Tests:**
|
||||
- **เครื่องมือ:** **Playwright**
|
||||
- **เป้าหมาย:** ทดสอบ User Flow ทั้งระบบโดยอัตโนมัติ (เช่น ล็อกอิน -> สร้าง RFA -> ตรวจสอบ Workflow Visualization [cite: 5.6])
|
||||
|
||||
### **🗄️ Frontend State Management**
|
||||
|
||||
สำหรับ Next.js App Router เราจะแบ่ง State เป็น 4 ระดับ:
|
||||
|
||||
1. **Local UI State (สถานะ UI ชั่วคราว):**
|
||||
* **เครื่องมือ:** useState, useReducer
|
||||
* **ใช้เมื่อ:** จัดการสถานะเล็กๆ ที่จบใน Component เดียว (เช่น Modal เปิด/ปิด, ค่าใน Input)
|
||||
- **เครื่องมือ:** useState, useReducer
|
||||
- **ใช้เมื่อ:** จัดการสถานะเล็กๆ ที่จบใน Component เดียว (เช่น Modal เปิด/ปิด, ค่าใน Input)
|
||||
2. **Server State (สถานะข้อมูลจากเซิร์ฟเวอร์):**
|
||||
* **เครื่องมือ:** **React Query (TanStack Query)** หรือ SWR
|
||||
* **ใช้เมื่อ:** จัดการข้อมูลที่ดึงมาจาก NestJS API (เช่น รายการ correspondences, rfas, drawings)
|
||||
* **ทำไม:** React Query เป็น "Cache" ที่จัดการ Caching, Re-fetching, และ Invalidation ให้โดยอัตโนมัติ
|
||||
- **เครื่องมือ:** **React Query (TanStack Query)** หรือ SWR
|
||||
- **ใช้เมื่อ:** จัดการข้อมูลที่ดึงมาจาก NestJS API (เช่น รายการ correspondences, rfas, drawings)
|
||||
- **ทำไม:** React Query เป็น "Cache" ที่จัดการ Caching, Re-fetching, และ Invalidation ให้โดยอัตโนมัติ
|
||||
3. **Global Client State (สถานะส่วนกลางฝั่ง Client):**
|
||||
* **เครื่องมือ:** **Zustand** (แนะนำ) หรือ Context API
|
||||
* **ใช้เมื่อ:** จัดการข้อมูลที่ต้องใช้ร่วมกันทั่วทั้งแอป และ *ไม่ใช่* ข้อมูลจากเซิร์ฟเวอร์ (เช่น ข้อมูล User ที่ล็อกอิน, สิทธิ์ Permissions)
|
||||
- **เครื่องมือ:** **Zustand** (แนะนำ) หรือ Context API
|
||||
- **ใช้เมื่อ:** จัดการข้อมูลที่ต้องใช้ร่วมกันทั่วทั้งแอป และ _ไม่ใช่_ ข้อมูลจากเซิร์ฟเวอร์ (เช่น ข้อมูล User ที่ล็อกอิน, สิทธิ์ Permissions)
|
||||
4. **Form State (สถานะของฟอร์ม):**
|
||||
* **เครื่องมือ:** **React Hook Form** + **Zod**
|
||||
* **ใช้เมื่อ:** จัดการฟอร์มที่ซับซ้อน (เช่น ฟอร์มสร้าง RFA, ฟอร์ม Circulation [cite: 3.7])
|
||||
- **เครื่องมือ:** **React Hook Form** + **Zod**
|
||||
- **ใช้เมื่อ:** จัดการฟอร์มที่ซับซ้อน (เช่น ฟอร์มสร้าง RFA, ฟอร์ม Circulation [cite: 3.7])
|
||||
|
||||
# **🔗 แนวทางการบูรณาการ Full Stack (Full Stack Integration Guidelines)**
|
||||
|
||||
| Aspect (แง่มุม) | Backend (NestJS) | Frontend (NextJS) | UI Layer (Tailwind/Shadcn) |
|
||||
| :---- | :---- | :---- | :---- |
|
||||
| API | REST / GraphQL Controllers | API hooks ผ่าน fetch/axios/SWR | Components ที่รับข้อมูล |
|
||||
| Validation (การตรวจสอบ) | class-validator DTOs | zod / react-hook-form | สถานะของฟอร์ม/input ใน Shadcn |
|
||||
| Auth (การยืนยันตัวตน) | Guards, JWT | NextAuth / cookies | สถานะ UI ของ Auth (loading, signed in) |
|
||||
| Errors (ข้อผิดพลาด) | Global filters | Toasts / modals | Alerts / ข้อความ feedback |
|
||||
| Testing (การทดสอบ) | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles (สไตล์) | Scoped modules (ถ้าจำเป็น) | Tailwind / Shadcn | Tailwind utilities |
|
||||
| Accessibility (การเข้าถึง) | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
| Aspect (แง่มุม) | Backend (NestJS) | Frontend (NextJS) | UI Layer (Tailwind/Shadcn) |
|
||||
| :------------------------- | :------------------------- | :----------------------------- | :------------------------------------- |
|
||||
| API | REST / GraphQL Controllers | API hooks ผ่าน fetch/axios/SWR | Components ที่รับข้อมูล |
|
||||
| Validation (การตรวจสอบ) | class-validator DTOs | zod / react-hook-form | สถานะของฟอร์ม/input ใน Shadcn |
|
||||
| Auth (การยืนยันตัวตน) | Guards, JWT | NextAuth / cookies | สถานะ UI ของ Auth (loading, signed in) |
|
||||
| Errors (ข้อผิดพลาด) | Global filters | Toasts / modals | Alerts / ข้อความ feedback |
|
||||
| Testing (การทดสอบ) | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles (สไตล์) | Scoped modules (ถ้าจำเป็น) | Tailwind / Shadcn | Tailwind utilities |
|
||||
| Accessibility (การเข้าถึง) | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
|
||||
## **🗂️ ข้อตกลงเฉพาะสำหรับ DMS (LCBP3-DMS)**
|
||||
|
||||
@@ -318,25 +318,25 @@ Backend (NestJS) ควรเป็น **Stateless** (ไม่เก็บส
|
||||
@RequirePermission('rfas.respond') // ต้องตรงกับ 'permission\code'
|
||||
@Put(':id')
|
||||
updateRFA(@Param('id') id: string) {
|
||||
return this.rfaService.update(id);
|
||||
return this.rfaService.update(id);
|
||||
}
|
||||
|
||||
### **Roles (บทบาท)**
|
||||
|
||||
* **Superadmin**: ไม่มีข้อจำกัดใดๆ [cite: 4.3]
|
||||
* **Admin**: มีสิทธิ์เต็มที่ในองค์กร [cite: 4.3]
|
||||
* **Document Control**: เพิ่ม/แก้ไข/ลบ เอกสารในองค์กร [cite: 4.3]
|
||||
* **Editor**: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนด [cite: 4.3]
|
||||
* **Viewer**: สามารถดู เอกสาร [cite: 4.3]
|
||||
- **Superadmin**: ไม่มีข้อจำกัดใดๆ [cite: 4.3]
|
||||
- **Admin**: มีสิทธิ์เต็มที่ในองค์กร [cite: 4.3]
|
||||
- **Document Control**: เพิ่ม/แก้ไข/ลบ เอกสารในองค์กร [cite: 4.3]
|
||||
- **Editor**: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนด [cite: 4.3]
|
||||
- **Viewer**: สามารถดู เอกสาร [cite: 4.3]
|
||||
|
||||
### **ตัวอย่าง Permissions (จากตาราง permissions)**
|
||||
|
||||
* rfas.view, rfas.create, rfas.respond, rfas.delete
|
||||
* drawings.view, drawings.upload, drawings.delete
|
||||
* corr.view, corr.manage
|
||||
* transmittals.manage
|
||||
* cirs.manage
|
||||
* project\parties.manage
|
||||
- rfas.view, rfas.create, rfas.respond, rfas.delete
|
||||
- drawings.view, drawings.upload, drawings.delete
|
||||
- corr.view, corr.manage
|
||||
- transmittals.manage
|
||||
- cirs.manage
|
||||
- project\parties.manage
|
||||
|
||||
การจับคู่ระหว่าง roles และ permissions **เริ่มต้น** จะถูก seed ผ่านสคริปต์ (ดังที่เห็นในไฟล์ SQL)**อย่างไรก็ตาม AuthModule/UserModule ต้องมี API สำหรับ Admin เพื่อสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลัง** [cite: 4.3]
|
||||
|
||||
@@ -344,33 +344,33 @@ updateRFA(@Param('id') id: string) {
|
||||
|
||||
บันทึกการดำเนินการ CRUD และการจับคู่ทั้งหมดลงในตาราง audit_logs
|
||||
|
||||
| Field (ฟิลด์) | Type (จาก SQL) | Description (คำอธิบาย) |
|
||||
| :---- | :---- | :---- |
|
||||
| audit_id | BIGINT | Primary Key |
|
||||
| user_id | INT | ผู้ใช้ที่ดำเนินการ (FK -> users) |
|
||||
| action | VARCHAR(100) | rfa.create, correspondence.update, login.success |
|
||||
| entity_type | VARCHAR(50) | ชื่อตาราง/โมดูล เช่น 'rfa', 'correspondence' |
|
||||
| entity_id | VARCHAR(50) | Primary ID ของระเบียนที่ได้รับผลกระทบ |
|
||||
| details_json | JSON | ข้อมูลบริบท (เช่น ฟิลด์ที่มีการเปลี่ยนแปลง) |
|
||||
| ip_address | VARCHAR(45) | IP address ของผู้ดำเนินการ |
|
||||
| user_agent | VARCHAR(255) | User Agent ของผู้ดำเนินการ |
|
||||
| created_at | TIMESTAMP | Timestamp (UTC) |
|
||||
| Field (ฟิลด์) | Type (จาก SQL) | Description (คำอธิบาย) |
|
||||
| :------------ | :------------- | :----------------------------------------------- |
|
||||
| audit_id | BIGINT | Primary Key |
|
||||
| user_id | INT | ผู้ใช้ที่ดำเนินการ (FK -> users) |
|
||||
| action | VARCHAR(100) | rfa.create, correspondence.update, login.success |
|
||||
| entity_type | VARCHAR(50) | ชื่อตาราง/โมดูล เช่น 'rfa', 'correspondence' |
|
||||
| entity_id | VARCHAR(50) | Primary ID ของระเบียนที่ได้รับผลกระทบ |
|
||||
| details_json | JSON | ข้อมูลบริบท (เช่น ฟิลด์ที่มีการเปลี่ยนแปลง) |
|
||||
| ip_address | VARCHAR(45) | IP address ของผู้ดำเนินการ |
|
||||
| user_agent | VARCHAR(255) | User Agent ของผู้ดำเนินการ |
|
||||
| created_at | TIMESTAMP | Timestamp (UTC) |
|
||||
|
||||
## **📂 การจัดการไฟล์ (File Handling) (ปรับปรุงใหม่)**
|
||||
|
||||
### **มาตรฐานการอัปโหลดไฟล์ (File Upload Standard)**
|
||||
|
||||
* **ตรรกะใหม่:** การอัปโหลดไฟล์ทั้งหมดจะถูกจัดการโดย FileStorageService และบันทึกข้อมูลไฟล์ลงในตาราง attachments (ตารางกลาง)
|
||||
* ไฟล์จะถูกเชื่อมโยงไปยัง Entity ที่ถูกต้องผ่าน **ตารางเชื่อม (Junction Tables)** เท่านั้น:
|
||||
* correspondence_attachments (เชื่อม Correspondence กับ Attachments)
|
||||
* circulation_attachments (เชื่อม Circulation กับ Attachments)
|
||||
* shop_drawing_revision_attachments (เชื่อม Shop Drawing Revision กับ Attachments)
|
||||
* contract_drawing_attachments (เชื่อม Contract Drawing กับ Attachments)
|
||||
* เส้นทางจัดเก็บไฟล์ (Upload path): อ้างอิงจาก Requirement 2.1 คือ /share/dms-data [cite: 2.1] โดย FileStorageService จะสร้างโฟลเดอร์ย่อยแบบรวมศูนย์ (เช่น /share/dms-data/uploads/{YYYY}/{MM}/[stored\filename])
|
||||
* ประเภทไฟล์ที่อนุญาต: pdf, dwg, docx, xlsx, zip
|
||||
* ขนาดสูงสุด: **50 MB**
|
||||
* จัดเก็บนอก webroot
|
||||
* ให้บริการไฟล์ผ่าน endpoint ที่ปลอดภัย /files/:attachment_id/download
|
||||
- **ตรรกะใหม่:** การอัปโหลดไฟล์ทั้งหมดจะถูกจัดการโดย FileStorageService และบันทึกข้อมูลไฟล์ลงในตาราง attachments (ตารางกลาง)
|
||||
- ไฟล์จะถูกเชื่อมโยงไปยัง Entity ที่ถูกต้องผ่าน **ตารางเชื่อม (Junction Tables)** เท่านั้น:
|
||||
- correspondence_attachments (เชื่อม Correspondence กับ Attachments)
|
||||
- circulation_attachments (เชื่อม Circulation กับ Attachments)
|
||||
- shop_drawing_revision_attachments (เชื่อม Shop Drawing Revision กับ Attachments)
|
||||
- contract_drawing_attachments (เชื่อม Contract Drawing กับ Attachments)
|
||||
- เส้นทางจัดเก็บไฟล์ (Upload path): อ้างอิงจาก Requirement 2.1 คือ /share/dms-data [cite: 2.1] โดย FileStorageService จะสร้างโฟลเดอร์ย่อยแบบรวมศูนย์ (เช่น /share/dms-data/uploads/{YYYY}/{MM}/[stored\filename])
|
||||
- ประเภทไฟล์ที่อนุญาต: pdf, dwg, docx, xlsx, zip
|
||||
- ขนาดสูงสุด: **50 MB**
|
||||
- จัดเก็บนอก webroot
|
||||
- ให้บริการไฟล์ผ่าน endpoint ที่ปลอดภัย /files/:attachment_id/download
|
||||
|
||||
### **การควบคุมการเข้าถึง (Access Control)**
|
||||
|
||||
@@ -382,15 +382,15 @@ updateRFA(@Param('id') id: string) {
|
||||
|
||||
## **🔟 การจัดการเลขที่เอกสาร (Document Numbering) [cite: 3.10]**
|
||||
|
||||
* **เป้าหมาย:** สร้างเลขที่เอกสาร (เช่น correspondence\number) โดยอัตโนมัติ ตามรูปแบบที่กำหนด
|
||||
* **ตรรกะการนับ:** การนับ Running number (SEQ) จะนับแยกตาม Key: **Project + Originator Organization + Document Type + Year**
|
||||
* **ตาราง SQL:**
|
||||
* document_number_formats: Admin ใช้กำหนด "รูปแบบ" (Template) ของเลขที่ (เช่น {ORG\CODE}-{TYPE\CODE}-{YEAR\SHORT}-{SEQ:4}) โดยกำหนดตาม **Project** และ **Document Type** [cite: 4.5]
|
||||
* document_number_counters: ระบบใช้เก็บ "ตัวนับ" ล่าสุดของ Key (Project+Org+Type+Year)
|
||||
* **การทำงาน (Backend):**
|
||||
* DocumentNumberingModule จะให้บริการ DocumentNumberingService
|
||||
* เมื่อ CorrespondenceModule ต้องการสร้างเอกสารใหม่, มันจะเรียก documentNumberingService.generateNextNumber(...)
|
||||
* Service นี้จะเรียกใช้ Stored Procedure **sp_get_next_document_number** [cite: 2.9.3] ซึ่ง Procedure นี้จะจัดการ Database Transaction และ Row Lock (FOR UPDATE) ภายใน DB เพื่อรับประกันการป้องกัน Race Condition
|
||||
- **เป้าหมาย:** สร้างเลขที่เอกสาร (เช่น correspondence\number) โดยอัตโนมัติ ตามรูปแบบที่กำหนด
|
||||
- **ตรรกะการนับ:** การนับ Running number (SEQ) จะนับแยกตาม Key: **Project + Originator Organization + Document Type + Year**
|
||||
- **ตาราง SQL:**
|
||||
- document_number_formats: Admin ใช้กำหนด "รูปแบบ" (Template) ของเลขที่ (เช่น {ORG\CODE}-{TYPE\CODE}-{YEAR\SHORT}-{SEQ:4}) โดยกำหนดตาม **Project** และ **Document Type** [cite: 4.5]
|
||||
- document_number_counters: ระบบใช้เก็บ "ตัวนับ" ล่าสุดของ Key (Project+Org+Type+Year)
|
||||
- **การทำงาน (Backend):**
|
||||
- DocumentNumberingModule จะให้บริการ DocumentNumberingService
|
||||
- เมื่อ CorrespondenceModule ต้องการสร้างเอกสารใหม่, มันจะเรียก documentNumberingService.generateNextNumber(...)
|
||||
- Service นี้จะเรียกใช้ Stored Procedure **sp_get_next_document_number** [cite: 2.9.3] ซึ่ง Procedure นี้จะจัดการ Database Transaction และ Row Lock (FOR UPDATE) ภายใน DB เพื่อรับประกันการป้องกัน Race Condition
|
||||
|
||||
## **📊 การรายงานและการส่งออก (Reporting & Exports)**
|
||||
|
||||
@@ -398,81 +398,81 @@ updateRFA(@Param('id') id: string) {
|
||||
|
||||
การรายงานควรสร้างขึ้นจาก Views ที่กำหนดไว้ล่วงหน้าในฐานข้อมูลเป็นหลัก:
|
||||
|
||||
* v_current_correspondences: สำหรับ revision ปัจจุบันทั้งหมดของเอกสารที่ไม่ใช่ RFA
|
||||
* v_current_rfas: สำหรับ revision ปัจจุบันทั้งหมดของ RFA และข้อมูล master
|
||||
* v_contract_parties_all: สำหรับการตรวจสอบความสัมพันธ์ของ project/contract/organization
|
||||
* v_user_tasks: สำหรับ Dashboard "งานของฉัน"
|
||||
* v_audit_log_details: สำหรับ Activity Feed
|
||||
- v_current_correspondences: สำหรับ revision ปัจจุบันทั้งหมดของเอกสารที่ไม่ใช่ RFA
|
||||
- v_current_rfas: สำหรับ revision ปัจจุบันทั้งหมดของ RFA และข้อมูล master
|
||||
- v_contract_parties_all: สำหรับการตรวจสอบความสัมพันธ์ของ project/contract/organization
|
||||
- v_user_tasks: สำหรับ Dashboard "งานของฉัน"
|
||||
- v_audit_log_details: สำหรับ Activity Feed
|
||||
|
||||
Views เหล่านี้ทำหน้าที่เป็นแหล่งข้อมูลหลักสำหรับการรายงานฝั่งเซิร์ฟเวอร์และการส่งออกข้อมูล
|
||||
|
||||
### **กฎการส่งออก (Export Rules)**
|
||||
|
||||
* Export formats: CSV, Excel, PDF.
|
||||
* จัดเตรียมมุมมองสำหรับพิมพ์ (Print view).
|
||||
* รวมลิงก์ไปยังต้นทาง (เช่น /rfas/:id).
|
||||
- Export formats: CSV, Excel, PDF.
|
||||
- จัดเตรียมมุมมองสำหรับพิมพ์ (Print view).
|
||||
- รวมลิงก์ไปยังต้นทาง (เช่น /rfas/:id).
|
||||
|
||||
## **🧮 ฟรอนต์เอนด์: รูปแบบ DataTable และฟอร์ม (Frontend: DataTable & Form Patterns)**
|
||||
|
||||
### **DataTable (Server‑Side)**
|
||||
|
||||
* Endpoint: /api/{module}?page=1\&pageSize=20\&sort=...\&filter=...
|
||||
* ต้องรองรับ: การแบ่งหน้า (pagination), การเรียงลำดับ (sorting), การค้นหา (search), การกรอง (filters)
|
||||
* แสดง revision ล่าสุดแบบ inline เสมอ (สำหรับ RFA/Drawing)
|
||||
- Endpoint: /api/{module}?page=1\&pageSize=20\&sort=...\&filter=...
|
||||
- ต้องรองรับ: การแบ่งหน้า (pagination), การเรียงลำดับ (sorting), การค้นหา (search), การกรอง (filters)
|
||||
- แสดง revision ล่าสุดแบบ inline เสมอ (สำหรับ RFA/Drawing)
|
||||
|
||||
### **มาตรฐานฟอร์ม (Form Standards)**
|
||||
|
||||
* ต้องมีการใช้งาน Dropdowns แบบขึ้นต่อกัน (Dependent dropdowns) (ตามที่สคีมารองรับ):
|
||||
* Project → Contract Drawing Volumes
|
||||
* Contract Drawing Category → Sub-Category
|
||||
* RFA (ประเภท Shop Drawing) → Shop Drawing Revisions ที่เชื่อมโยงได้
|
||||
* **(ใหม่)** การอัปโหลดไฟล์: ต้องรองรับ **Multi-file upload (Drag-and-Drop)** [cite: 5.7]
|
||||
* **(ใหม่)** UI ต้องอนุญาตให้ผู้ใช้กำหนดว่าไฟล์ใดเป็น **"เอกสารหลัก"** หรือ "เอกสารแนบประกอบ" [cite: 5.7]
|
||||
* ส่ง (Submit) ผ่าน API พร้อม feedback แบบ toast
|
||||
- ต้องมีการใช้งาน Dropdowns แบบขึ้นต่อกัน (Dependent dropdowns) (ตามที่สคีมารองรับ):
|
||||
- Project → Contract Drawing Volumes
|
||||
- Contract Drawing Category → Sub-Category
|
||||
- RFA (ประเภท Shop Drawing) → Shop Drawing Revisions ที่เชื่อมโยงได้
|
||||
- **(ใหม่)** การอัปโหลดไฟล์: ต้องรองรับ **Multi-file upload (Drag-and-Drop)** [cite: 5.7]
|
||||
- **(ใหม่)** UI ต้องอนุญาตให้ผู้ใช้กำหนดว่าไฟล์ใดเป็น **"เอกสารหลัก"** หรือ "เอกสารแนบประกอบ" [cite: 5.7]
|
||||
- ส่ง (Submit) ผ่าน API พร้อม feedback แบบ toast
|
||||
|
||||
### **ข้อกำหนด Component เฉพาะ (Specific UI Requirements)**
|
||||
|
||||
* **Dashboard \- My Tasks:** ต้องพัฒนา Component ตาราง "งานของฉัน" (My Tasks)ซึ่งดึงข้อมูลงานที่ผู้ใช้ล็อกอินอยู่ต้องรับผิดชอบ (Main/Action) จาก v\user\tasks [cite: 5.3]
|
||||
* **Workflow Visualization:** ต้องพัฒนา Component สำหรับแสดงผล Workflow (โดยเฉพาะ RFA)ที่แสดงขั้นตอนทั้งหมดเป็นลำดับ โดยขั้นตอนปัจจุบัน (active) เท่านั้นที่ดำเนินการได้ และขั้นตอนอื่นเป็น disabled [cite: 5.6] ต้องมีตรรกะสำหรับ Admin ในการ override หรือย้อนกลับขั้นตอนได้ [cite: 5.6]
|
||||
* ** Admin Panel:** ต้องมีหน้า UI สำหรับ Superadmin/Admin เพื่อจัดการข้อมูลหลัก (Master Data [cite: 4.5]), การเริ่มต้นใช้งาน (Onboarding [cite: 4.6]), และ **รูปแบบเลขที่เอกสาร (Numbering Formats [cite: 3.10])**
|
||||
- **Dashboard \- My Tasks:** ต้องพัฒนา Component ตาราง "งานของฉัน" (My Tasks)ซึ่งดึงข้อมูลงานที่ผู้ใช้ล็อกอินอยู่ต้องรับผิดชอบ (Main/Action) จาก v\user\tasks [cite: 5.3]
|
||||
- **Workflow Visualization:** ต้องพัฒนา Component สำหรับแสดงผล Workflow (โดยเฉพาะ RFA)ที่แสดงขั้นตอนทั้งหมดเป็นลำดับ โดยขั้นตอนปัจจุบัน (active) เท่านั้นที่ดำเนินการได้ และขั้นตอนอื่นเป็น disabled [cite: 5.6] ต้องมีตรรกะสำหรับ Admin ในการ override หรือย้อนกลับขั้นตอนได้ [cite: 5.6]
|
||||
- ** Admin Panel:** ต้องมีหน้า UI สำหรับ Superadmin/Admin เพื่อจัดการข้อมูลหลัก (Master Data [cite: 4.5]), การเริ่มต้นใช้งาน (Onboarding [cite: 4.6]), และ **รูปแบบเลขที่เอกสาร (Numbering Formats [cite: 3.10])**
|
||||
|
||||
## **🧭 แดชบอร์ดและฟีดกิจกรรม (Dashboard & Activity Feed)**
|
||||
|
||||
### **การ์ดบนแดชบอร์ด (Dashboard Cards)**
|
||||
|
||||
* แสดง Correspondences, RFAs, Circulations, Shop Drawing Revision ล่าสุด
|
||||
* รวมสรุป KPI (เช่น "RFAs ที่รอการอนุมัติ", "Shop Drawing ที่รอการอนุมัติ") [cite: 5.3]
|
||||
* รวมลิงก์ด่วนไปยังโมดูลต่างๆ
|
||||
- แสดง Correspondences, RFAs, Circulations, Shop Drawing Revision ล่าสุด
|
||||
- รวมสรุป KPI (เช่น "RFAs ที่รอการอนุมัติ", "Shop Drawing ที่รอการอนุมัติ") [cite: 5.3]
|
||||
- รวมลิงก์ด่วนไปยังโมดูลต่างๆ
|
||||
|
||||
### **ฟีดกิจกรรม (Activity Feed)**
|
||||
|
||||
* แสดงรายการ v\audit\log\details ล่าสุด (10 รายการ) ที่เกี่ยวข้องกับผู้ใช้
|
||||
- แสดงรายการ v\audit\log\details ล่าสุด (10 รายการ) ที่เกี่ยวข้องกับผู้ใช้
|
||||
|
||||
// ตัวอย่าง API response
|
||||
[
|
||||
{ user: 'editor01', action: 'Updated RFA (LCBP3-RFA-001)', time: '2025-11-04T09:30Z' }
|
||||
{ user: 'editor01', action: 'Updated RFA (LCBP3-RFA-001)', time: '2025-11-04T09:30Z' }
|
||||
]
|
||||
|
||||
## **🛡️ ข้อกำหนดที่ไม่ใช่ฟังก์ชันการทำงาน (Non-Functional Requirements)**
|
||||
|
||||
ส่วนนี้สรุปข้อกำหนด Non-Functional จาก requirements.md เพื่อให้ทีมพัฒนาทราบ
|
||||
|
||||
* **Audit Log [cite: 6.1]:** ทุกการกระทำที่สำคัญ (C/U/D) ต้องถูกบันทึกใน audit_logs
|
||||
* **Performance [cite: 6.4]:** ต้องใช้ Caching สำหรับข้อมูลที่เรียกบ่อย และใช้ Pagination
|
||||
* **Security [cite: 6.5]:** ต้องมี Rate Limiting และจัดการ Secret ผ่าน docker-compose.yml (ไม่ใช่ .env)
|
||||
* **(ใหม่) Backup & Recovery [cite: 6.6]:** ต้องมีแผนสำรองข้อมูลทั้ง Database (MariaDB) และ File Storage (/share/dms-data) อย่างน้อยวันละ 1 ครั้ง
|
||||
* **(ใหม่) Notification Strategy [cite: 6.7]:** ระบบแจ้งเตือน (Email/Line) ต้องถูก Trigger เมื่อมีเอกสารใหม่ส่งถึง, มีการมอบหมายงานใหม่ (Circulation), หรือ (ทางเลือก) เมื่องานเสร็จ/ใกล้ถึงกำหนด
|
||||
- **Audit Log [cite: 6.1]:** ทุกการกระทำที่สำคัญ (C/U/D) ต้องถูกบันทึกใน audit_logs
|
||||
- **Performance [cite: 6.4]:** ต้องใช้ Caching สำหรับข้อมูลที่เรียกบ่อย และใช้ Pagination
|
||||
- **Security [cite: 6.5]:** ต้องมี Rate Limiting และจัดการ Secret ผ่าน docker-compose.yml (ไม่ใช่ .env)
|
||||
- **(ใหม่) Backup & Recovery [cite: 6.6]:** ต้องมีแผนสำรองข้อมูลทั้ง Database (MariaDB) และ File Storage (/share/dms-data) อย่างน้อยวันละ 1 ครั้ง
|
||||
- **(ใหม่) Notification Strategy [cite: 6.7]:** ระบบแจ้งเตือน (Email/Line) ต้องถูก Trigger เมื่อมีเอกสารใหม่ส่งถึง, มีการมอบหมายงานใหม่ (Circulation), หรือ (ทางเลือก) เมื่องานเสร็จ/ใกล้ถึงกำหนด
|
||||
|
||||
## **✅ มาตรฐานที่นำไปใช้แล้ว (จาก SQL v1.1.0) (Implemented Standards (from SQL v1.1.0))**
|
||||
|
||||
ส่วนนี้ยืนยันว่าแนวทางปฏิบัติที่ดีที่สุดต่อไปนี้เป็นส่วนหนึ่งของการออกแบบฐานข้อมูลอยู่แล้ว และควรถูกนำไปใช้ประโยชน์ ไม่ใช่สร้างขึ้นใหม่
|
||||
|
||||
* ✅ **Soft Delete:** นำไปใช้แล้วผ่านคอลัมน์ deleted_at ในตารางสำคัญ (เช่น correspondences, rfas, project_parties) ตรรกะการดึงข้อมูลต้องกรอง deleted_at IS NULL
|
||||
* ✅ **Database Indexes:** สคีมาได้มีการทำ index ไว้อย่างหนักหน่วงบน foreign keys และคอลัมน์ที่ใช้ค้นหาบ่อย (เช่น idx_rr_rfa, idx_cor_project, idx_cr_is_current) เพื่อประสิทธิภาพ
|
||||
* ✅ **โครงสร้าง RBAC:** มีระบบ users, roles, permissions, user_roles, และ user_project_roles ที่ครอบคลุมอยู่แล้ว
|
||||
* ✅ **Data Seeding:** ข้อมูล Master (roles, permissions, organization_roles, initial users, project parties) ถูกรวมอยู่ในสคริปต์สคีมาแล้ว
|
||||
- ✅ **Soft Delete:** นำไปใช้แล้วผ่านคอลัมน์ deleted_at ในตารางสำคัญ (เช่น correspondences, rfas, project_parties) ตรรกะการดึงข้อมูลต้องกรอง deleted_at IS NULL
|
||||
- ✅ **Database Indexes:** สคีมาได้มีการทำ index ไว้อย่างหนักหน่วงบน foreign keys และคอลัมน์ที่ใช้ค้นหาบ่อย (เช่น idx_rr_rfa, idx_cor_project, idx_cr_is_current) เพื่อประสิทธิภาพ
|
||||
- ✅ **โครงสร้าง RBAC:** มีระบบ users, roles, permissions, user_roles, และ user_project_roles ที่ครอบคลุมอยู่แล้ว
|
||||
- ✅ **Data Seeding:** ข้อมูล Master (roles, permissions, organization_roles, initial users, project parties) ถูกรวมอยู่ในสคริปต์สคีมาแล้ว
|
||||
|
||||
## **🧩 การปรับปรุงที่แนะนำ (สำหรับอนาคต) (Recommended Enhancements (Future))**
|
||||
|
||||
* ✅ สร้าง Background job (โดยใช้ **n8n** เพื่อเชื่อมต่อกับ **Line** [cite: 2.7] และ/หรือใช้สำหรับการแจ้งเตือน RFA ที่ใกล้ถึงกำหนด due_date [cite: 6.7])
|
||||
* ✅ เพิ่ม job ล้างข้อมูลเป็นระยะสำหรับ attachments ที่ไม่ถูกเชื่อมโยงกับ Entity ใดๆ เลย (ไฟล์กำพร้า)
|
||||
- ✅ สร้าง Background job (โดยใช้ **n8n** เพื่อเชื่อมต่อกับ **Line** [cite: 2.7] และ/หรือใช้สำหรับการแจ้งเตือน RFA ที่ใกล้ถึงกำหนด due_date [cite: 6.7])
|
||||
- ✅ เพิ่ม job ล้างข้อมูลเป็นระยะสำหรับ attachments ที่ไม่ถูกเชื่อมโยงกับ Entity ใดๆ เลย (ไฟล์กำพร้า)
|
||||
|
||||
@@ -4,40 +4,40 @@
|
||||
|
||||
## **1\. วัตถุประสงค์ (Objectives)**
|
||||
|
||||
* เพื่อให้มั่นใจว่า API ทั้งหมดทำงานตรงตาม requirements.md
|
||||
* เพื่อตรวจสอบว่าระบบรักษาความปลอดภัย (RBAC และ Security) ทำงานได้ถูกต้อง 100%
|
||||
* เพื่อค้นหาและแก้ไขข้อบกพร่อง (Bugs) ที่เกี่ยวข้องกับการเชื่อมต่อฐานข้อมูลและ Business Logic
|
||||
* เพื่อยืนยันว่าระบบทนทานต่อการใช้งานพร้อมกัน (Concurrency) และมีประสิทธิภาพ (Performance)
|
||||
* เพื่อส่งมอบ API ที่เสถียรและมีเอกสาร (Swagger) ครบถ้วนให้แก่ทีม Frontend
|
||||
- เพื่อให้มั่นใจว่า API ทั้งหมดทำงานตรงตาม requirements.md
|
||||
- เพื่อตรวจสอบว่าระบบรักษาความปลอดภัย (RBAC และ Security) ทำงานได้ถูกต้อง 100%
|
||||
- เพื่อค้นหาและแก้ไขข้อบกพร่อง (Bugs) ที่เกี่ยวข้องกับการเชื่อมต่อฐานข้อมูลและ Business Logic
|
||||
- เพื่อยืนยันว่าระบบทนทานต่อการใช้งานพร้อมกัน (Concurrency) และมีประสิทธิภาพ (Performance)
|
||||
- เพื่อส่งมอบ API ที่เสถียรและมีเอกสาร (Swagger) ครบถ้วนให้แก่ทีม Frontend
|
||||
|
||||
## **2\. ขอบเขตการทดสอบ (Scope)**
|
||||
|
||||
### **สิ่งที่อยู่ในขอบเขต (In-Scope)**
|
||||
|
||||
* **API Functionality:** การทดสอบ Endpoints ทั้งหมด (CRUD, Search, Upload)
|
||||
* **Business Logic:** ตรรกะการสร้างเอกสาร (RFA, Correspondence), การสร้างเลขที่, และ Workflow
|
||||
* **Security:** การยืนยันตัวตน (JWT), การจัดการสิทธิ์ (RBAC Guard), การป้องกัน (Helmet, Rate Limiter)
|
||||
* **Data Integrity:** การตรวจสอบความถูกต้องของข้อมูลที่บันทึกลง MariaDB
|
||||
* **Performance:** การทดสอบ Concurrency (การสร้างเลขที่) และการตอบสนองของ API
|
||||
* **Error Handling:** การตรวจสอบว่า Global Exception Filter ทำงานได้ถูกต้อง
|
||||
- **API Functionality:** การทดสอบ Endpoints ทั้งหมด (CRUD, Search, Upload)
|
||||
- **Business Logic:** ตรรกะการสร้างเอกสาร (RFA, Correspondence), การสร้างเลขที่, และ Workflow
|
||||
- **Security:** การยืนยันตัวตน (JWT), การจัดการสิทธิ์ (RBAC Guard), การป้องกัน (Helmet, Rate Limiter)
|
||||
- **Data Integrity:** การตรวจสอบความถูกต้องของข้อมูลที่บันทึกลง MariaDB
|
||||
- **Performance:** การทดสอบ Concurrency (การสร้างเลขที่) และการตอบสนองของ API
|
||||
- **Error Handling:** การตรวจสอบว่า Global Exception Filter ทำงานได้ถูกต้อง
|
||||
|
||||
### **สิ่งที่อยู่นอกขอบเขต (Out-of-Scope)**
|
||||
|
||||
* การทดสอบ Next.js Frontend (UI/UX)
|
||||
* การทดสอบตรรกะภายในของ N8N (เราทดสอบแค่ว่า Backend *ยิง* Webhook ไปหรือไม่)
|
||||
* การทดสอบ Penetration Test ขั้นสูง (เน้น Functional & Security พื้นฐาน)
|
||||
- การทดสอบ Next.js Frontend (UI/UX)
|
||||
- การทดสอบตรรกะภายในของ N8N (เราทดสอบแค่ว่า Backend _ยิง_ Webhook ไปหรือไม่)
|
||||
- การทดสอบ Penetration Test ขั้นสูง (เน้น Functional & Security พื้นฐาน)
|
||||
|
||||
## **3\. สภาพแวดล้อมและเครื่องมือ (Environment & Tools)**
|
||||
|
||||
| ประเภท | เครื่องมือ/สภาพแวดล้อม | วัตถุประสงค์ |
|
||||
| :---- | :---- | :---- |
|
||||
| **สภาพแวดล้อม** | **Staging (QNAP)** | สภาพแวดล้อมจำลอง (บน Docker) ที่เหมือน Production ที่สุด ประกอบด้วย backend, mariadb, elasticsearch, n8n (Mock Receiver) |
|
||||
| **ฐานข้อมูล** | **DBeaver** | ใช้สำหรับเชื่อมต่อ MariaDB (Staging) เพื่อตรวจสอบผลลัพธ์ (Data Verification) |
|
||||
| **API (Manual)** | **Postman / Insomnia** | ใช้สำหรับการทดสอบ API ด้วยตนเอง, สำรวจ Endpoints, และสร้าง Test Case |
|
||||
| **API (Automation)** | **Postman (Newman) / Supertest** | (E2E) ใช้รัน Test Case อัตโนมัติเพื่อตรวจสอบ API Contract |
|
||||
| **Unit/Integration** | **Jest / @nestjs/testing** | (Developer) ใช้สำหรับทดสอบ Logic ภายใน Service และ Guard (ตามตัวอย่าง spec.ts ที่สร้างไว้) |
|
||||
| **Concurrency** | **k6 (แนะนำ) / Node.js Script** | ใช้สำหรับทดสอบ Stress Test และ Concurrency (โดยเฉพาะ TC-CON-01) |
|
||||
| **Webhook** | **N8N (Webhook Node)** | ใช้ N8N จริง (Staging) ตั้งค่า Webhook Node เพื่อรับ Event จาก NotificationService |
|
||||
| ประเภท | เครื่องมือ/สภาพแวดล้อม | วัตถุประสงค์ |
|
||||
| :------------------- | :------------------------------- | :----------------------------------------------------------------------------------------------------------------------- |
|
||||
| **สภาพแวดล้อม** | **Staging (QNAP)** | สภาพแวดล้อมจำลอง (บน Docker) ที่เหมือน Production ที่สุด ประกอบด้วย backend, mariadb, elasticsearch, n8n (Mock Receiver) |
|
||||
| **ฐานข้อมูล** | **DBeaver** | ใช้สำหรับเชื่อมต่อ MariaDB (Staging) เพื่อตรวจสอบผลลัพธ์ (Data Verification) |
|
||||
| **API (Manual)** | **Postman / Insomnia** | ใช้สำหรับการทดสอบ API ด้วยตนเอง, สำรวจ Endpoints, และสร้าง Test Case |
|
||||
| **API (Automation)** | **Postman (Newman) / Supertest** | (E2E) ใช้รัน Test Case อัตโนมัติเพื่อตรวจสอบ API Contract |
|
||||
| **Unit/Integration** | **Jest / @nestjs/testing** | (Developer) ใช้สำหรับทดสอบ Logic ภายใน Service และ Guard (ตามตัวอย่าง spec.ts ที่สร้างไว้) |
|
||||
| **Concurrency** | **k6 (แนะนำ) / Node.js Script** | ใช้สำหรับทดสอบ Stress Test และ Concurrency (โดยเฉพาะ TC-CON-01) |
|
||||
| **Webhook** | **N8N (Webhook Node)** | ใช้ N8N จริง (Staging) ตั้งค่า Webhook Node เพื่อรับ Event จาก NotificationService |
|
||||
|
||||
## **4\. รายละเอียดสถานการณ์ทดสอบ (Detailed Test Scenarios)**
|
||||
|
||||
@@ -45,35 +45,34 @@
|
||||
|
||||
### **T1: การรักษาความปลอดภัย (Security & RBAC) \- (ความเสี่ยงสูงมาก)**
|
||||
|
||||
| ID | สถานการณ์ | ขั้นตอนการทดสอบ (Steps) | ผลลัพธ์ที่คาดหวัง (Expected) | เครื่องมือ |
|
||||
| :---- | :---- | :---- | :---- | :---- |
|
||||
| **TC-SEC-01** | **(RBAC) ห้าม Viewer สร้างเอกสาร** | 1\. (Postman) เรียก POST /api/v1/auth/login ด้วย User "Viewer" 2\. คัดลอก access\_token 3\. เรียก POST /api/v1/correspondence (ใน Auth Header) พร้อม Body ที่ถูกต้อง | 403 Forbidden (RBACGuard ทำงาน) | Postman |
|
||||
| **TC-SEC-02** | **(RBAC) Editor ข้าม Project** | 1\. (Postman) Login User "Editor" ที่มีสิทธิ์เฉพาะ Project A 2\. (DBeaver) หา ID เอกสาร (เช่น corr\_id: 99\) ที่อยู่ใน Project B 3\. (Postman) เรียก GET /api/v1/correspondence/99 ด้วย Token ของ Editor | 403 Forbidden หรือ 404 Not Found | Postman, DBeaver |
|
||||
| **TC-SEC-03** | **(RBAC) Super Admin** | 1\. (Postman) Login User "Super Admin" 2\. เรียก Endpoint ที่จำกัดสิทธิ์สูง (เช่น POST /api/v1/admin/users) | 201 Created (Super Admin ต้องผ่านทุกการตรวจสอบ) | Postman |
|
||||
| **TC-SEC-04** | **(Rate Limit) Brute-force** | 1\. (Postman Runner หรือ k6) ตั้งค่าให้เรียก POST /api/v1/auth/login (ด้วยรหัสผ่านผิด) 110 ครั้ง (Limit คือ 100\) 2\. สังเกตผลลัพธ์ | Request ที่ 1-100: 401 Unauthorized Request ที่ 101+: 429 Too Many Requests | k6, Postman |
|
||||
| **TC-SEC-05** | **(Security) Helmet** | 1\. (Postman) เรียก Endpoint ใดก็ได้ (เช่น GET /api/v1/health) 2\. ตรวจสอบ Response Headers | ต้องมี Headers เช่น X-Content-Type-Options: nosniff, Strict-Transport-Security, X-Frame-Options: SAMEORIGIN | Postman |
|
||||
| ID | สถานการณ์ | ขั้นตอนการทดสอบ (Steps) | ผลลัพธ์ที่คาดหวัง (Expected) | เครื่องมือ |
|
||||
| :------------ | :--------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | :---------------------------------------------------------------------------------------------------------- | :--------------- |
|
||||
| **TC-SEC-01** | **(RBAC) ห้าม Viewer สร้างเอกสาร** | 1\. (Postman) เรียก POST /api/v1/auth/login ด้วย User "Viewer" 2\. คัดลอก access_token 3\. เรียก POST /api/v1/correspondence (ใน Auth Header) พร้อม Body ที่ถูกต้อง | 403 Forbidden (RBACGuard ทำงาน) | Postman |
|
||||
| **TC-SEC-02** | **(RBAC) Editor ข้าม Project** | 1\. (Postman) Login User "Editor" ที่มีสิทธิ์เฉพาะ Project A 2\. (DBeaver) หา ID เอกสาร (เช่น corr_id: 99\) ที่อยู่ใน Project B 3\. (Postman) เรียก GET /api/v1/correspondence/99 ด้วย Token ของ Editor | 403 Forbidden หรือ 404 Not Found | Postman, DBeaver |
|
||||
| **TC-SEC-03** | **(RBAC) Super Admin** | 1\. (Postman) Login User "Super Admin" 2\. เรียก Endpoint ที่จำกัดสิทธิ์สูง (เช่น POST /api/v1/admin/users) | 201 Created (Super Admin ต้องผ่านทุกการตรวจสอบ) | Postman |
|
||||
| **TC-SEC-04** | **(Rate Limit) Brute-force** | 1\. (Postman Runner หรือ k6) ตั้งค่าให้เรียก POST /api/v1/auth/login (ด้วยรหัสผ่านผิด) 110 ครั้ง (Limit คือ 100\) 2\. สังเกตผลลัพธ์ | Request ที่ 1-100: 401 Unauthorized Request ที่ 101+: 429 Too Many Requests | k6, Postman |
|
||||
| **TC-SEC-05** | **(Security) Helmet** | 1\. (Postman) เรียก Endpoint ใดก็ได้ (เช่น GET /api/v1/health) 2\. ตรวจสอบ Response Headers | ต้องมี Headers เช่น X-Content-Type-Options: nosniff, Strict-Transport-Security, X-Frame-Options: SAMEORIGIN | Postman |
|
||||
|
||||
### **T2: ตรรกะหลัก (Core Logic & Concurrency) \- (ความเสี่ยงสูง)**
|
||||
|
||||
| ID | สถานการณ์ | ขั้นตอนการทดสอบ (Steps) | ผลลัพธ์ที่คาดหวัง (Expected) | เครื่องมือ |
|
||||
| :---- | :---- | :---- | :---- | :---- |
|
||||
| **TC-CON-01** | **(Concurrency) สร้างเลขที่เอกสาร** | 1\. (k6/Script) สร้าง Script ที่เรียก POST /api/v1/correspondence (สร้างเอกสารใหม่) 50 ครั้ง *พร้อมกัน* (Simultaneously) 2\. (Postman) Login Admin 3\. (DBeaver) ตรวจสอบตาราง correspondences และ document\_number\_counters | 1\. Script ทั้ง 50 ครั้งสำเร็จ (201 Created) 2\. (DBeaver) document\_number\_counters มี last\_number: 50 3\. correspondences มีเอกสาร 50 ฉบับ โดย *ไม่มี* correspondence\_number ซ้ำกันเลย | k6, DBeaver |
|
||||
| **TC-FUNC-01** | **(Data) สร้าง RFA (Complex)** | 1\. (Postman) Login User (เช่น "Editor") 2\. เรียก POST /api/v1/rfa พร้อม DTO ที่ซับซ้อน (มี rfa\_type\_id, title, attachments, shop\_drawings) | 1\. 201 Created 2\. (DBeaver) ตรวจสอบว่ามีข้อมูลถูกสร้างขึ้นใน 3 ตารางหลัก: \- correspondences (ตารางแม่) \- rfas (ตารางแม่ RFA) \- rfa\_revisions (ตารางลูก Revision 0\) | Postman, DBeaver |
|
||||
| ID | สถานการณ์ | ขั้นตอนการทดสอบ (Steps) | ผลลัพธ์ที่คาดหวัง (Expected) | เครื่องมือ |
|
||||
| :------------- | :---------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------- |
|
||||
| **TC-CON-01** | **(Concurrency) สร้างเลขที่เอกสาร** | 1\. (k6/Script) สร้าง Script ที่เรียก POST /api/v1/correspondence (สร้างเอกสารใหม่) 50 ครั้ง _พร้อมกัน_ (Simultaneously) 2\. (Postman) Login Admin 3\. (DBeaver) ตรวจสอบตาราง correspondences และ document_number_counters | 1\. Script ทั้ง 50 ครั้งสำเร็จ (201 Created) 2\. (DBeaver) document_number_counters มี last_number: 50 3\. correspondences มีเอกสาร 50 ฉบับ โดย _ไม่มี_ correspondence_number ซ้ำกันเลย | k6, DBeaver |
|
||||
| **TC-FUNC-01** | **(Data) สร้าง RFA (Complex)** | 1\. (Postman) Login User (เช่น "Editor") 2\. เรียก POST /api/v1/rfa พร้อม DTO ที่ซับซ้อน (มี rfa_type_id, title, attachments, shop_drawings) | 1\. 201 Created 2\. (DBeaver) ตรวจสอบว่ามีข้อมูลถูกสร้างขึ้นใน 3 ตารางหลัก: \- correspondences (ตารางแม่) \- rfas (ตารางแม่ RFA) \- rfa_revisions (ตารางลูก Revision 0\) | Postman, DBeaver |
|
||||
|
||||
### **T3: การทำงานของโมดูล (Module Functionality)**
|
||||
|
||||
| ID | สถานการณ์ | ขั้นตอนการทดสอบ (Steps) | ผลลัพธ์ที่คาดหวัง (Expected) | เครื่องมือ |
|
||||
| :---- | :---- | :---- | :---- | :---- |
|
||||
| **TC-FUNC-02** | **(File) อัปโหลดไฟล์** | 1\. (Postman) Login User 2\. เรียก POST /api/v1/files/upload (ประเภท form-data, key file) 3\. (DBeaver) ตรวจสอบตาราง attachments | 1\. 201 Created คืนค่าข้อมูล Attachment (เช่น ID, stored\_filename) 2\. (DBeaver) มีแถวใหม่ในตาราง attachments 3\. (ถ้าทำได้) ตรวจสอบ QNAP /share/dms-data/... ว่ามีไฟล์จริง | Postman, DBeaver |
|
||||
| **TC-FUNC-03** | **(File) ดาวน์โหลด (ผ่าน Auth)** | 1\. (Postman) ทำ TC-FUNC-02 เพื่ออัปโหลดไฟล์ (สมมติได้ attachment\_id: 123\) 2\. เรียก GET /api/v1/files/download/123 (ต้องใส่ Auth Header) | 200 OK และได้ข้อมูลไฟล์กลับมา | Postman |
|
||||
| **TC-FUNC-04** | **(Search) Elasticsearch** | 1\. (Postman) สร้างเอกสารใหม่ POST /api/v1/correspondence (จดจำ Title ไว้) 2\. (รอ 10 วินาที ให้ Elastic Index) 3\. เรียก GET /api/v1/search?query=\[Title ที่จดไว้\] | 200 OK และผลลัพธ์การค้นหาต้องมีเอกสารที่เพิ่งสร้าง | Postman |
|
||||
| **TC-FUNC-05** | **(Notification) N8N Webhook** | 1\. (N8N) สร้าง Workflow ใหม่, ใช้ "Webhook" Node (เปิด Test Mode) 2\. (Postman) Login User 3\. เรียก POST /api/v1/circulation (สร้างใบเวียนใหม่) | 1\. (Postman) 201 Created 2\. (N8N) Webhook Node ได้รับข้อมูล Payload ({ event: 'NEW\_CIRCULATION\_TASK', ... }) | Postman, N8N |
|
||||
| **TC-FUNC-06** | **(Audit) Audit Log** | 1\. (Postman) Login Admin 2\. เรียก DELETE /api/v1/admin/roles/10 (ลบ Role สมมติ) 3\. (DBeaver) ตรวจสอบ audit\_logs | 1\. (DBeaver) มีแถวใหม่ใน audit\_logs 2\. ข้อมูลถูกต้อง: action: 'role.delete', entity\_type: 'role', entity\_id: '10', user\_id: \[Admin ID\] | Postman, DBeaver |
|
||||
| ID | สถานการณ์ | ขั้นตอนการทดสอบ (Steps) | ผลลัพธ์ที่คาดหวัง (Expected) | เครื่องมือ |
|
||||
| :------------- | :------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :--------------- |
|
||||
| **TC-FUNC-02** | **(File) อัปโหลดไฟล์** | 1\. (Postman) Login User 2\. เรียก POST /api/v1/files/upload (ประเภท form-data, key file) 3\. (DBeaver) ตรวจสอบตาราง attachments | 1\. 201 Created คืนค่าข้อมูล Attachment (เช่น ID, stored_filename) 2\. (DBeaver) มีแถวใหม่ในตาราง attachments 3\. (ถ้าทำได้) ตรวจสอบ QNAP /share/dms-data/... ว่ามีไฟล์จริง | Postman, DBeaver |
|
||||
| **TC-FUNC-03** | **(File) ดาวน์โหลด (ผ่าน Auth)** | 1\. (Postman) ทำ TC-FUNC-02 เพื่ออัปโหลดไฟล์ (สมมติได้ attachment_id: 123\) 2\. เรียก GET /api/v1/files/download/123 (ต้องใส่ Auth Header) | 200 OK และได้ข้อมูลไฟล์กลับมา | Postman |
|
||||
| **TC-FUNC-04** | **(Search) Elasticsearch** | 1\. (Postman) สร้างเอกสารใหม่ POST /api/v1/correspondence (จดจำ Title ไว้) 2\. (รอ 10 วินาที ให้ Elastic Index) 3\. เรียก GET /api/v1/search?query=\[Title ที่จดไว้\] | 200 OK และผลลัพธ์การค้นหาต้องมีเอกสารที่เพิ่งสร้าง | Postman |
|
||||
| **TC-FUNC-05** | **(Notification) N8N Webhook** | 1\. (N8N) สร้าง Workflow ใหม่, ใช้ "Webhook" Node (เปิด Test Mode) 2\. (Postman) Login User 3\. เรียก POST /api/v1/circulation (สร้างใบเวียนใหม่) | 1\. (Postman) 201 Created 2\. (N8N) Webhook Node ได้รับข้อมูล Payload ({ event: 'NEW_CIRCULATION_TASK', ... }) | Postman, N8N |
|
||||
| **TC-FUNC-06** | **(Audit) Audit Log** | 1\. (Postman) Login Admin 2\. เรียก DELETE /api/v1/admin/roles/10 (ลบ Role สมมติ) 3\. (DBeaver) ตรวจสอบ audit_logs | 1\. (DBeaver) มีแถวใหม่ใน audit_logs 2\. ข้อมูลถูกต้อง: action: 'role.delete', entity_type: 'role', entity_id: '10', user_id: \[Admin ID\] | Postman, DBeaver |
|
||||
|
||||
### **T4: การ Deploy (NFR)**
|
||||
|
||||
| ID | สถานการณ์ | ขั้นตอนการทดสอบ (Steps) | ผลลัพธ์ที่คาดหวัง (Expected) | เครื่องมือ |
|
||||
| :---- | :---- | :---- | :---- | :---- |
|
||||
| **TC-NFR-01** | **(Health) Health Check** | 1\. (Browser/Postman) เรียก GET /api/v1/health (จาก Staging URL) | 200 OK และ JSON Response แสดง status: "ok" และสถานะ DB | Postman, Browser |
|
||||
| **TC-NFR-02** | **(Error) Global Filter** | 1\. (Postman) เรียก Endpoint ที่ไม่มีอยู่จริง (เช่น GET /api/v1/invalid\_path) | 404 Not Found Response Body ต้องมีโครงสร้าง JSON ที่กำหนดไว้ (เช่น { "statusCode": 404, "message": "Cannot GET /api/v1/invalid\_path", ... }) | Postman |
|
||||
|
||||
| ID | สถานการณ์ | ขั้นตอนการทดสอบ (Steps) | ผลลัพธ์ที่คาดหวัง (Expected) | เครื่องมือ |
|
||||
| :------------ | :------------------------ | :---------------------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------------------------- | :--------------- |
|
||||
| **TC-NFR-01** | **(Health) Health Check** | 1\. (Browser/Postman) เรียก GET /api/v1/health (จาก Staging URL) | 200 OK และ JSON Response แสดง status: "ok" และสถานะ DB | Postman, Browser |
|
||||
| **TC-NFR-02** | **(Error) Global Filter** | 1\. (Postman) เรียก Endpoint ที่ไม่มีอยู่จริง (เช่น GET /api/v1/invalid_path) | 404 Not Found Response Body ต้องมีโครงสร้าง JSON ที่กำหนดไว้ (เช่น { "statusCode": 404, "message": "Cannot GET /api/v1/invalid_path", ... }) | Postman |
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
# แผนการพัฒนา Backend NestJS สำหรับ DMS v1.3.0
|
||||
|
||||
## การเตรียมความพร้อมและการติดตั้ง (Prerequisites & Setup)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
# แผนการพัฒนา Frontend Next.js สำหรับ DMS v1.3.0
|
||||
|
||||
## การเตรียมความพร้อมและการติดตั้ง (Prerequisites & Setup)
|
||||
|
||||
@@ -4,206 +4,206 @@
|
||||
|
||||
สร้างเว็บแอปพลิเคชั่นสำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System)ที่สามารถจัดการและควบคุม การสื่อสารด้วยเอกสารที่ซับซ้อน อย่างมีประสิทธิภาพ
|
||||
|
||||
* มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
* ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
* เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
- มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
- ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
- เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
|
||||
## **🛠️ 2. สถาปัตยกรรมและเทคโนโลยี (System Architecture & Technology Stack)**
|
||||
|
||||
ใช้สถาปัตยกรรมแบบ Headless/API-First ที่ทันสมัย ทำงานทั้งหมดบน QNAP Server ผ่าน Container Station เพื่อความสะดวกในการจัดการและบำรุงรักษา, Domain: np-dms.work, มี fix ip, รัน docker command ใน application ของ Container Station ได้โดยตรง, ประกอบด้วย
|
||||
|
||||
* 2.1. Infrastructure & Environment:
|
||||
* Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
* Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
|
||||
* Development Environment: VS Code on Windows 11
|
||||
* Domain: np-dms.work, www.np-dms.work
|
||||
* ip: 159.192.126.103
|
||||
* Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
* Data Storage: /share/dms-data บน QNAP
|
||||
* ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
* 2.2. Code Hosting:
|
||||
* Application name: git
|
||||
* Service: Gitea (Self-hosted on QNAP)
|
||||
* Service name: gitea
|
||||
* Domain: git.np-dms.work
|
||||
* หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
|
||||
* 2.3. Backend / Data Platform:
|
||||
* Application name: lcbp3-backend
|
||||
* Service: NestJS
|
||||
* Service name: backend
|
||||
* Domain: backend.np-dms.work
|
||||
* Framework: NestJS (Node.js, TypeScript, ESM)
|
||||
* หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
|
||||
* 2.4. Database:
|
||||
* Application name: lcbp3-db
|
||||
* Service: mariadb:10.11
|
||||
* Service name: mariadb
|
||||
* Domain: db.np-dms.work
|
||||
* หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
|
||||
* Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
|
||||
* 2.5. Database management:
|
||||
* Application name: lcbp3-db
|
||||
* Service: phpmyadmin:5-apache
|
||||
* Service name: pma
|
||||
* Domain: pma.np-dms.work
|
||||
* หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
|
||||
* 2.6. Frontend:
|
||||
* Application name: lcbp3-frontend
|
||||
* Service: next.js
|
||||
* Service name: frontend
|
||||
* Domain: lcbp3.np-dms.work
|
||||
* Framework: Next.js (App Router, React, TypeScript, ESM)
|
||||
* Styling: Tailwind CSS + PostCSS
|
||||
* Component Library: shadcn/ui
|
||||
* หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
|
||||
* 2.7. Workflow automation:
|
||||
* Application name: lcbp3-n8n
|
||||
* Service: n8nio/n8n:latest
|
||||
* Service name: n8n
|
||||
* Domain: n8n.np-dms.work
|
||||
* หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
|
||||
* 2.8. Reverse Proxy:
|
||||
* Application name: lcbp3-npm
|
||||
* Service: Nginx Proxy Manager (nginx-proxy-manage: latest)
|
||||
* Service name: npm
|
||||
* Domain: npm.np-dms.work
|
||||
* หน้าที่: เป็นด่านหน้าในการรับ-ส่งข้อมูล จัดการโดเมนทั้งหมด, ทำหน้าที่เป็น Proxy ชี้ไปยัง Service ที่ถูกต้อง, และจัดการ SSL Certificate (HTTPS) ให้อัตโนมัติ
|
||||
* **2.9. การจัดการตรรกะทางธุรกิจ (Business Logic Implementation):**
|
||||
* 2.9.1. ตรรกะทางธุรกิจที่ซับซ้อนทั้งหมด (เช่น การเปลี่ยนสถานะ Workflow [cite: 3.5.4, 3.6.5], การบังคับใช้สิทธิ์ [cite: 4.4], การตรวจสอบ Deadline [cite: 3.2.5]) **จะถูกจัดการในฝั่ง Backend (NestJS)** [cite: 2.3] เพื่อให้สามารถบำรุงรักษาและทดสอบได้ง่าย (Testability)
|
||||
* 2.9.2. **จะไม่มีการใช้ SQL Triggers** เพื่อป้องกันตรรกะซ่อนเร้น (Hidden Logic) และความซับซ้อนในการดีบัก
|
||||
* 2.9.3. **ข้อยกเว้น:** ตรรกะเดียวที่จะอยู่ในฐานข้อมูลคือ **Stored Procedure** สำหรับการสร้างเลขที่เอกสาร (Document Numbering) [cite: 3.10] เพื่อป้องกันการซ้ำซ้อนของข้อมูล (Race Condition)
|
||||
- 2.1. Infrastructure & Environment:
|
||||
- Server: QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
- Containerization: Container Station (Docker & Docker Compose) ใช้ UI ของ Container Station เป็นหลัก ในการ configuration และการรัน docker command
|
||||
- Development Environment: VS Code on Windows 11
|
||||
- Domain: np-dms.work, www.np-dms.work
|
||||
- ip: 159.192.126.103
|
||||
- Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
- Data Storage: /share/dms-data บน QNAP
|
||||
- ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
- 2.2. Code Hosting:
|
||||
- Application name: git
|
||||
- Service: Gitea (Self-hosted on QNAP)
|
||||
- Service name: gitea
|
||||
- Domain: git.np-dms.work
|
||||
- หน้าที่: เป็นศูนย์กลางในการเก็บและจัดการเวอร์ชันของโค้ด (Source Code) สำหรับทุกส่วน
|
||||
- 2.3. Backend / Data Platform:
|
||||
- Application name: lcbp3-backend
|
||||
- Service: NestJS
|
||||
- Service name: backend
|
||||
- Domain: backend.np-dms.work
|
||||
- Framework: NestJS (Node.js, TypeScript, ESM)
|
||||
- หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
|
||||
- 2.4. Database:
|
||||
- Application name: lcbp3-db
|
||||
- Service: mariadb:10.11
|
||||
- Service name: mariadb
|
||||
- Domain: db.np-dms.work
|
||||
- หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
|
||||
- Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
|
||||
- 2.5. Database management:
|
||||
- Application name: lcbp3-db
|
||||
- Service: phpmyadmin:5-apache
|
||||
- Service name: pma
|
||||
- Domain: pma.np-dms.work
|
||||
- หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
|
||||
- 2.6. Frontend:
|
||||
- Application name: lcbp3-frontend
|
||||
- Service: next.js
|
||||
- Service name: frontend
|
||||
- Domain: lcbp3.np-dms.work
|
||||
- Framework: Next.js (App Router, React, TypeScript, ESM)
|
||||
- Styling: Tailwind CSS + PostCSS
|
||||
- Component Library: shadcn/ui
|
||||
- หน้าที่: สร้างหน้าตาเว็บแอปพลิเคชันสำหรับให้ผู้ใช้งานเข้ามาดู Dashboard, จัดการเอกสาร, และติดตามงาน โดยจะสื่อสารกับ Backend ผ่าน API
|
||||
- 2.7. Workflow automation:
|
||||
- Application name: lcbp3-n8n
|
||||
- Service: n8nio/n8n:latest
|
||||
- Service name: n8n
|
||||
- Domain: n8n.np-dms.work
|
||||
- หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
|
||||
- 2.8. Reverse Proxy:
|
||||
- Application name: lcbp3-npm
|
||||
- Service: Nginx Proxy Manager (nginx-proxy-manage: latest)
|
||||
- Service name: npm
|
||||
- Domain: npm.np-dms.work
|
||||
- หน้าที่: เป็นด่านหน้าในการรับ-ส่งข้อมูล จัดการโดเมนทั้งหมด, ทำหน้าที่เป็น Proxy ชี้ไปยัง Service ที่ถูกต้อง, และจัดการ SSL Certificate (HTTPS) ให้อัตโนมัติ
|
||||
- **2.9. การจัดการตรรกะทางธุรกิจ (Business Logic Implementation):**
|
||||
- 2.9.1. ตรรกะทางธุรกิจที่ซับซ้อนทั้งหมด (เช่น การเปลี่ยนสถานะ Workflow [cite: 3.5.4, 3.6.5], การบังคับใช้สิทธิ์ [cite: 4.4], การตรวจสอบ Deadline [cite: 3.2.5]) **จะถูกจัดการในฝั่ง Backend (NestJS)** [cite: 2.3] เพื่อให้สามารถบำรุงรักษาและทดสอบได้ง่าย (Testability)
|
||||
- 2.9.2. **จะไม่มีการใช้ SQL Triggers** เพื่อป้องกันตรรกะซ่อนเร้น (Hidden Logic) และความซับซ้อนในการดีบัก
|
||||
- 2.9.3. **ข้อยกเว้น:** ตรรกะเดียวที่จะอยู่ในฐานข้อมูลคือ **Stored Procedure** สำหรับการสร้างเลขที่เอกสาร (Document Numbering) [cite: 3.10] เพื่อป้องกันการซ้ำซ้อนของข้อมูล (Race Condition)
|
||||
|
||||
## **📦 3. ข้อกำหนดด้านฟังก์ชันการทำงาน (Functional Requirements)**
|
||||
|
||||
* 3.1. การจัดการโครงสร้างโครงการและองค์กร
|
||||
* 3.1.1. โครงการ (Projects): ระบบต้องสามารถจัดการเอกสารภายในหลายโครงการได้ (ปัจจุบันมี 4 โครงการ และจะเพิ่มขึ้นในอนาคต)
|
||||
* 3.1.2. สัญญา (Contracts): ระบบต้องสามารถจัดการเอกสารภายในแต่ละสัญญาได้ ในแต่ละโครงการ มีได้หลายสัญญา หรืออย่างน้อย 1 สัญญา
|
||||
* 3.1.3. องค์กร (Organizations):
|
||||
* มีหลายองค์กรในโครงการ องค์กรณ์ที่เป็น Owner, Designer และ Consultant สามารถอยู่ในหลายโครงการและหลายสัญญาได้
|
||||
* Contractor จะถือ 1 สัญญา และอยู่ใน 1 โครงการเท่านั้น
|
||||
* 3.2. การจัดการเอกสารโต้ตอบ (Correspondence Management)
|
||||
* 3.2.1. วัตถุประสงค์: เอกสารโต้ตอบ (correspondences) ระหว่างองกรณื-องกรณ์ ภายใน โครงการ (Projects) และระหว่าง องค์กร-องค์กร ภายนอก โครงการ (Projects), รองรับ To (ผู้รับหลัก) และ CC (ผู้รับสำเนา) หลายองค์กร
|
||||
* 3.2.2. ประเภทเอกสาร: ระบบต้องรองรับเอกสารรูปแบบ ไฟล์ PDF หลายประเภท (Types) เช่น จดหมาย (Letter), อีเมล์ (Email), Request for Information (RFI), และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
|
||||
* 3.2.3. การสร้างเอกสาร (Correspondence):
|
||||
* ผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารรอไว้ในสถานะ ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
|
||||
* เมื่อกด "Submitted" แล้ว การแก้ไข, ถอนเอกสารกลับไปสถานะ Draft, หรือยกเลิก (Cancel) จะต้องทำโดยผู้ใช้ระดับ Admin ขึ้นไป พร้อมระบุเหตุผล
|
||||
* 3.2.4. การอ้างอิงและจัดกลุ่ม:
|
||||
* เอกสารสามารถอ้างถึง (Reference) เอกสารฉบับก่อนหน้าได้หลายฉบับ
|
||||
* สามารถกำหนด Tag ได้หลาย Tag เพื่อจัดกลุ่มและใช้ในการค้นหาขั้นสูง
|
||||
* 3.2.5. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
* สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่เป็นผู้รับได้
|
||||
* มีระบบแจ้งเตือน ให้ผู้รับผิดชอบขององกรณ์ที่เป็น ผู้รับ/ผู้ส่ง ทราบ เมื่อมีเอกสารใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
* 3.3. การจัดกาแบบคู่สัญญา (Contract Drawing)
|
||||
* 3.3.1. วัตถุประสงค์: แบบคู่สัญญา (Contract Drawing) ใช้เพื่ออ้างอิงและใช้ในการตรวจสอบ
|
||||
* 3.3.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
* 3.3.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
* 3.3.4. การอ้างอิงและจัดกลุ่ม: ใช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Contract Drawing
|
||||
* 3.4. การจัดกาแบบก่อสร้าง (Shop Drawing)
|
||||
* 3.4.1. วัตถุประสงค์: แบบก่อสร้าง (Shop Drawing) ใช้เในการตรวจสอบ โดยจัดส่งด้วย Request for Approval (RFA)
|
||||
* 3.4.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
* 3.4.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
* 3.4.4. การอ้างอิงและจัดกลุ่ม: ช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Shop Drawings
|
||||
* 3.5. การจัดการเอกสารขออนุมัติ (Request for Approval & Workflow)
|
||||
* 3.5.1. วัตถุประสงค์: เอกสารขออนุมัติ (Request for Approval) ใช้ในการส่งเอกสารเพิอขออนุมัติ
|
||||
* 3.5.2. ประเภทเอกสาร: Request for Approval (RFA) เป็นชนิดหนึ่งของ Correspondence ที่มีลักษณะเฉพาะที่ต้องได้รับการอนุมัติ มีประเภทดังนี้:
|
||||
* Request for Drawing Approval (RFA_DWG)
|
||||
* Request for Document Approval (RFA_DOC)
|
||||
* Request for Method statement Approval (RFA_MES)
|
||||
* Request for Material Approval (RFA_MAT)
|
||||
* 3.5.2. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
* 3.5.4. การอ้างอิงและจัดกลุ่ม: การจัดการ Drawing (RFA_DWG):
|
||||
* เอกสาร RFA_DWG จะประกอบไปด้วย Shop Drawing (shop_drawings) หลายแผ่น ซึ่งแต่ละแผ่นมี Revision ของตัวเอง
|
||||
* Shop Drawing แต่ละ Revision สามารถอ้างอิงถึง Contract Drawing (Ccontract_drawings) หลายแผ่น หรือไม่อ้างถึงก็ได้
|
||||
* ระบบต้องมีส่วนสำหรับจัดการข้อมูล Master Data ของทั้ง Shop Drawing และ Contract Drawing แยกจากกัน
|
||||
* 3.6.5. Workflow การอนุมัติ: ต้องรองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น
|
||||
* ส่งจาก Originator -> Organization 1 -> Organization 2 -> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Workflow ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
|
||||
* 3.6.6. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
* สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ได้
|
||||
* มีระบบแจ้งเตือน ให้ผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ทราบ เมื่อมี RFA ใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
* 3.6.การจัดการเอกสารนำส่ง (Transmittals)
|
||||
* 3.6.1. วัตถุประสงค์: เอกสารนำส่ง ใช้สำหรับ นำส่ง Request for Approval (RFAS) หลายฉบับ ไปยังองค์กรอื่น
|
||||
* 3.6.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
* 3.6.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
* 3.6.4. การอ้างอิงและจัดกลุ่ม: เอกสารนำส่ง เป็นส่วนหนึ่งใน Correspondence
|
||||
* 3.7. ใบเวียนเอกสารภายใน (Internal Circulation Sheet)
|
||||
* 3.7.1. วัตถุประสงค์: การสื่อสาร เอกสาร (Correspondence) ทุกฉบับ จะมีใบเวียนเอกสารเพื่อควบคุมและมอบหมายงานภายในองค์กร (สามารถดูและแก้ไขได้เฉพาะคนในองค์กร)
|
||||
* 3.7.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
* 3.7.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ในองค์กรนั้น สามารถสร้างและแก้ไขได้
|
||||
* 3.7.4. การอ้างอิงและจัดกลุ่ม: การระบุผู้รับผิดชอบ:
|
||||
* ผู้รับผิดชอบหลัก (Main): มีได้หลายคน
|
||||
* ผู้ร่วมปฏิบัติงาน (Action): มีได้หลายคน
|
||||
* ผู้ที่ต้องรับทราบ (Information): มีได้หลายคน
|
||||
* 3.7.5. การติดตามงาน:
|
||||
* สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบประเภท Main และ Action ได้
|
||||
* มีระบบแจ้งเตือนเมื่อมี Circulation ใหม่ และแจ้งเตือนล่วงหน้าก่อนถึงวันแล้วเสร็จ
|
||||
* สามารถปิด Circulation ได้เมื่อดำเนินการตอบกลับไปยังองค์กรผู้ส่ง (Originator) แล้ว หรือ รับทราบแล้ว (For Information)
|
||||
* 3.8. ประวัติการแก้ไข (Revisions): ระบบจะเก็บประวัติการสร้างและแก้ไข เอกสารทั้งหมด
|
||||
* 3.9. การจัดเก็บ: (ปรับปรุงตามสถาปัตยกรรมใหม่)
|
||||
* เอกสารและไฟล์แนบทั้งหมดจะถูกจัดเก็บในโฟลเดอร์บน Server (/share/dms-data/) [cite: 2.1]
|
||||
* ข้อมูล Metadata ของไฟล์ (เช่น ชื่อไฟล์, ขนาด, path) จะถูกเก็บในตาราง attachments (ตารางกลาง)
|
||||
* ไฟล์จะถูกเชื่อมโยงกับเอกสารประเภทต่างๆ ผ่านตารางเชื่อม (Junction tables) เช่น correspondence_attachments, circulation_attachments, shop_drawing_revision_attachments ,และ contracy_drawing_attachments
|
||||
* สถาปัตยกรรมแบบรวมศูนย์นี้ *แทนที่* แนวคิดเดิมที่จะแยกโฟลเดอร์ตามประเภทเอกสาร เพื่อรองรับการขยายระบบที่ดีกว่า
|
||||
* 3.10. การจัดการเลขที่เอกสาร (Document Numbering):
|
||||
* 3.10.1. ระบบต้องสามารถสร้างเลขที่เอกสาร (เช่น correspondence_number) ได้โดยอัตโนมัติ
|
||||
* 3.10.2. การนับเลข Running Number (SEQ) จะต้องนับแยกตาม Key ดังนี้: **โครงการ (Project)**, **องค์กรผู้ส่ง (Originator Organization)**, **ประเภทเอกสาร (Document Type)** และ **ปีปัจจุบัน (Year)**
|
||||
* 3.10.3. ผู้ดูแลระบบ (Admin) ต้องสามารถกำหนด "รูปแบบ" (Format Template) ของเลขที่เอกสารได้ (เช่น {ORG_CODE}-{TYPE_CODE}-{YEAR_SHORT}-{SEQ:4}) โดยกำหนดแยกตามโครงการและประเภทเอกสาร
|
||||
- 3.1. การจัดการโครงสร้างโครงการและองค์กร
|
||||
- 3.1.1. โครงการ (Projects): ระบบต้องสามารถจัดการเอกสารภายในหลายโครงการได้ (ปัจจุบันมี 4 โครงการ และจะเพิ่มขึ้นในอนาคต)
|
||||
- 3.1.2. สัญญา (Contracts): ระบบต้องสามารถจัดการเอกสารภายในแต่ละสัญญาได้ ในแต่ละโครงการ มีได้หลายสัญญา หรืออย่างน้อย 1 สัญญา
|
||||
- 3.1.3. องค์กร (Organizations):
|
||||
- มีหลายองค์กรในโครงการ องค์กรณ์ที่เป็น Owner, Designer และ Consultant สามารถอยู่ในหลายโครงการและหลายสัญญาได้
|
||||
- Contractor จะถือ 1 สัญญา และอยู่ใน 1 โครงการเท่านั้น
|
||||
- 3.2. การจัดการเอกสารโต้ตอบ (Correspondence Management)
|
||||
- 3.2.1. วัตถุประสงค์: เอกสารโต้ตอบ (correspondences) ระหว่างองกรณื-องกรณ์ ภายใน โครงการ (Projects) และระหว่าง องค์กร-องค์กร ภายนอก โครงการ (Projects), รองรับ To (ผู้รับหลัก) และ CC (ผู้รับสำเนา) หลายองค์กร
|
||||
- 3.2.2. ประเภทเอกสาร: ระบบต้องรองรับเอกสารรูปแบบ ไฟล์ PDF หลายประเภท (Types) เช่น จดหมาย (Letter), อีเมล์ (Email), Request for Information (RFI), และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
|
||||
- 3.2.3. การสร้างเอกสาร (Correspondence):
|
||||
- ผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารรอไว้ในสถานะ ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
|
||||
- เมื่อกด "Submitted" แล้ว การแก้ไข, ถอนเอกสารกลับไปสถานะ Draft, หรือยกเลิก (Cancel) จะต้องทำโดยผู้ใช้ระดับ Admin ขึ้นไป พร้อมระบุเหตุผล
|
||||
- 3.2.4. การอ้างอิงและจัดกลุ่ม:
|
||||
- เอกสารสามารถอ้างถึง (Reference) เอกสารฉบับก่อนหน้าได้หลายฉบับ
|
||||
- สามารถกำหนด Tag ได้หลาย Tag เพื่อจัดกลุ่มและใช้ในการค้นหาขั้นสูง
|
||||
- 3.2.5. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่เป็นผู้รับได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบขององกรณ์ที่เป็น ผู้รับ/ผู้ส่ง ทราบ เมื่อมีเอกสารใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
- 3.3. การจัดกาแบบคู่สัญญา (Contract Drawing)
|
||||
- 3.3.1. วัตถุประสงค์: แบบคู่สัญญา (Contract Drawing) ใช้เพื่ออ้างอิงและใช้ในการตรวจสอบ
|
||||
- 3.3.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.3.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.3.4. การอ้างอิงและจัดกลุ่ม: ใช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Contract Drawing
|
||||
- 3.4. การจัดกาแบบก่อสร้าง (Shop Drawing)
|
||||
- 3.4.1. วัตถุประสงค์: แบบก่อสร้าง (Shop Drawing) ใช้เในการตรวจสอบ โดยจัดส่งด้วย Request for Approval (RFA)
|
||||
- 3.4.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.4.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.4.4. การอ้างอิงและจัดกลุ่ม: ช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Shop Drawings
|
||||
- 3.5. การจัดการเอกสารขออนุมัติ (Request for Approval & Workflow)
|
||||
- 3.5.1. วัตถุประสงค์: เอกสารขออนุมัติ (Request for Approval) ใช้ในการส่งเอกสารเพิอขออนุมัติ
|
||||
- 3.5.2. ประเภทเอกสาร: Request for Approval (RFA) เป็นชนิดหนึ่งของ Correspondence ที่มีลักษณะเฉพาะที่ต้องได้รับการอนุมัติ มีประเภทดังนี้:
|
||||
- Request for Drawing Approval (RFA_DWG)
|
||||
- Request for Document Approval (RFA_DOC)
|
||||
- Request for Method statement Approval (RFA_MES)
|
||||
- Request for Material Approval (RFA_MAT)
|
||||
- 3.5.2. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.5.4. การอ้างอิงและจัดกลุ่ม: การจัดการ Drawing (RFA_DWG):
|
||||
- เอกสาร RFA_DWG จะประกอบไปด้วย Shop Drawing (shop_drawings) หลายแผ่น ซึ่งแต่ละแผ่นมี Revision ของตัวเอง
|
||||
- Shop Drawing แต่ละ Revision สามารถอ้างอิงถึง Contract Drawing (Ccontract_drawings) หลายแผ่น หรือไม่อ้างถึงก็ได้
|
||||
- ระบบต้องมีส่วนสำหรับจัดการข้อมูล Master Data ของทั้ง Shop Drawing และ Contract Drawing แยกจากกัน
|
||||
- 3.6.5. Workflow การอนุมัติ: ต้องรองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น
|
||||
- ส่งจาก Originator -> Organization 1 -> Organization 2 -> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Workflow ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
|
||||
- 3.6.6. การจัดการ: มีการจัดการอย่างน้อยดังนี้
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ทราบ เมื่อมี RFA ใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
- 3.6.การจัดการเอกสารนำส่ง (Transmittals)
|
||||
- 3.6.1. วัตถุประสงค์: เอกสารนำส่ง ใช้สำหรับ นำส่ง Request for Approval (RFAS) หลายฉบับ ไปยังองค์กรอื่น
|
||||
- 3.6.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.6.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
- 3.6.4. การอ้างอิงและจัดกลุ่ม: เอกสารนำส่ง เป็นส่วนหนึ่งใน Correspondence
|
||||
- 3.7. ใบเวียนเอกสารภายใน (Internal Circulation Sheet)
|
||||
- 3.7.1. วัตถุประสงค์: การสื่อสาร เอกสาร (Correspondence) ทุกฉบับ จะมีใบเวียนเอกสารเพื่อควบคุมและมอบหมายงานภายในองค์กร (สามารถดูและแก้ไขได้เฉพาะคนในองค์กร)
|
||||
- 3.7.2. ประเภทเอกสาร: ไฟล์ PDF
|
||||
- 3.7.3. การสร้างเอกสาร: ผู้ใช้ที่มีสิทธิ์ในองค์กรนั้น สามารถสร้างและแก้ไขได้
|
||||
- 3.7.4. การอ้างอิงและจัดกลุ่ม: การระบุผู้รับผิดชอบ:
|
||||
- ผู้รับผิดชอบหลัก (Main): มีได้หลายคน
|
||||
- ผู้ร่วมปฏิบัติงาน (Action): มีได้หลายคน
|
||||
- ผู้ที่ต้องรับทราบ (Information): มีได้หลายคน
|
||||
- 3.7.5. การติดตามงาน:
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบประเภท Main และ Action ได้
|
||||
- มีระบบแจ้งเตือนเมื่อมี Circulation ใหม่ และแจ้งเตือนล่วงหน้าก่อนถึงวันแล้วเสร็จ
|
||||
- สามารถปิด Circulation ได้เมื่อดำเนินการตอบกลับไปยังองค์กรผู้ส่ง (Originator) แล้ว หรือ รับทราบแล้ว (For Information)
|
||||
- 3.8. ประวัติการแก้ไข (Revisions): ระบบจะเก็บประวัติการสร้างและแก้ไข เอกสารทั้งหมด
|
||||
- 3.9. การจัดเก็บ: (ปรับปรุงตามสถาปัตยกรรมใหม่)
|
||||
- เอกสารและไฟล์แนบทั้งหมดจะถูกจัดเก็บในโฟลเดอร์บน Server (/share/dms-data/) [cite: 2.1]
|
||||
- ข้อมูล Metadata ของไฟล์ (เช่น ชื่อไฟล์, ขนาด, path) จะถูกเก็บในตาราง attachments (ตารางกลาง)
|
||||
- ไฟล์จะถูกเชื่อมโยงกับเอกสารประเภทต่างๆ ผ่านตารางเชื่อม (Junction tables) เช่น correspondence_attachments, circulation_attachments, shop_drawing_revision_attachments ,และ contracy_drawing_attachments
|
||||
- สถาปัตยกรรมแบบรวมศูนย์นี้ _แทนที่_ แนวคิดเดิมที่จะแยกโฟลเดอร์ตามประเภทเอกสาร เพื่อรองรับการขยายระบบที่ดีกว่า
|
||||
- 3.10. การจัดการเลขที่เอกสาร (Document Numbering):
|
||||
- 3.10.1. ระบบต้องสามารถสร้างเลขที่เอกสาร (เช่น correspondence_number) ได้โดยอัตโนมัติ
|
||||
- 3.10.2. การนับเลข Running Number (SEQ) จะต้องนับแยกตาม Key ดังนี้: **โครงการ (Project)**, **องค์กรผู้ส่ง (Originator Organization)**, **ประเภทเอกสาร (Document Type)** และ **ปีปัจจุบัน (Year)**
|
||||
- 3.10.3. ผู้ดูแลระบบ (Admin) ต้องสามารถกำหนด "รูปแบบ" (Format Template) ของเลขที่เอกสารได้ (เช่น {ORG_CODE}-{TYPE_CODE}-{YEAR_SHORT}-{SEQ:4}) โดยกำหนดแยกตามโครงการและประเภทเอกสาร
|
||||
|
||||
## **🔐 4. ข้อกำหนดด้านสิทธิ์และการเข้าถึง (Access Control Requirements)**
|
||||
|
||||
* 4.1. ภาพรวม: ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
|
||||
* 4.2. ระดับของสิทธิ์:
|
||||
* Global Roles: สิทธิ์ในภาพรวมของระบบ
|
||||
* Project-Specific Roles: สิทธิ์ที่ถูกกำหนดให้ผู้ใช้สำหรับโครงการนั้นๆ โดยเฉพาะ (เช่น เป็น Editor ในโครงการ A แต่เป็น Viewer ในโครงการ B)
|
||||
* 4.3. บทบาท (Roles) พื้นฐาน:
|
||||
* Superadmin: ไม่มีข้อจำกัดใดๆ สามารถจัดการได้ทุกอย่างข้ามองค์กรณ์
|
||||
* Admin: มีสิทธิ์เต็มที่ แต่จำกัดเฉพาะในองค์กรที่ตัวเองสังกัด สามารถจัดการผู้ใช้ในองค์กรณ์ได้ สามารถสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลังผ่านหน้า Admin
|
||||
* Document Control สามารถ เพิ่ม/แก้ไข/ลบ เอกสาร เฉพาะในองค์กรณ์ที่ตัวเองสังกัด ไม่สามารถจัดการผู้ใช้ได้
|
||||
* Editor: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนดไว้ เฉพาะในองค์กรณ์ที่ตัวเองสังกัด
|
||||
* Viewer: สามารถดู เอกสาร เฉพาะในองค์กรณ์ที่ตัวเองสังกัด
|
||||
* 4.4. การบังคับใช้สิทธิ์: สิทธิ์ขององค์กรจะครอบคลุมสิทธิ์ของผู้ใช้ และการเข้าถึงข้อมูลที่เกี่ยวข้องกับโครงการ (เช่น การแก้ไขเอกสาร) จะถูกตรวจสอบเทียบกับสิทธิ์ที่ผู้ใช้มีในโครงการนั้นๆ โดยเฉพาะ
|
||||
* 4.5. (ใหม่) การจัดการข้อมูลหลัก (Master Data Management):
|
||||
* ระบบจะต้องมีส่วน "Admin Panel" (สำหรับ Superadmin และ Admin) เพื่อใช้จัดการข้อมูลหลัก (Master Data) ของระบบ
|
||||
* ข้อมูลหลักที่ต้องจัดการได้เป็นอย่างน้อย:
|
||||
* ประเภทเอกสาร (เช่น correspondence_types, rfa_types)
|
||||
* หมวดหมู่แบบ (เช่น shop_drawing_categories)
|
||||
* Tags ที่ใช้ในระบบ
|
||||
* สถานะเอกสาร (หากจำเป็นต้องเพิ่มในอนาคต)
|
||||
* 4.6. (ใหม่) การเริ่มต้นใช้งาน (User & Organization Onboarding):
|
||||
* การเพิ่มองค์กรณ์ใหม่ (Organizations) เข้าสู่ระบบ จะต้องดำเนินการโดย Superadmin เท่านั้น
|
||||
* เมื่อ Superadmin สร้างองค์กรณ์ใหม่ จะต้องสามารถกำหนดผู้ใช้ (User) อย่างน้อย 1 คน ให้เป็น "Admin" ประจำองค์กรณ์นั้นๆ
|
||||
* Admin ประจำองค์กณ์รจึงจะสามารถเพิ่มผู้ใช้ (Editor, Viewer, Document Control) คนอื่นๆ เข้าสู่องค์กรของตนเองได้
|
||||
- 4.1. ภาพรวม: ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
|
||||
- 4.2. ระดับของสิทธิ์:
|
||||
- Global Roles: สิทธิ์ในภาพรวมของระบบ
|
||||
- Project-Specific Roles: สิทธิ์ที่ถูกกำหนดให้ผู้ใช้สำหรับโครงการนั้นๆ โดยเฉพาะ (เช่น เป็น Editor ในโครงการ A แต่เป็น Viewer ในโครงการ B)
|
||||
- 4.3. บทบาท (Roles) พื้นฐาน:
|
||||
- Superadmin: ไม่มีข้อจำกัดใดๆ สามารถจัดการได้ทุกอย่างข้ามองค์กรณ์
|
||||
- Admin: มีสิทธิ์เต็มที่ แต่จำกัดเฉพาะในองค์กรที่ตัวเองสังกัด สามารถจัดการผู้ใช้ในองค์กรณ์ได้ สามารถสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลังผ่านหน้า Admin
|
||||
- Document Control สามารถ เพิ่ม/แก้ไข/ลบ เอกสาร เฉพาะในองค์กรณ์ที่ตัวเองสังกัด ไม่สามารถจัดการผู้ใช้ได้
|
||||
- Editor: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนดไว้ เฉพาะในองค์กรณ์ที่ตัวเองสังกัด
|
||||
- Viewer: สามารถดู เอกสาร เฉพาะในองค์กรณ์ที่ตัวเองสังกัด
|
||||
- 4.4. การบังคับใช้สิทธิ์: สิทธิ์ขององค์กรจะครอบคลุมสิทธิ์ของผู้ใช้ และการเข้าถึงข้อมูลที่เกี่ยวข้องกับโครงการ (เช่น การแก้ไขเอกสาร) จะถูกตรวจสอบเทียบกับสิทธิ์ที่ผู้ใช้มีในโครงการนั้นๆ โดยเฉพาะ
|
||||
- 4.5. (ใหม่) การจัดการข้อมูลหลัก (Master Data Management):
|
||||
- ระบบจะต้องมีส่วน "Admin Panel" (สำหรับ Superadmin และ Admin) เพื่อใช้จัดการข้อมูลหลัก (Master Data) ของระบบ
|
||||
- ข้อมูลหลักที่ต้องจัดการได้เป็นอย่างน้อย:
|
||||
- ประเภทเอกสาร (เช่น correspondence_types, rfa_types)
|
||||
- หมวดหมู่แบบ (เช่น shop_drawing_categories)
|
||||
- Tags ที่ใช้ในระบบ
|
||||
- สถานะเอกสาร (หากจำเป็นต้องเพิ่มในอนาคต)
|
||||
- 4.6. (ใหม่) การเริ่มต้นใช้งาน (User & Organization Onboarding):
|
||||
- การเพิ่มองค์กรณ์ใหม่ (Organizations) เข้าสู่ระบบ จะต้องดำเนินการโดย Superadmin เท่านั้น
|
||||
- เมื่อ Superadmin สร้างองค์กรณ์ใหม่ จะต้องสามารถกำหนดผู้ใช้ (User) อย่างน้อย 1 คน ให้เป็น "Admin" ประจำองค์กรณ์นั้นๆ
|
||||
- Admin ประจำองค์กณ์รจึงจะสามารถเพิ่มผู้ใช้ (Editor, Viewer, Document Control) คนอื่นๆ เข้าสู่องค์กรของตนเองได้
|
||||
|
||||
## **👥 5\. ข้อกำหนดด้านผู้ใช้งาน (User Interface & Experience)**
|
||||
|
||||
* 5.1. Layout หลัก: หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย:
|
||||
* Navbar (ส่วนบน): แสดงชื่อระบบ, เมนูผู้ใช้ (Profile), เมนูสำหรับ Admin/Superadmin (จัดการผู้ใช้, จัดการสิทธิ์), และปุ่ม Login/Logout
|
||||
* Sidebar (ด้านข้าง): เป็นเมนูหลักสำหรับเข้าถึงส่วนที่เกี่ยวกับเอกสารทั้งหมด เช่น Dashboard, Correspondences, RFA, Drawings
|
||||
* Main Content Area: พื้นที่สำหรับแสดงเนื้อหาหลักของหน้าที่เลือก
|
||||
* 5.2. หน้า Landing Page: เป็นหน้าแรกที่แสดงข้อมูลบางส่วนของโครงการสำหรับผู้ใช้ที่ยังไม่ได้ล็อกอิน
|
||||
* 5.3. หน้า Dashboard: เป็นหน้าแรกหลังจากล็อกอิน ประกอบด้วย:
|
||||
* การ์ดสรุปภาพรวม (KPI Cards): แสดงข้อมูลสรุปที่สำคัญขององค์กร เช่น จำนวนเอกสาร, งานที่เกินกำหนด
|
||||
* ตาราง "งานของฉัน" (My Tasks Table): แสดงรายการงานทั้งหมดจาก Circulation ที่ผู้ใช้ต้องดำเนินการ
|
||||
* 5.4. การติดตามสถานะ: องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
|
||||
* 5.5. การจัดการข้อมูลส่วนตัว (Profile Page): ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้
|
||||
* 5.6. การจัดการเอกสารทางเทคนิค (Technical Documents & Workflow): ผู้ใช้สามารถดู Technical Document ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว, ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ admin ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ admin ขึ้นไป
|
||||
* 5.7. ข้อกำหนด UI/UX การแนบไฟล์ (File Attachment UX):
|
||||
* ระบบต้องรองรับการอัปโหลดไฟล์หลายไฟล์พร้อมกัน (Multi-file upload) เช่น การลากและวาง (Drag-and-Drop)
|
||||
* ในหน้าอัปโหลด (เช่น สร้าง RFA หรือ Correspondence) ผู้ใช้ต้องสามารถกำหนดได้ว่าไฟล์ใดเป็น "เอกสารหลัก" (Main Document เช่น PDF) และไฟล์ใดเป็น "เอกสารแนบประกอบ" (Supporting Attachments เช่น .dwg, .docx, .zip)
|
||||
- 5.1. Layout หลัก: หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย:
|
||||
- Navbar (ส่วนบน): แสดงชื่อระบบ, เมนูผู้ใช้ (Profile), เมนูสำหรับ Admin/Superadmin (จัดการผู้ใช้, จัดการสิทธิ์), และปุ่ม Login/Logout
|
||||
- Sidebar (ด้านข้าง): เป็นเมนูหลักสำหรับเข้าถึงส่วนที่เกี่ยวกับเอกสารทั้งหมด เช่น Dashboard, Correspondences, RFA, Drawings
|
||||
- Main Content Area: พื้นที่สำหรับแสดงเนื้อหาหลักของหน้าที่เลือก
|
||||
- 5.2. หน้า Landing Page: เป็นหน้าแรกที่แสดงข้อมูลบางส่วนของโครงการสำหรับผู้ใช้ที่ยังไม่ได้ล็อกอิน
|
||||
- 5.3. หน้า Dashboard: เป็นหน้าแรกหลังจากล็อกอิน ประกอบด้วย:
|
||||
- การ์ดสรุปภาพรวม (KPI Cards): แสดงข้อมูลสรุปที่สำคัญขององค์กร เช่น จำนวนเอกสาร, งานที่เกินกำหนด
|
||||
- ตาราง "งานของฉัน" (My Tasks Table): แสดงรายการงานทั้งหมดจาก Circulation ที่ผู้ใช้ต้องดำเนินการ
|
||||
- 5.4. การติดตามสถานะ: องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
|
||||
- 5.5. การจัดการข้อมูลส่วนตัว (Profile Page): ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้
|
||||
- 5.6. การจัดการเอกสารทางเทคนิค (Technical Documents & Workflow): ผู้ใช้สามารถดู Technical Document ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว, ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ admin ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ admin ขึ้นไป
|
||||
- 5.7. ข้อกำหนด UI/UX การแนบไฟล์ (File Attachment UX):
|
||||
- ระบบต้องรองรับการอัปโหลดไฟล์หลายไฟล์พร้อมกัน (Multi-file upload) เช่น การลากและวาง (Drag-and-Drop)
|
||||
- ในหน้าอัปโหลด (เช่น สร้าง RFA หรือ Correspondence) ผู้ใช้ต้องสามารถกำหนดได้ว่าไฟล์ใดเป็น "เอกสารหลัก" (Main Document เช่น PDF) และไฟล์ใดเป็น "เอกสารแนบประกอบ" (Supporting Attachments เช่น .dwg, .docx, .zip)
|
||||
|
||||
## **6. ข้อกำหนดที่ไม่ใช่ฟังก์ชันการทำงาน (Non-Functional Requirements)**
|
||||
|
||||
* 6.1. การบันทึกการกระทำ (Audit Log): ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน audit_logs เพื่อการตรวจสอบย้อนหลัง
|
||||
* 6.2. การค้นหา (Search): ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสาร **correspondence**, **rfa**, **shop_drawing**, **contract-drawing**, **transmittal** และ **ใบเวียน (Circulations)** จากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
|
||||
* 6.3. การทำรายงาน (Reporting): สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
|
||||
* 6.4. ประสิทธิภาพ (Performance): มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
* 6.5. ความปลอดภัย (Security):
|
||||
* มีระบบ Rate Limiting เพื่อป้องกันการโจมตีแบบ Brute-force
|
||||
* การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด
|
||||
* 6.6. (ใหม่) การสำรองข้อมูลและการกู้คืน (Backup & Recovery):
|
||||
* ระบบจะต้องมีกลไกการสำรองข้อมูลอัตโนมัติสำหรับฐานข้อมูล MariaDB [cite: 2.4] และไฟล์เอกสารทั้งหมดใน /share/dms-data [cite: 2.1] (เช่น ใช้ HBS 3 ของ QNAP หรือสคริปต์สำรองข้อมูล) อย่างน้อยวันละ 1 ครั้ง
|
||||
* ต้องมีแผนการกู้คืนระบบ (Disaster Recovery Plan) ในกรณีที่ Server หลัก (QNAP) ใช้งานไม่ได้
|
||||
* 6.7. (ใหม่) กลยุทธ์การแจ้งเตือน (Notification Strategy):
|
||||
* ระบบจะส่งการแจ้งเตือน (ผ่าน Email หรือ Line [cite: 2.7]) เมื่อมีการกระทำที่สำคัญ ดังนี้:
|
||||
- 6.1. การบันทึกการกระทำ (Audit Log): ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน audit_logs เพื่อการตรวจสอบย้อนหลัง
|
||||
- 6.2. การค้นหา (Search): ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสาร **correspondence**, **rfa**, **shop_drawing**, **contract-drawing**, **transmittal** และ **ใบเวียน (Circulations)** จากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
|
||||
- 6.3. การทำรายงาน (Reporting): สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
|
||||
- 6.4. ประสิทธิภาพ (Performance): มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
- 6.5. ความปลอดภัย (Security):
|
||||
- มีระบบ Rate Limiting เพื่อป้องกันการโจมตีแบบ Brute-force
|
||||
- การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด
|
||||
- 6.6. (ใหม่) การสำรองข้อมูลและการกู้คืน (Backup & Recovery):
|
||||
- ระบบจะต้องมีกลไกการสำรองข้อมูลอัตโนมัติสำหรับฐานข้อมูล MariaDB [cite: 2.4] และไฟล์เอกสารทั้งหมดใน /share/dms-data [cite: 2.1] (เช่น ใช้ HBS 3 ของ QNAP หรือสคริปต์สำรองข้อมูล) อย่างน้อยวันละ 1 ครั้ง
|
||||
- ต้องมีแผนการกู้คืนระบบ (Disaster Recovery Plan) ในกรณีที่ Server หลัก (QNAP) ใช้งานไม่ได้
|
||||
- 6.7. (ใหม่) กลยุทธ์การแจ้งเตือน (Notification Strategy):
|
||||
- ระบบจะส่งการแจ้งเตือน (ผ่าน Email หรือ Line [cite: 2.7]) เมื่อมีการกระทำที่สำคัญ ดังนี้:
|
||||
1. เมื่อมีเอกสารใหม่ (Correspondence, RFA) ถูกส่งมาถึงองค์กรณ์ของเรา
|
||||
2. เมื่อมีใบเวียน (Circulation) ใหม่ มอบหมายงานมาที่เรา
|
||||
3. (ทางเลือก) เมื่อเอกสารที่เราส่งไป ถูกดำเนินการ (เช่น อนุมัติ/ปฏิเสธ)
|
||||
|
||||
@@ -60,7 +60,6 @@ Milestone: สร้างโครงสร้างพื้นฐานแล
|
||||
### Phase 0: Tasks
|
||||
|
||||
- **[✅]T0.1 Setup QNAP Container Station**
|
||||
|
||||
- สร้าง Docker Network: `lcbp3`
|
||||
- Setup docker-compose.yml สำหรับ:
|
||||
- MariaDB (db.np-dms.work)
|
||||
@@ -71,7 +70,6 @@ Milestone: สร้างโครงสร้างพื้นฐานแล
|
||||
- Deliverable: Services ทั้งหมดรันได้และเชื่อมต่อกันผ่าน Network
|
||||
|
||||
- **[✅]T0.2 Initialize NestJS Project**
|
||||
|
||||
- สร้างโปรเจกต์ใหม่ด้วย Nest CLI
|
||||
- ติดตั้ง Dependencies:
|
||||
|
||||
@@ -219,7 +217,6 @@ Milestone: Master Data และระบบจัดการไฟล์
|
||||
### Phase 2: Tasks
|
||||
|
||||
- **[ ] T2.1 MasterModule - Master Data Management**
|
||||
|
||||
- [ ] สร้าง Entities:
|
||||
- [ ] CorrespondenceType
|
||||
- [ ] CorrespondenceStatus
|
||||
@@ -235,7 +232,6 @@ Milestone: Master Data และระบบจัดการไฟล์
|
||||
- [ ] Deliverable: Admin จัดการ Master Data ได้
|
||||
|
||||
- **[ ] T2.2 FileStorageService - Central File Management**
|
||||
|
||||
- [ ] สร้าง Attachment Entity
|
||||
- [ ] สร้าง FileStorageService: (การจัดเก็บไฟล์ในรูปแบบ centralized storage, ครอบคลุมการจัดการไฟล์แนบทั้งหมด, Security Measures)
|
||||
- [ ] `uploadFile(file: Express.Multer.File)` → Attachment
|
||||
@@ -268,7 +264,6 @@ Milestone: ระบบเอกสารโต้ตอบและ RFA
|
||||
### Phase 3: Tasks
|
||||
|
||||
- **[ ] T3.1 CorrespondenceModule - Basic CRUD**
|
||||
|
||||
- [ ] สร้าง Entities:
|
||||
- [ ] Correspondence
|
||||
- [ ] CorrespondenceRevision
|
||||
@@ -297,7 +292,6 @@ Milestone: ระบบเอกสารโต้ตอบและ RFA
|
||||
- [ ] Deliverable: สร้าง/แก้ไข/ดูเอกสารได้
|
||||
|
||||
- **[ ] T3.2 CorrespondenceModule - Advanced Features**
|
||||
|
||||
- [ ] Implement Status Transitions:
|
||||
- [ ] `DRAFT` → `SUBMITTED` (Document Control)
|
||||
- [ ] `SUBMITTED` → `CLOSED` (Admin)
|
||||
@@ -334,7 +328,6 @@ Milestone: ระบบจัดการแบบ
|
||||
### Phase 4: Tasks
|
||||
|
||||
- **[ ] T4.1 DrawingModule - Contract Drawings**
|
||||
|
||||
- [ ] สร้าง Entities:
|
||||
- [ ] ContractDrawing
|
||||
- [ ] ContractDrawingVolume
|
||||
@@ -375,7 +368,6 @@ Milestone: ระบบ Workflow ทั้งหมด
|
||||
### Phase 5: Tasks
|
||||
|
||||
- **[ ] T5.1 RfaModule - Workflow Implementation**
|
||||
|
||||
- [ ] สร้าง Entities:
|
||||
- [ ] RfaWorkflowTemplate
|
||||
- [ ] RfaWorkflowTemplateStep
|
||||
@@ -398,7 +390,6 @@ Milestone: ระบบ Workflow ทั้งหมด
|
||||
- [ ] Deliverable: RFA Workflow ทำงานได้
|
||||
|
||||
- **[ ] T5.2 CirculationModule - Internal Routing**
|
||||
|
||||
- [ ] สร้าง Entities:
|
||||
- [ ] Circulation
|
||||
- [ ] CirculationTemplate
|
||||
@@ -442,7 +433,6 @@ Milestone: ฟีเจอร์ขั้นสูง
|
||||
### Phase 6: Tasks
|
||||
|
||||
- **[ ] T6.1 SearchModule - Elasticsearch Integration**
|
||||
|
||||
- [ ] Setup Elasticsearch Container ใน docker-compose.yml
|
||||
- [ ] สร้าง SearchService:
|
||||
- [ ] `indexDocument(entity)` → void
|
||||
@@ -461,7 +451,6 @@ Milestone: ฟีเจอร์ขั้นสูง
|
||||
- [ ] Deliverable: ค้นหาขั้นสูงทำงานได้
|
||||
|
||||
- **[ ] T6.2 NotificationModule - Email & Line**
|
||||
|
||||
- [ ] สร้าง NotificationService:
|
||||
- [ ] `sendEmail(to, subject, body)` → void (Nodemailer)
|
||||
- [ ] `sendLine(userId, message)` → void (ผ่าน n8n Webhook)
|
||||
@@ -477,7 +466,6 @@ Milestone: ฟีเจอร์ขั้นสูง
|
||||
- [ ] Deliverable: ระบบแจ้งเตือนทำงานได้
|
||||
|
||||
- **[ ] T6.3 Reporting & Analytics**
|
||||
|
||||
- [ ] สร้าง ReportService:
|
||||
- [ ] `getCorrespondenceSummary(projectId, from, to)` → Report
|
||||
- [ ] `getRfaSummary(projectId, from, to)` → Report
|
||||
@@ -512,7 +500,6 @@ Milestone: ทดสอบและปรับปรุงประสิทธ
|
||||
### Phase 7: Tasks
|
||||
|
||||
- **[ ] T7.1 Unit Testing**
|
||||
|
||||
- [ ] เขียน Unit Tests สำหรับ Services สำคัญ:
|
||||
- [ ] AuthService (login, validateUser)
|
||||
- [ ] RbacGuard (permission checks)
|
||||
@@ -523,7 +510,6 @@ Milestone: ทดสอบและปรับปรุงประสิทธ
|
||||
- [ ] Deliverable: Unit Tests ผ่านทั้งหมด
|
||||
|
||||
- **[ ] T7.2 Integration Testing**
|
||||
|
||||
- [ ] เขียน Integration Tests:
|
||||
- [ ] Authentication Flow (login → access protected route)
|
||||
- [ ] Document Creation Flow (create correspondence → attach files)
|
||||
@@ -534,7 +520,6 @@ Milestone: ทดสอบและปรับปรุงประสิทธ
|
||||
- [ ] Deliverable: Integration Tests ผ่าน
|
||||
|
||||
- **[ ] T7.3 E2E Testing**
|
||||
|
||||
- [ ] เขียน E2E Tests:
|
||||
- [ ] User Registration & Login
|
||||
- [ ] Create Correspondence (Full Flow)
|
||||
@@ -544,7 +529,6 @@ Milestone: ทดสอบและปรับปรุงประสิทธ
|
||||
- [ ] Deliverable: E2E Tests ผ่าน
|
||||
|
||||
- **[ ] T7.4 Performance Optimization**
|
||||
|
||||
- [ ] Implement Caching:
|
||||
- [ ] Cache Master Data (Roles, Permissions)
|
||||
- [ ] Cache User Permissions (ใช้ @nestjs/cache-manager)
|
||||
@@ -570,7 +554,6 @@ Milestone: เอกสารและ Deploy สู่ Production
|
||||
### Phase 8: Tasks
|
||||
|
||||
- **[ ] T8.1 API Documentation**
|
||||
|
||||
- [ ] ครบทุก Endpoint ใน Swagger:
|
||||
- [ ] ใส่ Description, Example Request/Response
|
||||
- [ ] ระบุ Required Permissions
|
||||
@@ -579,7 +562,6 @@ Milestone: เอกสารและ Deploy สู่ Production
|
||||
- [ ] Deliverable: Swagger Docs สมบูรณ์
|
||||
|
||||
- **[ ] T8.2 Technical Documentation**
|
||||
|
||||
- [ ] เขียนเอกสาร:
|
||||
- [ ] Architecture Overview
|
||||
- [ ] Module Structure
|
||||
@@ -589,7 +571,6 @@ Milestone: เอกสารและ Deploy สู่ Production
|
||||
- [ ] Deliverable: Technical Docs พร้อม
|
||||
|
||||
- **[ ] T8.3 Deployment Preparation**
|
||||
|
||||
- [ ] สร้าง Production docker-compose.yml
|
||||
- [ ] Setup Environment Variables ใน QNAP
|
||||
- [ ] Setup Nginx Proxy Manager (SSL Certificate)
|
||||
@@ -597,7 +578,6 @@ Milestone: เอกสารและ Deploy สู่ Production
|
||||
- [ ] Deliverable: Deployment Guide พร้อม
|
||||
|
||||
- **[ ] T8.4 Production Deployment**
|
||||
|
||||
- [ ] Deploy Backend ไปยัง backend.np-dms.work
|
||||
- [ ] ทดสอบ API ผ่าน Postman
|
||||
- [ ] Monitor Logs (Winston)
|
||||
|
||||
@@ -617,14 +617,14 @@
|
||||
|
||||
**Purpose**: เก็บข้อมูลแม่แบบ (Template) ของสายงานการส่งต่อเอกสารเพื่อขออนุมัติ ทำให้ไม่ต้องกำหนดขั้นตอนซ้ำทุกครั้ง สามารถสร้างเป็นแม่แบบทั่วไป หรือเฉพาะสำหรับโครงการใดโครงการหนึ่งได้
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------- | --------- | --------------------------- | -------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลัก (Primary Key) ของแม่แบบ รันค่าอัตโนมัติ |
|
||||
| template_name | VARCHAR(255) | NOT NULL | ชื่อของแม่แบบ เช่น "เสนอโครงการ", "ขออนุมัติจัดซื้อ" |
|
||||
| description | TEXT | NULL | คำอธิบายรายละเอียดเกี่ยวกับแม่แบบนี้ |
|
||||
| project_id | INT | NULL | ID ของโครงการที่แม่แบบนี้สังกัดอยู่ (ถ้ามี) **ค่า NULL หมายถึง** เป็น "แม่แบบทั่วไป" ที่สามารถใช้กับทุกโครงการได้ |
|
||||
| created_a | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | วันที่และเวลาที่สร้างแม่แบบนี้ |
|
||||
| updated_at | TIMESTAMP | NOT NULL,`DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | วันที่และเวลาที่แก้ไขข้อมูลในแม่แบบนี้ล่าสุด |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------- | ------------ | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลัก (Primary Key) ของแม่แบบ รันค่าอัตโนมัติ |
|
||||
| template_name | VARCHAR(255) | NOT NULL | ชื่อของแม่แบบ เช่น "เสนอโครงการ", "ขออนุมัติจัดซื้อ" |
|
||||
| description | TEXT | NULL | คำอธิบายรายละเอียดเกี่ยวกับแม่แบบนี้ |
|
||||
| project_id | INT | NULL | ID ของโครงการที่แม่แบบนี้สังกัดอยู่ (ถ้ามี) **ค่า NULL หมายถึง** เป็น "แม่แบบทั่วไป" ที่สามารถใช้กับทุกโครงการได้ |
|
||||
| created_a | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | วันที่และเวลาที่สร้างแม่แบบนี้ |
|
||||
| updated_at | TIMESTAMP | NOT NULL,`DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | วันที่และเวลาที่แก้ไขข้อมูลในแม่แบบนี้ล่าสุด |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -641,11 +641,11 @@
|
||||
|
||||
**Purpose**: ตารางนี้ใช้กำหนดกฎ (State Machine) ว่าสถานะใดสามารถเปลี่ยนไปเป็นสถานะใดได้บ้าง โดยขึ้นอยู่กับประเภทของหนังสือ เพื่อควบคุมการไหลของสถานะให้ถูกต้องตามข้อบังคับ
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------- | --------- | ----------- | ------------------------------------------------- |
|
||||
| type_id | INT | PRIMARY KEY | ID ของประเภทหนังสือ (เช่น หนังสือภายใน, หนังสือภายนอก) |
|
||||
| from_status_id | INT | PRIMARY KEY | ID ของสถานะต้นทาง (เช่น ร่าง) |
|
||||
| to_status_id | INT | PRIMARY KEY | ID ของสถานะปลายทาง (เช่น รออนุมัติ) |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------- | --------- | ----------- | ------------------------------------------------------ |
|
||||
| type_id | INT | PRIMARY KEY | ID ของประเภทหนังสือ (เช่น หนังสือภายใน, หนังสือภายนอก) |
|
||||
| from_status_id | INT | PRIMARY KEY | ID ของสถานะต้นทาง (เช่น ร่าง) |
|
||||
| to_status_id | INT | PRIMARY KEY | ID ของสถานะปลายทาง (เช่น รออนุมัติ) |
|
||||
|
||||
**คีย์หลัก (Primary Key):**
|
||||
|
||||
@@ -664,13 +664,13 @@
|
||||
|
||||
**Purpose**: เก็บรายละเอียดของแต่ละขั้นตอน (Steps) ภายในแม่แบบสายงาน (correspondence_routing_templates) กำหนดว่าจะส่งไปที่องค์กรไหน ลำดับเป็นเท่าไร และเพื่อวัตถุประสงค์อะไร
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :----- |----- | ----- | ---- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของขั้นตอน |
|
||||
| template_id | INT | NOT NULL | ID ของแม่แบบที่ขั้นตอนนี้สังกัดอยู่ |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอน (1, 2, 3, ...) |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรที่เป็นผู้รับในขั้นตอนนี้ |
|
||||
| step_purpose | ENUM | NOT NULL,DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้ **ค่าที่เป็นไปได้:** [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ] |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :----------------- | --------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของขั้นตอน |
|
||||
| template_id | INT | NOT NULL | ID ของแม่แบบที่ขั้นตอนนี้สังกัดอยู่ |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอน (1, 2, 3, ...) |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรที่เป็นผู้รับในขั้นตอนนี้ |
|
||||
| step_purpose | ENUM | NOT NULL,DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้ **ค่าที่เป็นไปได้:** [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ] |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -689,21 +689,21 @@
|
||||
|
||||
**Purpose**: เป็นตารางที่เก็บข้อมูลการส่งต่อเอกสารจริง (Instance/Run-time) ติดตามประวัติการเคลื่อนย้ายของแต่ละเอกสาร ว่าผ่านใครมาบ้าง อยู่ที่ใคร และสถานะปัจจุบันคืออะไร
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| --- | --- | --- | --- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของรายการส่งต่อ |
|
||||
| correspondence_id | INT | NOT NUL | ID ของเอกสาร (FK ไปยัง correspondence_revisions) |
|
||||
| template_id | INT | NULL | ID ของแม่แบบที่ใช้สร้างสายงานนี้ (เก็บไว้เป็นข้อมูลอ้างอิง) |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอนการส่งต่อจริง |
|
||||
| from_organization_id | INT | NOT NULL | ID ขององค์กรผู้ส่ง |
|
||||
| to_organization_id| INT | NOT NULL | ID ขององค์กรผู้รับ |
|
||||
| step_purpose | ENUM | NOT NULL, DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้จริง **ค่าที่เป็นไปได้:** [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ, FOR_ACTION: เพื่อดำเนินการ] |
|
||||
| status | ENUM | NOT NULL, DEFAULT SENT | [ACTIONED: ดำเนินการแล้ว, FORWARDED: ส่งต่อแล้ว, REPLIE: ตอบกลับแล้ว] |
|
||||
| comments | TEXT | NULL | หมายเหตุหรือความคิดเห็นในการส่งต่อ |
|
||||
| due_date | DATETIME | NULL | วันที่ครบกำหนดที่ต้องดำเนินการในขั้นตอนนี้ |
|
||||
| processed_by_user_id | INT |NULL | ID ของผู้ใช้ที่ดำเนินการในขั้นตอนนี้จริงๆ |
|
||||
| processed_at | TIMESTAMP | NULL | เวลาที่ผู้ใช้ดำเนินการเสร็จสิ้น |
|
||||
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | เวลาที่สร้างรายการส่งต่อนี้ |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------- | --------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของรายการส่งต่อ |
|
||||
| correspondence_id | INT | NOT NUL | ID ของเอกสาร (FK ไปยัง correspondence_revisions) |
|
||||
| template_id | INT | NULL | ID ของแม่แบบที่ใช้สร้างสายงานนี้ (เก็บไว้เป็นข้อมูลอ้างอิง) |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอนการส่งต่อจริง |
|
||||
| from_organization_id | INT | NOT NULL | ID ขององค์กรผู้ส่ง |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรผู้รับ |
|
||||
| step_purpose | ENUM | NOT NULL, DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้จริง **ค่าที่เป็นไปได้:** [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ, FOR_ACTION: เพื่อดำเนินการ] |
|
||||
| status | ENUM | NOT NULL, DEFAULT SENT | [ACTIONED: ดำเนินการแล้ว, FORWARDED: ส่งต่อแล้ว, REPLIE: ตอบกลับแล้ว] |
|
||||
| comments | TEXT | NULL | หมายเหตุหรือความคิดเห็นในการส่งต่อ |
|
||||
| due_date | DATETIME | NULL | วันที่ครบกำหนดที่ต้องดำเนินการในขั้นตอนนี้ |
|
||||
| processed_by_user_id | INT | NULL | ID ของผู้ใช้ที่ดำเนินการในขั้นตอนนี้จริงๆ |
|
||||
| processed_at | TIMESTAMP | NULL | เวลาที่ผู้ใช้ดำเนินการเสร็จสิ้น |
|
||||
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | เวลาที่สร้างรายการส่งต่อนี้ |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -2319,28 +2319,23 @@ CALL sp_get_next_document_number(
|
||||
**Additional Performance Indexes**:
|
||||
|
||||
1. **Correspondence Tables**:
|
||||
|
||||
- `idx_correspondences_type_project` on (correspondence_type_id, project_id)
|
||||
- `idx_corr_revisions_current_status` on (is_current, correspondence_status_id)
|
||||
- `idx_corr_revisions_correspondence_current` on (correspondence_id, is_current)
|
||||
- `idx_correspondences_project_type` on (project_id, correspondence_type_id)
|
||||
|
||||
2. **RFA Tables**:
|
||||
|
||||
- `idx_rfa_revisions_current_status` on (is_current, rfa_status_code_id)
|
||||
- `idx_rfa_revisions_rfa_current` on (rfa_id, is_current)
|
||||
|
||||
3. **Circulation Tables**:
|
||||
|
||||
- `idx_circulation_routings_status_assigned` on (status, assigned_to)
|
||||
- `idx_circulation_routings_circulation_status` on (circulation_id, status)
|
||||
|
||||
4. **Document Numbering**:
|
||||
|
||||
- `idx_doc_counter_composite` on (project_id, originator_organization_id, correspondence_type_id, current_year)
|
||||
|
||||
5. **Audit & Notifications**:
|
||||
|
||||
- `idx_audit_logs_reporting` on (created_at, entity_type, action)
|
||||
- `idx_notifications_user_unread` on (user_id, is_read, created_at)
|
||||
|
||||
@@ -2371,12 +2366,10 @@ CALL sp_get_next_document_number(
|
||||
### Unique Constraints
|
||||
|
||||
1. **Globally Unique**:
|
||||
|
||||
- usernames, emails
|
||||
- shop_drawing.drawing_number
|
||||
|
||||
2. **Unique Within Scope**:
|
||||
|
||||
- (project_id, correspondence_number)
|
||||
- (project_id, condwg_no)
|
||||
- (correspondence_id, revision_number)
|
||||
@@ -2395,13 +2388,11 @@ CALL sp_get_next_document_number(
|
||||
### Business Rule Constraints
|
||||
|
||||
1. **Soft Delete Pattern**:
|
||||
|
||||
- deleted_at timestamp instead of hard delete
|
||||
- Preserves audit trail and relationships
|
||||
- Applied to: correspondences, rfas, shop_drawings, contract_drawings
|
||||
|
||||
2. **Current Revision Pattern**:
|
||||
|
||||
- is_current flag with UNIQUE constraint
|
||||
- Ensures only one current revision per document
|
||||
|
||||
@@ -2586,13 +2577,11 @@ ANALYZE TABLE correspondences;
|
||||
### Business Logic Validation
|
||||
|
||||
1. **Document Workflow**:
|
||||
|
||||
- Cannot edit submitted documents (unless Document Control)
|
||||
- Cannot skip workflow steps (unless forced)
|
||||
- Must provide approval comments
|
||||
|
||||
2. **User Management**:
|
||||
|
||||
- Cannot delete users with active assignments
|
||||
- Cannot deactivate own account
|
||||
- Must have valid organization for non-Global roles
|
||||
@@ -2708,19 +2697,16 @@ ANALYZE TABLE correspondences;
|
||||
### Integration Points
|
||||
|
||||
1. **Document Numbering**:
|
||||
|
||||
- Call sp_get_next_document_number
|
||||
- Format with template from document_number_formats
|
||||
- Store in correspondences.correspondence_number
|
||||
|
||||
2. **File Upload**:
|
||||
|
||||
- Upload to QNAP /share/dms-data/
|
||||
- Create attachment record
|
||||
- Link via junction table
|
||||
|
||||
3. **Workflow Execution**:
|
||||
|
||||
- Check rfa_workflow_templates
|
||||
- Create rfa_workflows records
|
||||
- Update status as steps complete
|
||||
@@ -2832,4 +2818,4 @@ SELECT * FROM information_schema.INNODB_LOCK_WAITS;
|
||||
|
||||
---
|
||||
|
||||
_End of Data Dictionary
|
||||
\_End of Data Dictionary
|
||||
|
||||
@@ -191,18 +191,18 @@ npx shadcn-ui@latest init
|
||||
- สร้าง `lib/api/client.ts`:
|
||||
|
||||
```typescript
|
||||
import axios from "axios";
|
||||
import axios from 'axios';
|
||||
|
||||
export const apiClient = axios.create({
|
||||
baseURL: process.env.NEXT_PUBLIC_API_URL,
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
// Request Interceptor (Add JWT Token)
|
||||
apiClient.interceptors.request.use((config) => {
|
||||
const token = localStorage.getItem("access_token");
|
||||
const token = localStorage.getItem('access_token');
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
@@ -215,7 +215,7 @@ npx shadcn-ui@latest init
|
||||
(error) => {
|
||||
if (error.response?.status === 401) {
|
||||
// Redirect to login
|
||||
window.location.href = "/login";
|
||||
window.location.href = '/login';
|
||||
}
|
||||
return Promise.reject(error);
|
||||
}
|
||||
@@ -260,8 +260,8 @@ npx shadcn-ui@latest init
|
||||
- สร้าง `lib/stores/auth-store.ts`:
|
||||
|
||||
```typescript
|
||||
import { create } from "zustand";
|
||||
import { persist } from "zustand/middleware";
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
interface User {
|
||||
user_id: number;
|
||||
@@ -288,11 +288,11 @@ npx shadcn-ui@latest init
|
||||
token: null,
|
||||
setAuth: (user, token) => {
|
||||
set({ user, token });
|
||||
localStorage.setItem("access_token", token);
|
||||
localStorage.setItem('access_token', token);
|
||||
},
|
||||
clearAuth: () => {
|
||||
set({ user: null, token: null });
|
||||
localStorage.removeItem("access_token");
|
||||
localStorage.removeItem('access_token');
|
||||
},
|
||||
hasPermission: (permission) => {
|
||||
const user = get().user;
|
||||
@@ -300,7 +300,7 @@ npx shadcn-ui@latest init
|
||||
},
|
||||
}),
|
||||
{
|
||||
name: "auth-storage",
|
||||
name: 'auth-storage',
|
||||
}
|
||||
)
|
||||
);
|
||||
@@ -491,14 +491,14 @@ npx shadcn-ui@latest init
|
||||
- สร้าง `lib/api/hooks/use-my-tasks.ts`:
|
||||
|
||||
```typescript
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { apiClient } from "../client";
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { apiClient } from '../client';
|
||||
|
||||
export function useMyTasks() {
|
||||
return useQuery({
|
||||
queryKey: ["my-tasks"],
|
||||
queryKey: ['my-tasks'],
|
||||
queryFn: async () => {
|
||||
const response = await apiClient.get("/circulations/my-tasks");
|
||||
const response = await apiClient.get('/circulations/my-tasks');
|
||||
return response.data;
|
||||
},
|
||||
});
|
||||
@@ -682,23 +682,23 @@ npx shadcn-ui@latest init
|
||||
- สร้าง `lib/api/hooks/use-rfa-workflow.ts`:
|
||||
|
||||
```typescript
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { apiClient } from "../client";
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { apiClient } from '../client';
|
||||
|
||||
export function useCompleteWorkflowStep() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({ rfaId, stepNumber, action, comments }) => {
|
||||
const response = await apiClient.post(
|
||||
`/rfas/${rfaId}/workflow/steps/${stepNumber}/complete`,
|
||||
{ action, comments }
|
||||
);
|
||||
const response = await apiClient.post(`/rfas/${rfaId}/workflow/steps/${stepNumber}/complete`, {
|
||||
action,
|
||||
comments,
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
queryClient.invalidateQueries(["rfa", variables.rfaId]);
|
||||
queryClient.invalidateQueries(["my-tasks"]);
|
||||
queryClient.invalidateQueries(['rfa', variables.rfaId]);
|
||||
queryClient.invalidateQueries(['my-tasks']);
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,142 +8,142 @@
|
||||
|
||||
### **หลักการพื้นฐาน**
|
||||
|
||||
* ใช้ **ภาษาอังกฤษ** สำหรับโค้ด
|
||||
* ใช้ **ภาษาไทย** สำหรับ comment และเอกสารทั้งหมด
|
||||
* กำหนดไทป์ (type) อย่างชัดเจนสำหรับตัวแปร, พารามิเตอร์ และค่าที่ส่งกลับ (return values) ทั้งหมด
|
||||
* หลีกเลี่ยงการใช้ any; ให้สร้างไทป์ (types) หรืออินเทอร์เฟซ (interfaces) ที่กำหนดเอง
|
||||
* ใช้ **JSDoc** สำหรับคลาส (classes) และเมธอด (methods) ที่เป็น public
|
||||
* ส่งออก (Export) **สัญลักษณ์หลัก (main symbol) เพียงหนึ่งเดียว** ต่อไฟล์
|
||||
* หลีกเลี่ยงบรรทัดว่างภายในฟังก์ชัน
|
||||
* ระบุ // File: path/filename ในบรรทัดแรกของทุกไฟล์
|
||||
* ระบุ // บันทึกการแก้ไข, หากมีการแก้ไขเพิ่มในอนาคต ให้เพิ่มบันทึก
|
||||
- ใช้ **ภาษาอังกฤษ** สำหรับโค้ด
|
||||
- ใช้ **ภาษาไทย** สำหรับ comment และเอกสารทั้งหมด
|
||||
- กำหนดไทป์ (type) อย่างชัดเจนสำหรับตัวแปร, พารามิเตอร์ และค่าที่ส่งกลับ (return values) ทั้งหมด
|
||||
- หลีกเลี่ยงการใช้ any; ให้สร้างไทป์ (types) หรืออินเทอร์เฟซ (interfaces) ที่กำหนดเอง
|
||||
- ใช้ **JSDoc** สำหรับคลาส (classes) และเมธอด (methods) ที่เป็น public
|
||||
- ส่งออก (Export) **สัญลักษณ์หลัก (main symbol) เพียงหนึ่งเดียว** ต่อไฟล์
|
||||
- หลีกเลี่ยงบรรทัดว่างภายในฟังก์ชัน
|
||||
- ระบุ // File: path/filename ในบรรทัดแรกของทุกไฟล์
|
||||
- ระบุ // บันทึกการแก้ไข, หากมีการแก้ไขเพิ่มในอนาคต ให้เพิ่มบันทึก
|
||||
|
||||
### **ข้อตกลงในการตั้งชื่อ (Naming Conventions)**
|
||||
|
||||
| Entity (สิ่งที่ตั้งชื่อ) | Convention (รูปแบบ) | Example (ตัวอย่าง) |
|
||||
| :---- | :---- | :---- |
|
||||
| Classes | PascalCase | UserService |
|
||||
| Property | snake_sase | user_id |
|
||||
| Variables & Functions | camelCase | getUserInfo |
|
||||
| Files & Folders | kebab-case | user-service.ts |
|
||||
| Environment Variables | UPPERCASE | DATABASE\URL |
|
||||
| Booleans | Verb \+ Noun | isActive, canDelete, hasPermission |
|
||||
| Entity (สิ่งที่ตั้งชื่อ) | Convention (รูปแบบ) | Example (ตัวอย่าง) |
|
||||
| :----------------------- | :------------------ | :--------------------------------- |
|
||||
| Classes | PascalCase | UserService |
|
||||
| Property | snake_sase | user_id |
|
||||
| Variables & Functions | camelCase | getUserInfo |
|
||||
| Files & Folders | kebab-case | user-service.ts |
|
||||
| Environment Variables | UPPERCASE | DATABASE\URL |
|
||||
| Booleans | Verb \+ Noun | isActive, canDelete, hasPermission |
|
||||
|
||||
ใช้คำเต็ม — ไม่ใช้อักษรย่อ — ยกเว้นคำมาตรฐาน (เช่น API, URL, req, res, err, ctx)
|
||||
|
||||
## **🧩 ฟังก์ชัน (Functions)**
|
||||
|
||||
* เขียนฟังก์ชันให้สั้น และทำ **หน้าที่เพียงอย่างเดียว** (single-purpose) (\< 20 บรรทัด)
|
||||
* ใช้ **early returns** เพื่อลดการซ้อน (nesting) ของโค้ด
|
||||
* ใช้ **map**, **filter**, **reduce** แทนการใช้ loops เมื่อเหมาะสม
|
||||
* ควรใช้ **arrow functions** สำหรับตรรกะสั้นๆ, และใช้ **named functions** ในกรณีอื่น
|
||||
* ใช้ **default parameters** แทนการตรวจสอบค่า null
|
||||
* จัดกลุ่มพารามิเตอร์หลายตัวให้เป็นอ็อบเจกต์เดียว (RO-RO pattern)
|
||||
* ส่งค่ากลับ (Return) เป็นอ็อบเจกต์ที่มีไทป์กำหนด (typed objects) ไม่ใช่ค่าพื้นฐาน (primitives)
|
||||
* รักษาระดับของสิ่งที่เป็นนามธรรม (abstraction level) ให้เป็นระดับเดียวในแต่ละฟังก์ชัน
|
||||
- เขียนฟังก์ชันให้สั้น และทำ **หน้าที่เพียงอย่างเดียว** (single-purpose) (\< 20 บรรทัด)
|
||||
- ใช้ **early returns** เพื่อลดการซ้อน (nesting) ของโค้ด
|
||||
- ใช้ **map**, **filter**, **reduce** แทนการใช้ loops เมื่อเหมาะสม
|
||||
- ควรใช้ **arrow functions** สำหรับตรรกะสั้นๆ, และใช้ **named functions** ในกรณีอื่น
|
||||
- ใช้ **default parameters** แทนการตรวจสอบค่า null
|
||||
- จัดกลุ่มพารามิเตอร์หลายตัวให้เป็นอ็อบเจกต์เดียว (RO-RO pattern)
|
||||
- ส่งค่ากลับ (Return) เป็นอ็อบเจกต์ที่มีไทป์กำหนด (typed objects) ไม่ใช่ค่าพื้นฐาน (primitives)
|
||||
- รักษาระดับของสิ่งที่เป็นนามธรรม (abstraction level) ให้เป็นระดับเดียวในแต่ละฟังก์ชัน
|
||||
|
||||
## **🧱 การจัดการข้อมูล (Data Handling)**
|
||||
|
||||
* ห่อหุ้มข้อมูล (Encapsulate) ในไทป์แบบผสม (composite types)
|
||||
* ใช้ **immutability** (การไม่เปลี่ยนแปลงค่า) ด้วย readonly และ as const
|
||||
* ทำการตรวจสอบความถูกต้องของข้อมูล (Validations) ในคลาสหรือ DTOs ไม่ใช่ภายในฟังก์ชันทางธุรกิจ
|
||||
* ตรวจสอบความถูกต้องของข้อมูลโดยใช้ DTOs ที่มีไทป์กำหนดเสมอ
|
||||
- ห่อหุ้มข้อมูล (Encapsulate) ในไทป์แบบผสม (composite types)
|
||||
- ใช้ **immutability** (การไม่เปลี่ยนแปลงค่า) ด้วย readonly และ as const
|
||||
- ทำการตรวจสอบความถูกต้องของข้อมูล (Validations) ในคลาสหรือ DTOs ไม่ใช่ภายในฟังก์ชันทางธุรกิจ
|
||||
- ตรวจสอบความถูกต้องของข้อมูลโดยใช้ DTOs ที่มีไทป์กำหนดเสมอ
|
||||
|
||||
## **🧰 คลาส (Classes)**
|
||||
|
||||
* ปฏิบัติตามหลักการ **SOLID**
|
||||
* ควรใช้ **composition มากกว่า inheritance** (Prefer composition over inheritance)
|
||||
* กำหนด **interfaces** สำหรับสัญญา (contracts)
|
||||
* ให้คลาสมุ่งเน้นการทำงานเฉพาะอย่างและมีขนาดเล็ก (\< 200 บรรทัด, \< 10 เมธอด, \< 10 properties)
|
||||
- ปฏิบัติตามหลักการ **SOLID**
|
||||
- ควรใช้ **composition มากกว่า inheritance** (Prefer composition over inheritance)
|
||||
- กำหนด **interfaces** สำหรับสัญญา (contracts)
|
||||
- ให้คลาสมุ่งเน้นการทำงานเฉพาะอย่างและมีขนาดเล็ก (\< 200 บรรทัด, \< 10 เมธอด, \< 10 properties)
|
||||
|
||||
## **🚨 การจัดการข้อผิดพลาด (Error Handling)**
|
||||
|
||||
* ใช้ Exceptions สำหรับข้อผิดพลาดที่ไม่คาดคิด
|
||||
* ดักจับ (Catch) ข้อผิดพลาดเพื่อแก้ไขหรือเพิ่มบริบท (context) เท่านั้น; หากไม่เช่นนั้น ให้ใช้ global error handlers
|
||||
* ระบุข้อความข้อผิดพลาด (error messages) ที่มีความหมายเสมอ
|
||||
- ใช้ Exceptions สำหรับข้อผิดพลาดที่ไม่คาดคิด
|
||||
- ดักจับ (Catch) ข้อผิดพลาดเพื่อแก้ไขหรือเพิ่มบริบท (context) เท่านั้น; หากไม่เช่นนั้น ให้ใช้ global error handlers
|
||||
- ระบุข้อความข้อผิดพลาด (error messages) ที่มีความหมายเสมอ
|
||||
|
||||
## **🧪 การทดสอบ (ทั่วไป) (Testing (General))**
|
||||
|
||||
* ใช้รูปแบบ **Arrange–Act–Assert**
|
||||
* ใช้ชื่อตัวแปรในการทดสอบที่สื่อความหมาย (inputData, expectedOutput)
|
||||
* เขียน **unit tests** สำหรับ public methods ทั้งหมด
|
||||
* จำลอง (Mock) การพึ่งพาภายนอก (external dependencies)
|
||||
* เพิ่ม **acceptance tests** ต่อโมดูลโดยใช้รูปแบบ Given–When-Then
|
||||
- ใช้รูปแบบ **Arrange–Act–Assert**
|
||||
- ใช้ชื่อตัวแปรในการทดสอบที่สื่อความหมาย (inputData, expectedOutput)
|
||||
- เขียน **unit tests** สำหรับ public methods ทั้งหมด
|
||||
- จำลอง (Mock) การพึ่งพาภายนอก (external dependencies)
|
||||
- เพิ่ม **acceptance tests** ต่อโมดูลโดยใช้รูปแบบ Given–When-Then
|
||||
|
||||
## **🏗️ แบ็กเอนด์ (NestJS) (Backend (NestJS))**
|
||||
|
||||
### **หลักการ**
|
||||
|
||||
* **สถาปัตยกรรมแบบโมดูลาร์ (Modular architecture)**:
|
||||
* หนึ่งโมดูลต่อหนึ่งโดเมน
|
||||
* โครงสร้างแบบ Controller → Service → Repository (Model)
|
||||
* API-First: มุ่งเน้นการสร้าง API ที่มีคุณภาพสูง มีเอกสารประกอบ (Swagger) ที่ชัดเจนสำหรับ Frontend Team
|
||||
* DTOs ที่ตรวจสอบความถูกต้องด้วย **class-validator**
|
||||
* ใช้ **MikroORM** (หรือ TypeORM/Prisma) สำหรับการคงอยู่ของข้อมูล (persistence) ซึ่งสอดคล้องกับสคีมา MariaDB
|
||||
* ห่อหุ้มโค้ดที่ใช้ซ้ำได้ไว้ใน **common module** (@app/common):
|
||||
* Configs, decorators, DTOs, guards, interceptors, notifications, shared services, types, validators
|
||||
- **สถาปัตยกรรมแบบโมดูลาร์ (Modular architecture)**:
|
||||
- หนึ่งโมดูลต่อหนึ่งโดเมน
|
||||
- โครงสร้างแบบ Controller → Service → Repository (Model)
|
||||
- API-First: มุ่งเน้นการสร้าง API ที่มีคุณภาพสูง มีเอกสารประกอบ (Swagger) ที่ชัดเจนสำหรับ Frontend Team
|
||||
- DTOs ที่ตรวจสอบความถูกต้องด้วย **class-validator**
|
||||
- ใช้ **MikroORM** (หรือ TypeORM/Prisma) สำหรับการคงอยู่ของข้อมูล (persistence) ซึ่งสอดคล้องกับสคีมา MariaDB
|
||||
- ห่อหุ้มโค้ดที่ใช้ซ้ำได้ไว้ใน **common module** (@app/common):
|
||||
- Configs, decorators, DTOs, guards, interceptors, notifications, shared services, types, validators
|
||||
|
||||
### **ฟังก์ชันหลัก (Core Functionalities)**
|
||||
|
||||
* Global **filters** สำหรับการจัดการ exception
|
||||
* **Middlewares** สำหรับการจัดการ request
|
||||
* **Guards** สำหรับการอนุญาต (permissions) และ RBAC
|
||||
* **Interceptors** สำหรับการแปลงข้อมูล response และการบันทึก log
|
||||
- Global **filters** สำหรับการจัดการ exception
|
||||
- **Middlewares** สำหรับการจัดการ request
|
||||
- **Guards** สำหรับการอนุญาต (permissions) และ RBAC
|
||||
- **Interceptors** สำหรับการแปลงข้อมูล response และการบันทึก log
|
||||
|
||||
### **ข้อจำกัดในการ Deploy (QNAP Container Station)**
|
||||
|
||||
* **ห้ามใช้ไฟล์ .env** ในการตั้งค่า Environment Variables [cite: 2.1]
|
||||
* การตั้งค่าทั้งหมด (เช่น Database connection string, JWT secret) **จะต้องถูกกำหนดผ่าน Environment Variable ใน docker-compose.yml โดยตรง** [cite: 6.5] ซึ่งจะจัดการผ่าน UI ของ QNAP Container Station [cite: 2.1]
|
||||
- **ห้ามใช้ไฟล์ .env** ในการตั้งค่า Environment Variables [cite: 2.1]
|
||||
- การตั้งค่าทั้งหมด (เช่น Database connection string, JWT secret) **จะต้องถูกกำหนดผ่าน Environment Variable ใน docker-compose.yml โดยตรง** [cite: 6.5] ซึ่งจะจัดการผ่าน UI ของ QNAP Container Station [cite: 2.1]
|
||||
|
||||
### **โครงสร้างโมดูลตามโดเมน (Domain-Driven Module Structure)**
|
||||
|
||||
เพื่อให้สอดคล้องกับสคีมา SQL (LCBP3-DMS) เราจะใช้โครงสร้างโมดูลแบบ **Domain-Driven (แบ่งตามขอบเขตธุรกิจ)** แทนการแบ่งตามฟังก์ชัน:
|
||||
|
||||
1. **CommonModule:**
|
||||
* เก็บ Services ที่ใช้ร่วมกัน เช่น DatabaseModule, FileStorageService (จัดการไฟล์ใน QNAP), AuditLogService, NotificationService
|
||||
* จัดการ audit_logs
|
||||
* NotificationService ต้องรองรับ Triggers ที่ระบุใน Requirement 6.7 [cite: 6.7]
|
||||
- เก็บ Services ที่ใช้ร่วมกัน เช่น DatabaseModule, FileStorageService (จัดการไฟล์ใน QNAP), AuditLogService, NotificationService
|
||||
- จัดการ audit_logs
|
||||
- NotificationService ต้องรองรับ Triggers ที่ระบุใน Requirement 6.7 [cite: 6.7]
|
||||
2. **AuthModule:**
|
||||
* จัดการะการยืนยันตัวตน (JWT, Guards)
|
||||
* **(สำคัญ)** ต้องรับผิดชอบการตรวจสอบสิทธิ์ **4 ระดับ** [cite: 4.2]: สิทธิ์ระดับระบบ (Global Role), สิทธิ์ระดับองกรณ์ (Organization Role), สิทธิ์ระดับโปรเจกต์ (Project Role), และ สิทธิ์ระดับสัญญา (Contract Role)
|
||||
* **(สำคัญ)** ต้องมี API สำหรับ **Admin Panel** เพื่อ:
|
||||
* สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก [cite: 4.3]
|
||||
* ให้ Superadmin สร้าง Organizations และกำหนด Org Admin ได้ [cite: 4.6]
|
||||
* ให้ Superadmin/Admin จัดการ document_number_formats (รูปแบบเลขที่เอกสาร), document_number_counters (Running Number) [cite: 3.10]
|
||||
- จัดการะการยืนยันตัวตน (JWT, Guards)
|
||||
- **(สำคัญ)** ต้องรับผิดชอบการตรวจสอบสิทธิ์ **4 ระดับ** [cite: 4.2]: สิทธิ์ระดับระบบ (Global Role), สิทธิ์ระดับองกรณ์ (Organization Role), สิทธิ์ระดับโปรเจกต์ (Project Role), และ สิทธิ์ระดับสัญญา (Contract Role)
|
||||
- **(สำคัญ)** ต้องมี API สำหรับ **Admin Panel** เพื่อ:
|
||||
- สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก [cite: 4.3]
|
||||
- ให้ Superadmin สร้าง Organizations และกำหนด Org Admin ได้ [cite: 4.6]
|
||||
- ให้ Superadmin/Admin จัดการ document_number_formats (รูปแบบเลขที่เอกสาร), document_number_counters (Running Number) [cite: 3.10]
|
||||
3. **UserModule:**
|
||||
* จัดการ users, roles, permissions, global_default_roles, role_permissions, user_roles, user_project_roles
|
||||
* **(สำคัญ)** ต้องมี API สำหรับ **Admin Panel** เพื่อ:
|
||||
* สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก [cite: 4.3]
|
||||
- จัดการ users, roles, permissions, global_default_roles, role_permissions, user_roles, user_project_roles
|
||||
- **(สำคัญ)** ต้องมี API สำหรับ **Admin Panel** เพื่อ:
|
||||
- สร้างและจัดการ Role และการจับคู่ Permission แบบไดนามิก [cite: 4.3]
|
||||
4. **ProjectModule:**
|
||||
* จัดการ projects, organizations, contracts, project_parties, contract_parties
|
||||
- จัดการ projects, organizations, contracts, project_parties, contract_parties
|
||||
5. **MasterModule:**
|
||||
* จัดการ master data (correspondence_types, rfa_types, rfa_status_codes, rfa_approve_codes, circulation_status_codes, correspondence_types, correspondence_status, tags) [cite: 4.5]
|
||||
- จัดการ master data (correspondence_types, rfa_types, rfa_status_codes, rfa_approve_codes, circulation_status_codes, correspondence_types, correspondence_status, tags) [cite: 4.5]
|
||||
6. **CorrespondenceModule (โมดูลศูนย์กลาง):**
|
||||
* จัดการ correspondences, correspondence_revisions, correspondence_tags
|
||||
|
||||
* **(สำคัญ)** Service นี้ต้อง Inject DocumentNumberingService เพื่อขอเลขที่เอกสารใหม่ก่อนการสร้าง
|
||||
* **(สำคัญ)** ตรรกะการสร้าง/อัปเดต Revision จะอยู่ใน Service นี้
|
||||
* จัดการ correspondence_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
* รับผิดชอบ Routing **Correspondence Routing** (correspondence_routings, correspondence_routing_template_steps, correspondence_routing_templates, correspondence_status_transitions) สำหรับการส่งต่อเอกสารทั่วไประหว่างองค์กร
|
||||
- จัดการ correspondences, correspondence_revisions, correspondence_tags
|
||||
- **(สำคัญ)** Service นี้ต้อง Inject DocumentNumberingService เพื่อขอเลขที่เอกสารใหม่ก่อนการสร้าง
|
||||
- **(สำคัญ)** ตรรกะการสร้าง/อัปเดต Revision จะอยู่ใน Service นี้
|
||||
- จัดการ correspondence_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
- รับผิดชอบ Routing **Correspondence Routing** (correspondence_routings, correspondence_routing_template_steps, correspondence_routing_templates, correspondence_status_transitions) สำหรับการส่งต่อเอกสารทั่วไประหว่างองค์กร
|
||||
|
||||
7. **RfaModule:**
|
||||
* จัดการ rfas, rfa_revisions, rfa_items
|
||||
* รับผิดชอบเวิร์กโฟลว์ **"RFA Workflows"** (rfa_workflows, rfa_workflow_templates, rfa_workflow_template_steps, rfa_status_transitions) สำหรับการอนุมัติเอกสารทางเทคนิค
|
||||
- จัดการ rfas, rfa_revisions, rfa_items
|
||||
- รับผิดชอบเวิร์กโฟลว์ **"RFA Workflows"** (rfa_workflows, rfa_workflow_templates, rfa_workflow_template_steps, rfa_status_transitions) สำหรับการอนุมัติเอกสารทางเทคนิค
|
||||
8. **DrawingModule:**
|
||||
* จัดการ shop_drawings, shop_drawing_revisions, contract_drawings, contract_drawing_volumes, contract_drawing_cats, contract_drawing_sub_cats, shop_drawing_main_categories, shop_drawing_sub_categories, contract_drawing_subcat_cat_maps, shop_drawing_revision_contract_refs
|
||||
* จัดการ shop_drawing_revision_attachments และ contract_drawing_attachments(ตารางเชื่อมไฟล์แนบ)
|
||||
- จัดการ shop_drawings, shop_drawing_revisions, contract_drawings, contract_drawing_volumes, contract_drawing_cats, contract_drawing_sub_cats, shop_drawing_main_categories, shop_drawing_sub_categories, contract_drawing_subcat_cat_maps, shop_drawing_revision_contract_refs
|
||||
- จัดการ shop_drawing_revision_attachments และ contract_drawing_attachments(ตารางเชื่อมไฟล์แนบ)
|
||||
9. **CirculationModule:**
|
||||
* จัดการ circulations, circulation_templates, circulation_assignees
|
||||
* จัดการ circulation_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
* รับผิดชอบเวิร์กโฟลว์ **"Circulations"** (circulation_status_transitions, circulation_template_assignees, circulation_assignees, circulation_recipients, circulation_actions, circulation_action_documents)สำหรับการเวียนเอกสาร **ภายในองค์กร**
|
||||
- จัดการ circulations, circulation_templates, circulation_assignees
|
||||
- จัดการ circulation_attachments (ตารางเชื่อมไฟล์แนบ)
|
||||
- รับผิดชอบเวิร์กโฟลว์ **"Circulations"** (circulation_status_transitions, circulation_template_assignees, circulation_assignees, circulation_recipients, circulation_actions, circulation_action_documents)สำหรับการเวียนเอกสาร **ภายในองค์กร**
|
||||
10. **TransmittalModule:**
|
||||
* จัดการ transmittals และ transmittal_items
|
||||
- จัดการ transmittals และ transmittal_items
|
||||
11. **SearchModule:**
|
||||
* ให้บริการค้นหาขั้นสูง (Advanced Search) [cite: 6.2] โดยใช้ **Elasticsearch** เพื่อรองรับการค้นหาแบบ Full-text จากชื่อเรื่อง, รายละเอียด, เลขที่เอกสาร, ประเภท, วันที่, และ Tags
|
||||
* ระบบจะใช้ Elasticsearch Engine ในการจัดทำดัชนีเพื่อการค้นหาข้อมูลเชิงลึกจากเนื้อหาของเอกสาร โดยข้อมูลจะถูกส่งไปทำดัชนีจาก Backend (NestJS) ทุกครั้งที่มีการสร้างหรือแก้ไขเอกสาร
|
||||
- ให้บริการค้นหาขั้นสูง (Advanced Search) [cite: 6.2] โดยใช้ **Elasticsearch** เพื่อรองรับการค้นหาแบบ Full-text จากชื่อเรื่อง, รายละเอียด, เลขที่เอกสาร, ประเภท, วันที่, และ Tags
|
||||
- ระบบจะใช้ Elasticsearch Engine ในการจัดทำดัชนีเพื่อการค้นหาข้อมูลเชิงลึกจากเนื้อหาของเอกสาร โดยข้อมูลจะถูกส่งไปทำดัชนีจาก Backend (NestJS) ทุกครั้งที่มีการสร้างหรือแก้ไขเอกสาร
|
||||
12. **DocumentNumberingModule:**
|
||||
* **สถานะ:** เป็น Module ภายใน (Internal Module) ไม่เปิด API สู่ภายนอก
|
||||
* **หน้าที่:** ให้บริการ DocumentNumberingService ที่ Module อื่น (เช่น CorrespondenceModule) จะ Inject ไปใช้งาน
|
||||
* **ตรรกะ:** รับผิดชอบการสร้างเลขที่เอกสาร โดยการเรียกใช้ Stored Procedure *sp_get_next_document_number** เพื่อป้องกัน Race Condition
|
||||
- **สถานะ:** เป็น Module ภายใน (Internal Module) ไม่เปิด API สู่ภายนอก
|
||||
- **หน้าที่:** ให้บริการ DocumentNumberingService ที่ Module อื่น (เช่น CorrespondenceModule) จะ Inject ไปใช้งาน
|
||||
- **ตรรกะ:** รับผิดชอบการสร้างเลขที่เอกสาร โดยการเรียกใช้ Stored Procedure \*sp_get_next_document_number\*\* เพื่อป้องกัน Race Condition
|
||||
|
||||
### **สถาปัตยกรรมระบบ (System Architecture)**
|
||||
|
||||
@@ -178,46 +178,46 @@
|
||||
|
||||
### **เเทคโนโลยีที่ใช้ (Technology Stack)**
|
||||
|
||||
| ส่วน | Library/Tool | หมายเหตุ |
|
||||
|---|---|---|
|
||||
| **Framework** | `@nestjs/core`, `@nestjs/common` | Core Framework |
|
||||
| **Language** | `TypeScript` | ใช้ TypeScript ทั้งระบบ |
|
||||
| **Database** | `MariaDB 10.11` | ฐานข้อมูลหลัก |
|
||||
| **ORM** | `@nestjs/typeorm`, `typeorm` | 🗃️จัดการการเชื่อมต่อและ Query ฐานข้อมูล |
|
||||
| **Validation** | `class-validator`, `class-transformer` | 📦ตรวจสอบและแปลงข้อมูลใน DTO |
|
||||
| **Auth** | `@nestjs/jwt`, `@nestjs/passport`, `passport-jwt` | 🔐การยืนยันตัวตนด้วย JWT |
|
||||
|**Authorization** | `casl` | 🔐จัดการสิทธิ์แบบ RBAC |
|
||||
| **File Upload** | `multer` | 📁จัดการการอัปโหลดไฟล์ |
|
||||
| **Search** | `@nestjs/elasticsearch` | 🔍สำหรับการค้นหาขั้นสูง |
|
||||
| **Notification** | `nodemailer` | 📬ส่งอีเมลแจ้งเตือน |
|
||||
| **Scheduling** | `@nestjs/schedule` | 📬สำหรับ Cron Jobs (เช่น แจ้งเตือน Deadline) |
|
||||
| **Logging** | `winston` | 📊บันทึก Log ที่มีประสิทธิภาพ |
|
||||
| **Testing** | `@nestjs/testing`, `jest`, `supertest` | 🧪ทดสอบ Unit, Integration และ E2E |
|
||||
| **Documentation** | `@nestjs/swagger` | 🌐สร้าง API Documentation อัตโนมัติ |
|
||||
| **Security** | `helmet`, `rate-limiter-flexible` | 🛡️เพิ่มความปลอดภัยให้ API |
|
||||
| ส่วน | Library/Tool | หมายเหตุ |
|
||||
| ----------------- | ------------------------------------------------- | -------------------------------------------- |
|
||||
| **Framework** | `@nestjs/core`, `@nestjs/common` | Core Framework |
|
||||
| **Language** | `TypeScript` | ใช้ TypeScript ทั้งระบบ |
|
||||
| **Database** | `MariaDB 10.11` | ฐานข้อมูลหลัก |
|
||||
| **ORM** | `@nestjs/typeorm`, `typeorm` | 🗃️จัดการการเชื่อมต่อและ Query ฐานข้อมูล |
|
||||
| **Validation** | `class-validator`, `class-transformer` | 📦ตรวจสอบและแปลงข้อมูลใน DTO |
|
||||
| **Auth** | `@nestjs/jwt`, `@nestjs/passport`, `passport-jwt` | 🔐การยืนยันตัวตนด้วย JWT |
|
||||
| **Authorization** | `casl` | 🔐จัดการสิทธิ์แบบ RBAC |
|
||||
| **File Upload** | `multer` | 📁จัดการการอัปโหลดไฟล์ |
|
||||
| **Search** | `@nestjs/elasticsearch` | 🔍สำหรับการค้นหาขั้นสูง |
|
||||
| **Notification** | `nodemailer` | 📬ส่งอีเมลแจ้งเตือน |
|
||||
| **Scheduling** | `@nestjs/schedule` | 📬สำหรับ Cron Jobs (เช่น แจ้งเตือน Deadline) |
|
||||
| **Logging** | `winston` | 📊บันทึก Log ที่มีประสิทธิภาพ |
|
||||
| **Testing** | `@nestjs/testing`, `jest`, `supertest` | 🧪ทดสอบ Unit, Integration และ E2E |
|
||||
| **Documentation** | `@nestjs/swagger` | 🌐สร้าง API Documentation อัตโนมัติ |
|
||||
| **Security** | `helmet`, `rate-limiter-flexible` | 🛡️เพิ่มความปลอดภัยให้ API |
|
||||
|
||||
เราจะแบ่งการทดสอบเป็น 3 ระดับ โดยใช้ **Jest** และ @nestjs/testing:
|
||||
|
||||
* **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
* **เป้าหมาย:** ทดสอบ Logic ภายใน Service, Guard, หรือ Pipe โดยจำลอง (Mock) Dependencies ทั้งหมด
|
||||
* **สิ่งที่ต้องทดสอบ:** Business Logic (เช่น การเปลี่ยนสถานะ Workflow, การตรวจสอบ Deadline) [cite: 2.9.1], ตรรกะการตรวจสอบสิทธิ์ (Auth Guard) ทั้ง 4 ระดับ
|
||||
* **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
* **เป้าหมาย:** ทดสอบการทำงานร่วมกันของ Controller -> Service -> Repository (Database)
|
||||
* **เทคนิค:** ใช้ **Test Database แยกต่างหาก** (ห้ามใช้ Dev DB) และใช้ supertest เพื่อยิง HTTP Request จริงไปยัง App
|
||||
* **สิ่งที่ต้องทดสอบ:** การเรียก sp\get\next\document\number [cite: 2.9.3] และการทำงานของ Views (เช่น v_user_tasks)
|
||||
* **E2E (End-to-End) Tests:**
|
||||
* **เป้าหมาย:** ทดสอบ API Contract ว่า Response Body Shape ตรงตามเอกสาร Swagger เพื่อรับประกันทีม Frontend
|
||||
- **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
- **เป้าหมาย:** ทดสอบ Logic ภายใน Service, Guard, หรือ Pipe โดยจำลอง (Mock) Dependencies ทั้งหมด
|
||||
- **สิ่งที่ต้องทดสอบ:** Business Logic (เช่น การเปลี่ยนสถานะ Workflow, การตรวจสอบ Deadline) [cite: 2.9.1], ตรรกะการตรวจสอบสิทธิ์ (Auth Guard) ทั้ง 4 ระดับ
|
||||
- **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
- **เป้าหมาย:** ทดสอบการทำงานร่วมกันของ Controller -> Service -> Repository (Database)
|
||||
- **เทคนิค:** ใช้ **Test Database แยกต่างหาก** (ห้ามใช้ Dev DB) และใช้ supertest เพื่อยิง HTTP Request จริงไปยัง App
|
||||
- **สิ่งที่ต้องทดสอบ:** การเรียก sp\get\next\document\number [cite: 2.9.3] และการทำงานของ Views (เช่น v_user_tasks)
|
||||
- **E2E (End-to-End) Tests:**
|
||||
- **เป้าหมาย:** ทดสอบ API Contract ว่า Response Body Shape ตรงตามเอกสาร Swagger เพื่อรับประกันทีม Frontend
|
||||
|
||||
### **🗄️ Backend State Management**
|
||||
|
||||
Backend (NestJS) ควรเป็น **Stateless** (ไม่เก็บสถานะ) "State" ทั้งหมดจะถูกจัดเก็บใน MariaDB
|
||||
|
||||
* **Request-Scoped State (สถานะภายใน Request เดียว):**
|
||||
* **ปัญหา:** จะส่งต่อข้อมูล (เช่น User ที่ล็อกอิน) ระหว่าง Guard และ Service ใน Request เดียวกันได้อย่างไร?
|
||||
* **วิธีแก้:** ใช้ **Request-Scoped Providers** ของ NestJS (เช่น AuthContextService) เพื่อเก็บข้อมูล User ปัจจุบันที่ได้จาก AuthGuard และให้ Service อื่น Inject ไปใช้
|
||||
* **Application-Scoped State (การ Caching):**
|
||||
* **ปัญหา:** ข้อมูล Master (เช่น roles, permissions, organizations) ถูกเรียกใช้บ่อย
|
||||
* **วิธีแก้:** ใช้ **Caching** (เช่น @nestjs/cache-manager) เพื่อ Caching ข้อมูลเหล่านี้ และลดภาระ Database
|
||||
- **Request-Scoped State (สถานะภายใน Request เดียว):**
|
||||
- **ปัญหา:** จะส่งต่อข้อมูล (เช่น User ที่ล็อกอิน) ระหว่าง Guard และ Service ใน Request เดียวกันได้อย่างไร?
|
||||
- **วิธีแก้:** ใช้ **Request-Scoped Providers** ของ NestJS (เช่น AuthContextService) เพื่อเก็บข้อมูล User ปัจจุบันที่ได้จาก AuthGuard และให้ Service อื่น Inject ไปใช้
|
||||
- **Application-Scoped State (การ Caching):**
|
||||
- **ปัญหา:** ข้อมูล Master (เช่น roles, permissions, organizations) ถูกเรียกใช้บ่อย
|
||||
- **วิธีแก้:** ใช้ **Caching** (เช่น @nestjs/cache-manager) เพื่อ Caching ข้อมูลเหล่านี้ และลดภาระ Database
|
||||
|
||||
### **การไหลของข้อมูล (Data Flow)**
|
||||
|
||||
@@ -238,76 +238,76 @@ Backend (NestJS) ควรเป็น **Stateless** (ไม่เก็บส
|
||||
|
||||
### **แนวทางการพัฒนาโค้ด (Code Implementation Guidelines)**
|
||||
|
||||
* ใช้ **early returns** เพื่อความชัดเจน
|
||||
* ใช้คลาสของ **TailwindCSS** ในการกำหนดสไตล์เสมอ
|
||||
* ควรใช้ class: syntax แบบมีเงื่อนไข (หรือ utility clsx) มากกว่าการใช้ ternary operators ใน class strings
|
||||
* ใช้ **const arrow functions** สำหรับ components และ handlers
|
||||
* Event handlers ให้ขึ้นต้นด้วย handle... (เช่น handleClick, handleSubmit)
|
||||
* รวมแอตทริบิวต์สำหรับการเข้าถึง (accessibility) ด้วย:
|
||||
- ใช้ **early returns** เพื่อความชัดเจน
|
||||
- ใช้คลาสของ **TailwindCSS** ในการกำหนดสไตล์เสมอ
|
||||
- ควรใช้ class: syntax แบบมีเงื่อนไข (หรือ utility clsx) มากกว่าการใช้ ternary operators ใน class strings
|
||||
- ใช้ **const arrow functions** สำหรับ components และ handlers
|
||||
- Event handlers ให้ขึ้นต้นด้วย handle... (เช่น handleClick, handleSubmit)
|
||||
- รวมแอตทริบิวต์สำหรับการเข้าถึง (accessibility) ด้วย:
|
||||
tabIndex="0", aria-label, onKeyDown, ฯลฯ
|
||||
* ตรวจสอบให้แน่ใจว่าโค้ดทั้งหมด **สมบูรณ์**, **ผ่านการทดสอบ**, และ **ไม่ซ้ำซ้อน (DRY)**
|
||||
* ต้อง import โมดูลที่จำเป็นต้องใช้อย่างชัดเจนเสมอ
|
||||
- ตรวจสอบให้แน่ใจว่าโค้ดทั้งหมด **สมบูรณ์**, **ผ่านการทดสอบ**, และ **ไม่ซ้ำซ้อน (DRY)**
|
||||
- ต้อง import โมดูลที่จำเป็นต้องใช้อย่างชัดเจนเสมอ
|
||||
|
||||
### **UI/UX ด้วย React**
|
||||
|
||||
* ใช้ **semantic HTML**
|
||||
* ใช้คลาสของ **Tailwind** ที่รองรับ responsive (sm:, md:, lg:)
|
||||
* รักษาลำดับชั้นของการมองเห็น (visual hierarchy) ด้วยการใช้ typography และ spacing
|
||||
* ใช้ **Shadcn** components (Button, Input, Card, ฯลฯ) เพื่อ UI ที่สอดคล้องกัน
|
||||
* ทำให้ components มีขนาดเล็กและมุ่งเน้นการทำงานเฉพาะอย่าง
|
||||
* ใช้ utility classes สำหรับการจัดสไตล์อย่างรวดเร็ว (spacing, colors, text, ฯลฯ)
|
||||
* ตรวจสอบให้แน่ใจว่าสอดคล้องกับ **ARIA** และใช้ semantic markup
|
||||
- ใช้ **semantic HTML**
|
||||
- ใช้คลาสของ **Tailwind** ที่รองรับ responsive (sm:, md:, lg:)
|
||||
- รักษาลำดับชั้นของการมองเห็น (visual hierarchy) ด้วยการใช้ typography และ spacing
|
||||
- ใช้ **Shadcn** components (Button, Input, Card, ฯลฯ) เพื่อ UI ที่สอดคล้องกัน
|
||||
- ทำให้ components มีขนาดเล็กและมุ่งเน้นการทำงานเฉพาะอย่าง
|
||||
- ใช้ utility classes สำหรับการจัดสไตล์อย่างรวดเร็ว (spacing, colors, text, ฯลฯ)
|
||||
- ตรวจสอบให้แน่ใจว่าสอดคล้องกับ **ARIA** และใช้ semantic markup
|
||||
|
||||
### **การตรวจสอบฟอร์มและข้อผิดพลาด (Form Validation & Errors)**
|
||||
|
||||
* ใช้ไลบรารีฝั่ง client เช่น zod และ react-hook-form
|
||||
* แสดงข้อผิดพลาดด้วย **alert components** หรือข้อความ inline
|
||||
* ต้องมี labels, placeholders, และข้อความ feedback
|
||||
- ใช้ไลบรารีฝั่ง client เช่น zod และ react-hook-form
|
||||
- แสดงข้อผิดพลาดด้วย **alert components** หรือข้อความ inline
|
||||
- ต้องมี labels, placeholders, และข้อความ feedback
|
||||
|
||||
### **🧪 Frontend Testing**
|
||||
|
||||
เราจะใช้ **React Testing Library (RTL)** สำหรับการทดสอบ Component และ **Playwright** สำหรับ E2E:
|
||||
|
||||
* **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
* **เครื่องมือ:** Vitest + RTL
|
||||
* **เป้าหมาย:** ทดสอบ Component ขนาดเล็ก (เช่น Buttons, Inputs) หรือ Utility functions
|
||||
* **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
* **เครื่องมือ:** RTL + **Mock Service Worker (MSW)**
|
||||
* **เป้าหมาย:** ทดสอบว่า Component หรือ Page ทำงานกับ API (ที่จำลองขึ้น) ได้ถูกต้อง
|
||||
* **เทคนิค:** ใช้ MSW เพื่อจำลอง NestJS API และทดสอบว่า Component แสดงผลข้อมูลจำลองได้ถูกต้องหรือไม่ (เช่น ทดสอบหน้า Dashboard [cite: 5.3] ที่ดึงข้อมูลจาก v_user_tasks)
|
||||
* **E2E (End-to-End) Tests:**
|
||||
* **เครื่องมือ:** **Playwright**
|
||||
* **เป้าหมาย:** ทดสอบ User Flow ทั้งระบบโดยอัตโนมัติ (เช่น ล็อกอิน -> สร้าง RFA -> ตรวจสอบ Workflow Visualization [cite: 5.6])
|
||||
- **Unit Tests (การทดสอบหน่วยย่อย):**
|
||||
- **เครื่องมือ:** Vitest + RTL
|
||||
- **เป้าหมาย:** ทดสอบ Component ขนาดเล็ก (เช่น Buttons, Inputs) หรือ Utility functions
|
||||
- **Integration Tests (การทดสอบการบูรณาการ):**
|
||||
- **เครื่องมือ:** RTL + **Mock Service Worker (MSW)**
|
||||
- **เป้าหมาย:** ทดสอบว่า Component หรือ Page ทำงานกับ API (ที่จำลองขึ้น) ได้ถูกต้อง
|
||||
- **เทคนิค:** ใช้ MSW เพื่อจำลอง NestJS API และทดสอบว่า Component แสดงผลข้อมูลจำลองได้ถูกต้องหรือไม่ (เช่น ทดสอบหน้า Dashboard [cite: 5.3] ที่ดึงข้อมูลจาก v_user_tasks)
|
||||
- **E2E (End-to-End) Tests:**
|
||||
- **เครื่องมือ:** **Playwright**
|
||||
- **เป้าหมาย:** ทดสอบ User Flow ทั้งระบบโดยอัตโนมัติ (เช่น ล็อกอิน -> สร้าง RFA -> ตรวจสอบ Workflow Visualization [cite: 5.6])
|
||||
|
||||
### **🗄️ Frontend State Management**
|
||||
|
||||
สำหรับ Next.js App Router เราจะแบ่ง State เป็น 4 ระดับ:
|
||||
|
||||
1. **Local UI State (สถานะ UI ชั่วคราว):**
|
||||
* **เครื่องมือ:** useState, useReducer
|
||||
* **ใช้เมื่อ:** จัดการสถานะเล็กๆ ที่จบใน Component เดียว (เช่น Modal เปิด/ปิด, ค่าใน Input)
|
||||
- **เครื่องมือ:** useState, useReducer
|
||||
- **ใช้เมื่อ:** จัดการสถานะเล็กๆ ที่จบใน Component เดียว (เช่น Modal เปิด/ปิด, ค่าใน Input)
|
||||
2. **Server State (สถานะข้อมูลจากเซิร์ฟเวอร์):**
|
||||
* **เครื่องมือ:** **React Query (TanStack Query)** หรือ SWR
|
||||
* **ใช้เมื่อ:** จัดการข้อมูลที่ดึงมาจาก NestJS API (เช่น รายการ correspondences, rfas, drawings)
|
||||
* **ทำไม:** React Query เป็น "Cache" ที่จัดการ Caching, Re-fetching, และ Invalidation ให้โดยอัตโนมัติ
|
||||
- **เครื่องมือ:** **React Query (TanStack Query)** หรือ SWR
|
||||
- **ใช้เมื่อ:** จัดการข้อมูลที่ดึงมาจาก NestJS API (เช่น รายการ correspondences, rfas, drawings)
|
||||
- **ทำไม:** React Query เป็น "Cache" ที่จัดการ Caching, Re-fetching, และ Invalidation ให้โดยอัตโนมัติ
|
||||
3. **Global Client State (สถานะส่วนกลางฝั่ง Client):**
|
||||
* **เครื่องมือ:** **Zustand** (แนะนำ) หรือ Context API
|
||||
* **ใช้เมื่อ:** จัดการข้อมูลที่ต้องใช้ร่วมกันทั่วทั้งแอป และ *ไม่ใช่* ข้อมูลจากเซิร์ฟเวอร์ (เช่น ข้อมูล User ที่ล็อกอิน, สิทธิ์ Permissions)
|
||||
- **เครื่องมือ:** **Zustand** (แนะนำ) หรือ Context API
|
||||
- **ใช้เมื่อ:** จัดการข้อมูลที่ต้องใช้ร่วมกันทั่วทั้งแอป และ _ไม่ใช่_ ข้อมูลจากเซิร์ฟเวอร์ (เช่น ข้อมูล User ที่ล็อกอิน, สิทธิ์ Permissions)
|
||||
4. **Form State (สถานะของฟอร์ม):**
|
||||
* **เครื่องมือ:** **React Hook Form** + **Zod**
|
||||
* **ใช้เมื่อ:** จัดการฟอร์มที่ซับซ้อน (เช่น ฟอร์มสร้าง RFA, ฟอร์ม Circulation [cite: 3.7])
|
||||
- **เครื่องมือ:** **React Hook Form** + **Zod**
|
||||
- **ใช้เมื่อ:** จัดการฟอร์มที่ซับซ้อน (เช่น ฟอร์มสร้าง RFA, ฟอร์ม Circulation [cite: 3.7])
|
||||
|
||||
# **🔗 แนวทางการบูรณาการ Full Stack (Full Stack Integration Guidelines)**
|
||||
|
||||
| Aspect (แง่มุม) | Backend (NestJS) | Frontend (NextJS) | UI Layer (Tailwind/Shadcn) |
|
||||
| :---- | :---- | :---- | :---- |
|
||||
| API | REST / GraphQL Controllers | API hooks ผ่าน fetch/axios/SWR | Components ที่รับข้อมูล |
|
||||
| Validation (การตรวจสอบ) | class-validator DTOs | zod / react-hook-form | สถานะของฟอร์ม/input ใน Shadcn |
|
||||
| Auth (การยืนยันตัวตน) | Guards, JWT | NextAuth / cookies | สถานะ UI ของ Auth (loading, signed in) |
|
||||
| Errors (ข้อผิดพลาด) | Global filters | Toasts / modals | Alerts / ข้อความ feedback |
|
||||
| Testing (การทดสอบ) | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles (สไตล์) | Scoped modules (ถ้าจำเป็น) | Tailwind / Shadcn | Tailwind utilities |
|
||||
| Accessibility (การเข้าถึง) | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
| Aspect (แง่มุม) | Backend (NestJS) | Frontend (NextJS) | UI Layer (Tailwind/Shadcn) |
|
||||
| :------------------------- | :------------------------- | :----------------------------- | :------------------------------------- |
|
||||
| API | REST / GraphQL Controllers | API hooks ผ่าน fetch/axios/SWR | Components ที่รับข้อมูล |
|
||||
| Validation (การตรวจสอบ) | class-validator DTOs | zod / react-hook-form | สถานะของฟอร์ม/input ใน Shadcn |
|
||||
| Auth (การยืนยันตัวตน) | Guards, JWT | NextAuth / cookies | สถานะ UI ของ Auth (loading, signed in) |
|
||||
| Errors (ข้อผิดพลาด) | Global filters | Toasts / modals | Alerts / ข้อความ feedback |
|
||||
| Testing (การทดสอบ) | Jest (unit/e2e) | Vitest / Playwright | Visual regression |
|
||||
| Styles (สไตล์) | Scoped modules (ถ้าจำเป็น) | Tailwind / Shadcn | Tailwind utilities |
|
||||
| Accessibility (การเข้าถึง) | Guards + filters | ARIA attributes | Semantic HTML |
|
||||
|
||||
## **🗂️ ข้อตกลงเฉพาะสำหรับ DMS (LCBP3-DMS)**
|
||||
|
||||
@@ -320,25 +320,25 @@ Backend (NestJS) ควรเป็น **Stateless** (ไม่เก็บส
|
||||
@RequirePermission('rfas.respond') // ต้องตรงกับ 'permission\code'
|
||||
@Put(':id')
|
||||
updateRFA(@Param('id') id: string) {
|
||||
return this.rfaService.update(id);
|
||||
return this.rfaService.update(id);
|
||||
}
|
||||
|
||||
### **Roles (บทบาท)**
|
||||
|
||||
* **Superadmin**: ไม่มีข้อจำกัดใดๆ [cite: 4.3]
|
||||
* **Admin**: มีสิทธิ์เต็มที่ในองค์กร [cite: 4.3]
|
||||
* **Document Control**: เพิ่ม/แก้ไข/ลบ เอกสารในองค์กร [cite: 4.3]
|
||||
* **Editor**: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนด [cite: 4.3]
|
||||
* **Viewer**: สามารถดู เอกสาร [cite: 4.3]
|
||||
- **Superadmin**: ไม่มีข้อจำกัดใดๆ [cite: 4.3]
|
||||
- **Admin**: มีสิทธิ์เต็มที่ในองค์กร [cite: 4.3]
|
||||
- **Document Control**: เพิ่ม/แก้ไข/ลบ เอกสารในองค์กร [cite: 4.3]
|
||||
- **Editor**: สามารถ เพิ่ม/แก้ไข เอกสารที่กำหนด [cite: 4.3]
|
||||
- **Viewer**: สามารถดู เอกสาร [cite: 4.3]
|
||||
|
||||
### **ตัวอย่าง Permissions (จากตาราง permissions)**
|
||||
|
||||
* rfas.view, rfas.create, rfas.respond, rfas.delete
|
||||
* drawings.view, drawings.upload, drawings.delete
|
||||
* corr.view, corr.manage
|
||||
* transmittals.manage
|
||||
* cirs.manage
|
||||
* project\parties.manage
|
||||
- rfas.view, rfas.create, rfas.respond, rfas.delete
|
||||
- drawings.view, drawings.upload, drawings.delete
|
||||
- corr.view, corr.manage
|
||||
- transmittals.manage
|
||||
- cirs.manage
|
||||
- project\parties.manage
|
||||
|
||||
การจับคู่ระหว่าง roles และ permissions **เริ่มต้น** จะถูก seed ผ่านสคริปต์ (ดังที่เห็นในไฟล์ SQL)**อย่างไรก็ตาม AuthModule/UserModule ต้องมี API สำหรับ Admin เพื่อสร้าง Role ใหม่และกำหนดสิทธิ์ (Permissions) เพิ่มเติมได้ในภายหลัง** [cite: 4.3]
|
||||
|
||||
@@ -346,33 +346,33 @@ updateRFA(@Param('id') id: string) {
|
||||
|
||||
บันทึกการดำเนินการ CRUD และการจับคู่ทั้งหมดลงในตาราง audit_logs
|
||||
|
||||
| Field (ฟิลด์) | Type (จาก SQL) | Description (คำอธิบาย) |
|
||||
| :---- | :---- | :---- |
|
||||
| audit_id | BIGINT | Primary Key |
|
||||
| user_id | INT | ผู้ใช้ที่ดำเนินการ (FK -> users) |
|
||||
| action | VARCHAR(100) | rfa.create, correspondence.update, login.success |
|
||||
| entity_type | VARCHAR(50) | ชื่อตาราง/โมดูล เช่น 'rfa', 'correspondence' |
|
||||
| entity_id | VARCHAR(50) | Primary ID ของระเบียนที่ได้รับผลกระทบ |
|
||||
| details_json | JSON | ข้อมูลบริบท (เช่น ฟิลด์ที่มีการเปลี่ยนแปลง) |
|
||||
| ip_address | VARCHAR(45) | IP address ของผู้ดำเนินการ |
|
||||
| user_agent | VARCHAR(255) | User Agent ของผู้ดำเนินการ |
|
||||
| created_at | TIMESTAMP | Timestamp (UTC) |
|
||||
| Field (ฟิลด์) | Type (จาก SQL) | Description (คำอธิบาย) |
|
||||
| :------------ | :------------- | :----------------------------------------------- |
|
||||
| audit_id | BIGINT | Primary Key |
|
||||
| user_id | INT | ผู้ใช้ที่ดำเนินการ (FK -> users) |
|
||||
| action | VARCHAR(100) | rfa.create, correspondence.update, login.success |
|
||||
| entity_type | VARCHAR(50) | ชื่อตาราง/โมดูล เช่น 'rfa', 'correspondence' |
|
||||
| entity_id | VARCHAR(50) | Primary ID ของระเบียนที่ได้รับผลกระทบ |
|
||||
| details_json | JSON | ข้อมูลบริบท (เช่น ฟิลด์ที่มีการเปลี่ยนแปลง) |
|
||||
| ip_address | VARCHAR(45) | IP address ของผู้ดำเนินการ |
|
||||
| user_agent | VARCHAR(255) | User Agent ของผู้ดำเนินการ |
|
||||
| created_at | TIMESTAMP | Timestamp (UTC) |
|
||||
|
||||
## **📂 การจัดการไฟล์ (File Handling) (ปรับปรุงใหม่)**
|
||||
|
||||
### **มาตรฐานการอัปโหลดไฟล์ (File Upload Standard)**
|
||||
|
||||
* **ตรรกะใหม่:** การอัปโหลดไฟล์ทั้งหมดจะถูกจัดการโดย FileStorageService และบันทึกข้อมูลไฟล์ลงในตาราง attachments (ตารางกลาง)
|
||||
* ไฟล์จะถูกเชื่อมโยงไปยัง Entity ที่ถูกต้องผ่าน **ตารางเชื่อม (Junction Tables)** เท่านั้น:
|
||||
* correspondence_attachments (เชื่อม Correspondence กับ Attachments)
|
||||
* circulation_attachments (เชื่อม Circulation กับ Attachments)
|
||||
* shop_drawing_revision_attachments (เชื่อม Shop Drawing Revision กับ Attachments)
|
||||
* contract_drawing_attachments (เชื่อม Contract Drawing กับ Attachments)
|
||||
* เส้นทางจัดเก็บไฟล์ (Upload path): อ้างอิงจาก Requirement 2.1 คือ /share/dms-data [cite: 2.1] โดย FileStorageService จะสร้างโฟลเดอร์ย่อยแบบรวมศูนย์ (เช่น /share/dms-data/uploads/{YYYY}/{MM}/[stored\filename])
|
||||
* ประเภทไฟล์ที่อนุญาต: pdf, dwg, docx, xlsx, zip
|
||||
* ขนาดสูงสุด: **50 MB**
|
||||
* จัดเก็บนอก webroot
|
||||
* ให้บริการไฟล์ผ่าน endpoint ที่ปลอดภัย /files/:attachment_id/download
|
||||
- **ตรรกะใหม่:** การอัปโหลดไฟล์ทั้งหมดจะถูกจัดการโดย FileStorageService และบันทึกข้อมูลไฟล์ลงในตาราง attachments (ตารางกลาง)
|
||||
- ไฟล์จะถูกเชื่อมโยงไปยัง Entity ที่ถูกต้องผ่าน **ตารางเชื่อม (Junction Tables)** เท่านั้น:
|
||||
- correspondence_attachments (เชื่อม Correspondence กับ Attachments)
|
||||
- circulation_attachments (เชื่อม Circulation กับ Attachments)
|
||||
- shop_drawing_revision_attachments (เชื่อม Shop Drawing Revision กับ Attachments)
|
||||
- contract_drawing_attachments (เชื่อม Contract Drawing กับ Attachments)
|
||||
- เส้นทางจัดเก็บไฟล์ (Upload path): อ้างอิงจาก Requirement 2.1 คือ /share/dms-data [cite: 2.1] โดย FileStorageService จะสร้างโฟลเดอร์ย่อยแบบรวมศูนย์ (เช่น /share/dms-data/uploads/{YYYY}/{MM}/[stored\filename])
|
||||
- ประเภทไฟล์ที่อนุญาต: pdf, dwg, docx, xlsx, zip
|
||||
- ขนาดสูงสุด: **50 MB**
|
||||
- จัดเก็บนอก webroot
|
||||
- ให้บริการไฟล์ผ่าน endpoint ที่ปลอดภัย /files/:attachment_id/download
|
||||
|
||||
### **การควบคุมการเข้าถึง (Access Control)**
|
||||
|
||||
@@ -384,15 +384,15 @@ updateRFA(@Param('id') id: string) {
|
||||
|
||||
## **🔟 การจัดการเลขที่เอกสาร (Document Numbering) [cite: 3.10]**
|
||||
|
||||
* **เป้าหมาย:** สร้างเลขที่เอกสาร (เช่น correspondence\number) โดยอัตโนมัติ ตามรูปแบบที่กำหนด
|
||||
* **ตรรกะการนับ:** การนับ Running number (SEQ) จะนับแยกตาม Key: **Project + Originator Organization + Document Type + Year**
|
||||
* **ตาราง SQL:**
|
||||
* document_number_formats: Admin ใช้กำหนด "รูปแบบ" (Template) ของเลขที่ (เช่น {ORG\CODE}-{TYPE\CODE}-{YEAR\SHORT}-{SEQ:4}) โดยกำหนดตาม **Project** และ **Document Type** [cite: 4.5]
|
||||
* document_number_counters: ระบบใช้เก็บ "ตัวนับ" ล่าสุดของ Key (Project+Org+Type+Year)
|
||||
* **การทำงาน (Backend):**
|
||||
* DocumentNumberingModule จะให้บริการ DocumentNumberingService
|
||||
* เมื่อ CorrespondenceModule ต้องการสร้างเอกสารใหม่, มันจะเรียก documentNumberingService.generateNextNumber(...)
|
||||
* Service นี้จะเรียกใช้ Stored Procedure **sp_get_next_document_number** [cite: 2.9.3] ซึ่ง Procedure นี้จะจัดการ Database Transaction และ Row Lock (FOR UPDATE) ภายใน DB เพื่อรับประกันการป้องกัน Race Condition
|
||||
- **เป้าหมาย:** สร้างเลขที่เอกสาร (เช่น correspondence\number) โดยอัตโนมัติ ตามรูปแบบที่กำหนด
|
||||
- **ตรรกะการนับ:** การนับ Running number (SEQ) จะนับแยกตาม Key: **Project + Originator Organization + Document Type + Year**
|
||||
- **ตาราง SQL:**
|
||||
- document_number_formats: Admin ใช้กำหนด "รูปแบบ" (Template) ของเลขที่ (เช่น {ORG\CODE}-{TYPE\CODE}-{YEAR\SHORT}-{SEQ:4}) โดยกำหนดตาม **Project** และ **Document Type** [cite: 4.5]
|
||||
- document_number_counters: ระบบใช้เก็บ "ตัวนับ" ล่าสุดของ Key (Project+Org+Type+Year)
|
||||
- **การทำงาน (Backend):**
|
||||
- DocumentNumberingModule จะให้บริการ DocumentNumberingService
|
||||
- เมื่อ CorrespondenceModule ต้องการสร้างเอกสารใหม่, มันจะเรียก documentNumberingService.generateNextNumber(...)
|
||||
- Service นี้จะเรียกใช้ Stored Procedure **sp_get_next_document_number** [cite: 2.9.3] ซึ่ง Procedure นี้จะจัดการ Database Transaction และ Row Lock (FOR UPDATE) ภายใน DB เพื่อรับประกันการป้องกัน Race Condition
|
||||
|
||||
## **📊 การรายงานและการส่งออก (Reporting & Exports)**
|
||||
|
||||
@@ -400,81 +400,81 @@ updateRFA(@Param('id') id: string) {
|
||||
|
||||
การรายงานควรสร้างขึ้นจาก Views ที่กำหนดไว้ล่วงหน้าในฐานข้อมูลเป็นหลัก:
|
||||
|
||||
* v_current_correspondences: สำหรับ revision ปัจจุบันทั้งหมดของเอกสารที่ไม่ใช่ RFA
|
||||
* v_current_rfas: สำหรับ revision ปัจจุบันทั้งหมดของ RFA และข้อมูล master
|
||||
* v_contract_parties_all: สำหรับการตรวจสอบความสัมพันธ์ของ project/contract/organization
|
||||
* v_user_tasks: สำหรับ Dashboard "งานของฉัน"
|
||||
* v_audit_log_details: สำหรับ Activity Feed
|
||||
- v_current_correspondences: สำหรับ revision ปัจจุบันทั้งหมดของเอกสารที่ไม่ใช่ RFA
|
||||
- v_current_rfas: สำหรับ revision ปัจจุบันทั้งหมดของ RFA และข้อมูล master
|
||||
- v_contract_parties_all: สำหรับการตรวจสอบความสัมพันธ์ของ project/contract/organization
|
||||
- v_user_tasks: สำหรับ Dashboard "งานของฉัน"
|
||||
- v_audit_log_details: สำหรับ Activity Feed
|
||||
|
||||
Views เหล่านี้ทำหน้าที่เป็นแหล่งข้อมูลหลักสำหรับการรายงานฝั่งเซิร์ฟเวอร์และการส่งออกข้อมูล
|
||||
|
||||
### **กฎการส่งออก (Export Rules)**
|
||||
|
||||
* Export formats: CSV, Excel, PDF.
|
||||
* จัดเตรียมมุมมองสำหรับพิมพ์ (Print view).
|
||||
* รวมลิงก์ไปยังต้นทาง (เช่น /rfas/:id).
|
||||
- Export formats: CSV, Excel, PDF.
|
||||
- จัดเตรียมมุมมองสำหรับพิมพ์ (Print view).
|
||||
- รวมลิงก์ไปยังต้นทาง (เช่น /rfas/:id).
|
||||
|
||||
## **🧮 ฟรอนต์เอนด์: รูปแบบ DataTable และฟอร์ม (Frontend: DataTable & Form Patterns)**
|
||||
|
||||
### **DataTable (Server‑Side)**
|
||||
|
||||
* Endpoint: /api/{module}?page=1\&pageSize=20\&sort=...\&filter=...
|
||||
* ต้องรองรับ: การแบ่งหน้า (pagination), การเรียงลำดับ (sorting), การค้นหา (search), การกรอง (filters)
|
||||
* แสดง revision ล่าสุดแบบ inline เสมอ (สำหรับ RFA/Drawing)
|
||||
- Endpoint: /api/{module}?page=1\&pageSize=20\&sort=...\&filter=...
|
||||
- ต้องรองรับ: การแบ่งหน้า (pagination), การเรียงลำดับ (sorting), การค้นหา (search), การกรอง (filters)
|
||||
- แสดง revision ล่าสุดแบบ inline เสมอ (สำหรับ RFA/Drawing)
|
||||
|
||||
### **มาตรฐานฟอร์ม (Form Standards)**
|
||||
|
||||
* ต้องมีการใช้งาน Dropdowns แบบขึ้นต่อกัน (Dependent dropdowns) (ตามที่สคีมารองรับ):
|
||||
* Project → Contract Drawing Volumes
|
||||
* Contract Drawing Category → Sub-Category
|
||||
* RFA (ประเภท Shop Drawing) → Shop Drawing Revisions ที่เชื่อมโยงได้
|
||||
* **(ใหม่)** การอัปโหลดไฟล์: ต้องรองรับ **Multi-file upload (Drag-and-Drop)** [cite: 5.7]
|
||||
* **(ใหม่)** UI ต้องอนุญาตให้ผู้ใช้กำหนดว่าไฟล์ใดเป็น **"เอกสารหลัก"** หรือ "เอกสารแนบประกอบ" [cite: 5.7]
|
||||
* ส่ง (Submit) ผ่าน API พร้อม feedback แบบ toast
|
||||
- ต้องมีการใช้งาน Dropdowns แบบขึ้นต่อกัน (Dependent dropdowns) (ตามที่สคีมารองรับ):
|
||||
- Project → Contract Drawing Volumes
|
||||
- Contract Drawing Category → Sub-Category
|
||||
- RFA (ประเภท Shop Drawing) → Shop Drawing Revisions ที่เชื่อมโยงได้
|
||||
- **(ใหม่)** การอัปโหลดไฟล์: ต้องรองรับ **Multi-file upload (Drag-and-Drop)** [cite: 5.7]
|
||||
- **(ใหม่)** UI ต้องอนุญาตให้ผู้ใช้กำหนดว่าไฟล์ใดเป็น **"เอกสารหลัก"** หรือ "เอกสารแนบประกอบ" [cite: 5.7]
|
||||
- ส่ง (Submit) ผ่าน API พร้อม feedback แบบ toast
|
||||
|
||||
### **ข้อกำหนด Component เฉพาะ (Specific UI Requirements)**
|
||||
|
||||
* **Dashboard \- My Tasks:** ต้องพัฒนา Component ตาราง "งานของฉัน" (My Tasks)ซึ่งดึงข้อมูลงานที่ผู้ใช้ล็อกอินอยู่ต้องรับผิดชอบ (Main/Action) จาก v\user\tasks [cite: 5.3]
|
||||
* **Workflow Visualization:** ต้องพัฒนา Component สำหรับแสดงผล Workflow (โดยเฉพาะ RFA)ที่แสดงขั้นตอนทั้งหมดเป็นลำดับ โดยขั้นตอนปัจจุบัน (active) เท่านั้นที่ดำเนินการได้ และขั้นตอนอื่นเป็น disabled [cite: 5.6] ต้องมีตรรกะสำหรับ Admin ในการ override หรือย้อนกลับขั้นตอนได้ [cite: 5.6]
|
||||
* ** Admin Panel:** ต้องมีหน้า UI สำหรับ Superadmin/Admin เพื่อจัดการข้อมูลหลัก (Master Data [cite: 4.5]), การเริ่มต้นใช้งาน (Onboarding [cite: 4.6]), และ **รูปแบบเลขที่เอกสาร (Numbering Formats [cite: 3.10])**
|
||||
- **Dashboard \- My Tasks:** ต้องพัฒนา Component ตาราง "งานของฉัน" (My Tasks)ซึ่งดึงข้อมูลงานที่ผู้ใช้ล็อกอินอยู่ต้องรับผิดชอบ (Main/Action) จาก v\user\tasks [cite: 5.3]
|
||||
- **Workflow Visualization:** ต้องพัฒนา Component สำหรับแสดงผล Workflow (โดยเฉพาะ RFA)ที่แสดงขั้นตอนทั้งหมดเป็นลำดับ โดยขั้นตอนปัจจุบัน (active) เท่านั้นที่ดำเนินการได้ และขั้นตอนอื่นเป็น disabled [cite: 5.6] ต้องมีตรรกะสำหรับ Admin ในการ override หรือย้อนกลับขั้นตอนได้ [cite: 5.6]
|
||||
- ** Admin Panel:** ต้องมีหน้า UI สำหรับ Superadmin/Admin เพื่อจัดการข้อมูลหลัก (Master Data [cite: 4.5]), การเริ่มต้นใช้งาน (Onboarding [cite: 4.6]), และ **รูปแบบเลขที่เอกสาร (Numbering Formats [cite: 3.10])**
|
||||
|
||||
## **🧭 แดชบอร์ดและฟีดกิจกรรม (Dashboard & Activity Feed)**
|
||||
|
||||
### **การ์ดบนแดชบอร์ด (Dashboard Cards)**
|
||||
|
||||
* แสดง Correspondences, RFAs, Circulations, Shop Drawing Revision ล่าสุด
|
||||
* รวมสรุป KPI (เช่น "RFAs ที่รอการอนุมัติ", "Shop Drawing ที่รอการอนุมัติ") [cite: 5.3]
|
||||
* รวมลิงก์ด่วนไปยังโมดูลต่างๆ
|
||||
- แสดง Correspondences, RFAs, Circulations, Shop Drawing Revision ล่าสุด
|
||||
- รวมสรุป KPI (เช่น "RFAs ที่รอการอนุมัติ", "Shop Drawing ที่รอการอนุมัติ") [cite: 5.3]
|
||||
- รวมลิงก์ด่วนไปยังโมดูลต่างๆ
|
||||
|
||||
### **ฟีดกิจกรรม (Activity Feed)**
|
||||
|
||||
* แสดงรายการ v\audit\log\details ล่าสุด (10 รายการ) ที่เกี่ยวข้องกับผู้ใช้
|
||||
- แสดงรายการ v\audit\log\details ล่าสุด (10 รายการ) ที่เกี่ยวข้องกับผู้ใช้
|
||||
|
||||
// ตัวอย่าง API response
|
||||
[
|
||||
{ user: 'editor01', action: 'Updated RFA (LCBP3-RFA-001)', time: '2025-11-04T09:30Z' }
|
||||
{ user: 'editor01', action: 'Updated RFA (LCBP3-RFA-001)', time: '2025-11-04T09:30Z' }
|
||||
]
|
||||
|
||||
## **🛡️ ข้อกำหนดที่ไม่ใช่ฟังก์ชันการทำงาน (Non-Functional Requirements)**
|
||||
|
||||
ส่วนนี้สรุปข้อกำหนด Non-Functional จาก requirements.md เพื่อให้ทีมพัฒนาทราบ
|
||||
|
||||
* **Audit Log [cite: 6.1]:** ทุกการกระทำที่สำคัญ (C/U/D) ต้องถูกบันทึกใน audit_logs
|
||||
* **Performance [cite: 6.4]:** ต้องใช้ Caching สำหรับข้อมูลที่เรียกบ่อย และใช้ Pagination
|
||||
* **Security [cite: 6.5]:** ต้องมี Rate Limiting และจัดการ Secret ผ่าน docker-compose.yml (ไม่ใช่ .env)
|
||||
* **(ใหม่) Backup & Recovery [cite: 6.6]:** ต้องมีแผนสำรองข้อมูลทั้ง Database (MariaDB) และ File Storage (/share/dms-data) อย่างน้อยวันละ 1 ครั้ง
|
||||
* **(ใหม่) Notification Strategy [cite: 6.7]:** ระบบแจ้งเตือน (Email/Line) ต้องถูก Trigger เมื่อมีเอกสารใหม่ส่งถึง, มีการมอบหมายงานใหม่ (Circulation), หรือ (ทางเลือก) เมื่องานเสร็จ/ใกล้ถึงกำหนด
|
||||
- **Audit Log [cite: 6.1]:** ทุกการกระทำที่สำคัญ (C/U/D) ต้องถูกบันทึกใน audit_logs
|
||||
- **Performance [cite: 6.4]:** ต้องใช้ Caching สำหรับข้อมูลที่เรียกบ่อย และใช้ Pagination
|
||||
- **Security [cite: 6.5]:** ต้องมี Rate Limiting และจัดการ Secret ผ่าน docker-compose.yml (ไม่ใช่ .env)
|
||||
- **(ใหม่) Backup & Recovery [cite: 6.6]:** ต้องมีแผนสำรองข้อมูลทั้ง Database (MariaDB) และ File Storage (/share/dms-data) อย่างน้อยวันละ 1 ครั้ง
|
||||
- **(ใหม่) Notification Strategy [cite: 6.7]:** ระบบแจ้งเตือน (Email/Line) ต้องถูก Trigger เมื่อมีเอกสารใหม่ส่งถึง, มีการมอบหมายงานใหม่ (Circulation), หรือ (ทางเลือก) เมื่องานเสร็จ/ใกล้ถึงกำหนด
|
||||
|
||||
## **✅ มาตรฐานที่นำไปใช้แล้ว (จาก SQL v1.1.0) (Implemented Standards (from SQL v1.1.0))**
|
||||
|
||||
ส่วนนี้ยืนยันว่าแนวทางปฏิบัติที่ดีที่สุดต่อไปนี้เป็นส่วนหนึ่งของการออกแบบฐานข้อมูลอยู่แล้ว และควรถูกนำไปใช้ประโยชน์ ไม่ใช่สร้างขึ้นใหม่
|
||||
|
||||
* ✅ **Soft Delete:** นำไปใช้แล้วผ่านคอลัมน์ deleted_at ในตารางสำคัญ (เช่น correspondences, rfas, project_parties) ตรรกะการดึงข้อมูลต้องกรอง deleted_at IS NULL
|
||||
* ✅ **Database Indexes:** สคีมาได้มีการทำ index ไว้อย่างหนักหน่วงบน foreign keys และคอลัมน์ที่ใช้ค้นหาบ่อย (เช่น idx_rr_rfa, idx_cor_project, idx_cr_is_current) เพื่อประสิทธิภาพ
|
||||
* ✅ **โครงสร้าง RBAC:** มีระบบ users, roles, permissions, user_roles, และ user_project_roles ที่ครอบคลุมอยู่แล้ว
|
||||
* ✅ **Data Seeding:** ข้อมูล Master (roles, permissions, organization_roles, initial users, project parties) ถูกรวมอยู่ในสคริปต์สคีมาแล้ว
|
||||
- ✅ **Soft Delete:** นำไปใช้แล้วผ่านคอลัมน์ deleted_at ในตารางสำคัญ (เช่น correspondences, rfas, project_parties) ตรรกะการดึงข้อมูลต้องกรอง deleted_at IS NULL
|
||||
- ✅ **Database Indexes:** สคีมาได้มีการทำ index ไว้อย่างหนักหน่วงบน foreign keys และคอลัมน์ที่ใช้ค้นหาบ่อย (เช่น idx_rr_rfa, idx_cor_project, idx_cr_is_current) เพื่อประสิทธิภาพ
|
||||
- ✅ **โครงสร้าง RBAC:** มีระบบ users, roles, permissions, user_roles, และ user_project_roles ที่ครอบคลุมอยู่แล้ว
|
||||
- ✅ **Data Seeding:** ข้อมูล Master (roles, permissions, organization_roles, initial users, project parties) ถูกรวมอยู่ในสคริปต์สคีมาแล้ว
|
||||
|
||||
## **🧩 การปรับปรุงที่แนะนำ (สำหรับอนาคต) (Recommended Enhancements (Future))**
|
||||
|
||||
* ✅ สร้าง Background job (โดยใช้ **n8n** เพื่อเชื่อมต่อกับ **Line** [cite: 2.7] และ/หรือใช้สำหรับการแจ้งเตือน RFA ที่ใกล้ถึงกำหนด due_date [cite: 6.7])
|
||||
* ✅ เพิ่ม job ล้างข้อมูลเป็นระยะสำหรับ attachments ที่ไม่ถูกเชื่อมโยงกับ Entity ใดๆ เลย (ไฟล์กำพร้า)
|
||||
- ✅ สร้าง Background job (โดยใช้ **n8n** เพื่อเชื่อมต่อกับ **Line** [cite: 2.7] และ/หรือใช้สำหรับการแจ้งเตือน RFA ที่ใกล้ถึงกำหนด due_date [cite: 6.7])
|
||||
- ✅ เพิ่ม job ล้างข้อมูลเป็นระยะสำหรับ attachments ที่ไม่ถูกเชื่อมโยงกับ Entity ใดๆ เลย (ไฟล์กำพร้า)
|
||||
|
||||
@@ -154,7 +154,6 @@
|
||||
|
||||
- **4.1. ภาพรวม:** ผู้ใช้และองค์กรสามารถดูและแก้ไขเอกสารได้ตามสิทธิ์ที่ได้รับ โดยระบบสิทธิ์จะเป็นแบบ Role-Based Access Control (RBAC)
|
||||
- **4.2. ลำดับชั้นของสิทธิ์ (Permission Hierarchy)**
|
||||
|
||||
- Global: สิทธิ์สูงสุดของระบบ
|
||||
- Organization: สิทธิ์ภายในองค์กร เป็นสิทธิ์พื้นฐานของผู้ใช้
|
||||
- Project: สิทธิ์เฉพาะในโครงการ จะถูกพิจารณาเมื่อผู้ใช้อยู่ในโครงการนั้น
|
||||
@@ -177,18 +176,14 @@
|
||||
| **Contract Admin** | Contract | ผู้ดูแลสัญญา | จัดการสมาชิกในสัญญา, สร้าง/จัดการข้อมูลหลักเฉพาะสัญญา (ถ้ามี), อนุมัติเอกสารในสัญญา |
|
||||
|
||||
- **4.4. กระบวนการเริ่มต้นใช้งาน (Onboarding Workflow) ที่สมบูรณ์**
|
||||
|
||||
- 4.1. **สร้างองค์กร (Organization)**
|
||||
|
||||
- **Superadmin** สร้างองค์กรใหม่ (เช่น บริษัท A)
|
||||
- **Superadmin** แต่งตั้งผู้ใช้อย่างน้อย 1 คนให้เป็น **Org Admin** หรือ **Document Control** ของบริษัท A
|
||||
|
||||
- 4.2. **เพิ่มผู้ใช้ในองค์กร**
|
||||
|
||||
- **Org Admin** ของบริษัท A เพิ่มผู้ใช้อื่นๆ (Editor, Viewer) เข้ามาในองค์กรของตน
|
||||
|
||||
- 4.3. **มอบหมายผู้ใช้ให้กับโครงการ (Project)**
|
||||
|
||||
- **Project Manager** ของโครงการ X (ซึ่งอาจมาจากบริษัท A หรือบริษัทอื่น) ทำการ "เชิญ" หรือ "มอบหมาย" ผู้ใช้จากองค์กรต่างๆ ที่เกี่ยวข้องเข้ามาในโครงการ X
|
||||
- ในขั้นตอนนี้ **Project Manager** จะกำหนด **บทบาทระดับโครงการ** (เช่น Project Member, หรืออาจไม่มีบทบาทพิเศษ ให้ใช้สิทธิ์จากระดับองค์กรไปก่อน)
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 📋 **แผนการพัฒนา Backend (NestJS) - LCBP3-DMS v1.4.1 (ปรับปรุงโดย deepseek)**
|
||||
|
||||
**ปรับปรุงตาม Requirements v1.4.0 ที่อัปเดตแล้ว*
|
||||
**Routing และ รูปแบบ JSON details**
|
||||
**ปรับปรุงตาม Requirements v1.4.0 ที่อัปเดตแล้ว\*
|
||||
**Routing และ รูปแบบ JSON details\*\*
|
||||
|
||||
---
|
||||
|
||||
@@ -67,164 +67,164 @@ src/
|
||||
|
||||
### **Dependency Diagram (ภาพรวม)**
|
||||
|
||||
```mermaid
|
||||
%% Phase 0: Infrastructure
|
||||
subgraph Phase 0 [Phase 0: Infrastructure Setup]
|
||||
T0_1[T0.1: Setup QNAP Container Station]
|
||||
T0_2[T0.2: Initialize NestJS Project]
|
||||
T0_3[T0.3: Setup Database Connection]
|
||||
T0_4[T0.4: Setup Git Repository]
|
||||
end
|
||||
```mermaid
|
||||
%% Phase 0: Infrastructure
|
||||
subgraph Phase 0 [Phase 0: Infrastructure Setup]
|
||||
T0_1[T0.1: Setup QNAP Container Station]
|
||||
T0_2[T0.2: Initialize NestJS Project]
|
||||
T0_3[T0.3: Setup Database Connection]
|
||||
T0_4[T0.4: Setup Git Repository]
|
||||
end
|
||||
|
||||
%% Phase 1: Core Foundation
|
||||
subgraph Phase 1 [Phase 1: Core Foundation & Security]
|
||||
T1_1[T1.1: CommonModule - Base Infrastructure]
|
||||
T1_2[T1.2: AuthModule - JWT Authentication]
|
||||
T1_3[T1.3: UserModule - User Management]
|
||||
T1_4[T1.4: RBAC Guard - 4-Level Authorization]
|
||||
T1_5[T1.5: ProjectModule - Base Structures]
|
||||
end
|
||||
%% Phase 1: Core Foundation
|
||||
subgraph Phase 1 [Phase 1: Core Foundation & Security]
|
||||
T1_1[T1.1: CommonModule - Base Infrastructure]
|
||||
T1_2[T1.2: AuthModule - JWT Authentication]
|
||||
T1_3[T1.3: UserModule - User Management]
|
||||
T1_4[T1.4: RBAC Guard - 4-Level Authorization]
|
||||
T1_5[T1.5: ProjectModule - Base Structures]
|
||||
end
|
||||
|
||||
%% Phase 2: Security & File Management
|
||||
subgraph Phase 2 [Phase 2: Security & File Management]
|
||||
T2_1[T2.1: MasterModule - Master Data Management]
|
||||
T2_2[T2.2: FileStorageService - Secure File Management]
|
||||
T2_3[T2.3: DocumentNumberingModule - App-Level Locking]
|
||||
T2_4[T2.4: SecurityModule - Enhanced Security]
|
||||
T2_5[T2.5: JSON Details & Schema Management]
|
||||
end
|
||||
%% Phase 2: Security & File Management
|
||||
subgraph Phase 2 [Phase 2: Security & File Management]
|
||||
T2_1[T2.1: MasterModule - Master Data Management]
|
||||
T2_2[T2.2: FileStorageService - Secure File Management]
|
||||
T2_3[T2.3: DocumentNumberingModule - App-Level Locking]
|
||||
T2_4[T2.4: SecurityModule - Enhanced Security]
|
||||
T2_5[T2.5: JSON Details & Schema Management]
|
||||
end
|
||||
|
||||
%% Phase 3: Correspondence & RFA Core
|
||||
subgraph Phase 3 [Phase 3: Correspondence & RFA Core]
|
||||
T3_1[T3.1: CorrespondenceModule - Basic CRUD]
|
||||
T3_2[T3.2: CorrespondenceModule - Advanced Features]
|
||||
T3_3[T3.3: RfaModule - Basic CRUD]
|
||||
T3_4[T3.4: Correspondence Routing]
|
||||
end
|
||||
%% Phase 3: Correspondence & RFA Core
|
||||
subgraph Phase 3 [Phase 3: Correspondence & RFA Core]
|
||||
T3_1[T3.1: CorrespondenceModule - Basic CRUD]
|
||||
T3_2[T3.2: CorrespondenceModule - Advanced Features]
|
||||
T3_3[T3.3: RfaModule - Basic CRUD]
|
||||
T3_4[T3.4: Correspondence Routing]
|
||||
end
|
||||
|
||||
%% Phase 4: Drawing Management
|
||||
subgraph Phase 4 [Phase 4: Drawing Management]
|
||||
T4_1[T4.1: DrawingModule - Contract Drawings]
|
||||
T4_2[T4.2: DrawingModule - Shop Drawings]
|
||||
end
|
||||
%% Phase 4: Drawing Management
|
||||
subgraph Phase 4 [Phase 4: Drawing Management]
|
||||
T4_1[T4.1: DrawingModule - Contract Drawings]
|
||||
T4_2[T4.2: DrawingModule - Shop Drawings]
|
||||
end
|
||||
|
||||
%% Phase 5: Workflow Systems & Resilience
|
||||
subgraph Phase 5 [Phase 5: Workflow Systems & Resilience]
|
||||
T5_1[T5.1: RfaModule - Workflow Implementation]
|
||||
T5_2[T5.2: CirculationModule - Internal Routing]
|
||||
T5_3[T5.3: TransmittalModule - Document Forwarding]
|
||||
end
|
||||
%% Phase 5: Workflow Systems & Resilience
|
||||
subgraph Phase 5 [Phase 5: Workflow Systems & Resilience]
|
||||
T5_1[T5.1: RfaModule - Workflow Implementation]
|
||||
T5_2[T5.2: CirculationModule - Internal Routing]
|
||||
T5_3[T5.3: TransmittalModule - Document Forwarding]
|
||||
end
|
||||
|
||||
%% Phase 6: Advanced Features & Monitoring
|
||||
subgraph Phase 6 [Phase 6: Advanced Features & Monitoring]
|
||||
T6_1[T6.1: SearchModule - Elasticsearch Integration]
|
||||
T6_2[T6.2: NotificationModule - Email & Line]
|
||||
T6_3[T6.3: MonitoringModule - Observability]
|
||||
T6_4[T6.4: ResilienceModule - Circuit Breaker & Retry]
|
||||
end
|
||||
%% Phase 6: Advanced Features & Monitoring
|
||||
subgraph Phase 6 [Phase 6: Advanced Features & Monitoring]
|
||||
T6_1[T6.1: SearchModule - Elasticsearch Integration]
|
||||
T6_2[T6.2: NotificationModule - Email & Line]
|
||||
T6_3[T6.3: MonitoringModule - Observability]
|
||||
T6_4[T6.4: ResilienceModule - Circuit Breaker & Retry]
|
||||
end
|
||||
|
||||
%% Phase 7: Testing & Optimization
|
||||
subgraph Phase 7 [Phase 7: Testing & Optimization]
|
||||
T7_1[T7.1: Unit Testing]
|
||||
T7_2[T7.2: Integration Testing]
|
||||
T7_3[T7.3: E2E Testing]
|
||||
T7_4[T7.4: Performance Testing]
|
||||
T7_5[T7.5: Security Testing]
|
||||
T7_6[T7.6: Performance Optimization]
|
||||
end
|
||||
%% Phase 7: Testing & Optimization
|
||||
subgraph Phase 7 [Phase 7: Testing & Optimization]
|
||||
T7_1[T7.1: Unit Testing]
|
||||
T7_2[T7.2: Integration Testing]
|
||||
T7_3[T7.3: E2E Testing]
|
||||
T7_4[T7.4: Performance Testing]
|
||||
T7_5[T7.5: Security Testing]
|
||||
T7_6[T7.6: Performance Optimization]
|
||||
end
|
||||
|
||||
%% Phase 8: Documentation & Deployment
|
||||
subgraph Phase 8 [Phase 8: Documentation & Deployment]
|
||||
T8_1[T8.1: API Documentation]
|
||||
T8_2[T8.2: Technical Documentation]
|
||||
T8_3[T8.3: Security Hardening]
|
||||
T8_4[T8.4: Deployment Preparation]
|
||||
T8_5[T8.5: Production Deployment]
|
||||
T8_6[T8.6: Handover to Frontend Team]
|
||||
end
|
||||
%% Phase 8: Documentation & Deployment
|
||||
subgraph Phase 8 [Phase 8: Documentation & Deployment]
|
||||
T8_1[T8.1: API Documentation]
|
||||
T8_2[T8.2: Technical Documentation]
|
||||
T8_3[T8.3: Security Hardening]
|
||||
T8_4[T8.4: Deployment Preparation]
|
||||
T8_5[T8.5: Production Deployment]
|
||||
T8_6[T8.6: Handover to Frontend Team]
|
||||
end
|
||||
|
||||
%% Dependencies
|
||||
T0_1 --> T0_2
|
||||
T0_2 --> T0_3
|
||||
T0_3 --> T0_4
|
||||
%% Dependencies
|
||||
T0_1 --> T0_2
|
||||
T0_2 --> T0_3
|
||||
T0_3 --> T0_4
|
||||
|
||||
T0_2 --> T1_1
|
||||
T0_3 --> T1_1
|
||||
T1_1 --> T1_2
|
||||
T1_1 --> T1_3
|
||||
T1_1 --> T1_4
|
||||
T1_1 --> T1_5
|
||||
T1_2 --> T1_3
|
||||
T1_3 --> T1_4
|
||||
T0_2 --> T1_1
|
||||
T0_3 --> T1_1
|
||||
T1_1 --> T1_2
|
||||
T1_1 --> T1_3
|
||||
T1_1 --> T1_4
|
||||
T1_1 --> T1_5
|
||||
T1_2 --> T1_3
|
||||
T1_3 --> T1_4
|
||||
|
||||
T0_3 --> T2_1
|
||||
T1_1 --> T2_1
|
||||
T1_5 --> T2_1
|
||||
T1_1 --> T2_2
|
||||
T1_4 --> T2_2
|
||||
T1_1 --> T2_3
|
||||
T1_1 --> T2_4
|
||||
T1_1 --> T2_5
|
||||
T0_3 --> T2_1
|
||||
T1_1 --> T2_1
|
||||
T1_5 --> T2_1
|
||||
T1_1 --> T2_2
|
||||
T1_4 --> T2_2
|
||||
T1_1 --> T2_3
|
||||
T1_1 --> T2_4
|
||||
T1_1 --> T2_5
|
||||
|
||||
T1_1 --> T3_1
|
||||
T1_2 --> T3_1
|
||||
T1_3 --> T3_1
|
||||
T1_4 --> T3_1
|
||||
T1_5 --> T3_1
|
||||
T2_3 --> T3_1
|
||||
T2_2 --> T3_1
|
||||
T2_5 --> T3_1
|
||||
T3_1 --> T3_2
|
||||
T3_1 --> T3_3
|
||||
T1_5 --> T3_3
|
||||
T3_1 --> T3_4
|
||||
T2_5 --> T3_4
|
||||
T1_1 --> T3_1
|
||||
T1_2 --> T3_1
|
||||
T1_3 --> T3_1
|
||||
T1_4 --> T3_1
|
||||
T1_5 --> T3_1
|
||||
T2_3 --> T3_1
|
||||
T2_2 --> T3_1
|
||||
T2_5 --> T3_1
|
||||
T3_1 --> T3_2
|
||||
T3_1 --> T3_3
|
||||
T1_5 --> T3_3
|
||||
T3_1 --> T3_4
|
||||
T2_5 --> T3_4
|
||||
|
||||
T1_1 --> T4_1
|
||||
T1_2 --> T4_1
|
||||
T1_4 --> T4_1
|
||||
T1_5 --> T4_1
|
||||
T2_2 --> T4_1
|
||||
T4_1 --> T4_2
|
||||
T1_1 --> T4_1
|
||||
T1_2 --> T4_1
|
||||
T1_4 --> T4_1
|
||||
T1_5 --> T4_1
|
||||
T2_2 --> T4_1
|
||||
T4_1 --> T4_2
|
||||
|
||||
T3_3 --> T5_1
|
||||
T4_2 --> T5_1
|
||||
T2_5 --> T5_1
|
||||
T3_1 --> T5_2
|
||||
T2_5 --> T5_2
|
||||
T3_1 --> T5_3
|
||||
T3_3 --> T5_1
|
||||
T4_2 --> T5_1
|
||||
T2_5 --> T5_1
|
||||
T3_1 --> T5_2
|
||||
T2_5 --> T5_2
|
||||
T3_1 --> T5_3
|
||||
|
||||
T3_1 --> T6_1
|
||||
T3_3 --> T6_1
|
||||
T4_2 --> T6_1
|
||||
T5_2 --> T6_1
|
||||
T5_3 --> T6_1
|
||||
T1_1 --> T6_2
|
||||
T6_4 --> T6_2
|
||||
T1_1 --> T6_3
|
||||
T1_1 --> T6_4
|
||||
T3_1 --> T6_1
|
||||
T3_3 --> T6_1
|
||||
T4_2 --> T6_1
|
||||
T5_2 --> T6_1
|
||||
T5_3 --> T6_1
|
||||
T1_1 --> T6_2
|
||||
T6_4 --> T6_2
|
||||
T1_1 --> T6_3
|
||||
T1_1 --> T6_4
|
||||
|
||||
%% All development phases must be complete before testing
|
||||
T1_5 --> T7_1
|
||||
T2_5 --> T7_1
|
||||
T3_4 --> T7_1
|
||||
T4_2 --> T7_1
|
||||
T5_3 --> T7_1
|
||||
T6_4 --> T7_1
|
||||
T7_1 --> T7_2
|
||||
T7_2 --> T7_3
|
||||
T7_3 --> T7_4
|
||||
T7_4 --> T7_5
|
||||
T7_5 --> T7_6
|
||||
%% All development phases must be complete before testing
|
||||
T1_5 --> T7_1
|
||||
T2_5 --> T7_1
|
||||
T3_4 --> T7_1
|
||||
T4_2 --> T7_1
|
||||
T5_3 --> T7_1
|
||||
T6_4 --> T7_1
|
||||
T7_1 --> T7_2
|
||||
T7_2 --> T7_3
|
||||
T7_3 --> T7_4
|
||||
T7_4 --> T7_5
|
||||
T7_5 --> T7_6
|
||||
|
||||
%% Testing must be complete before deployment
|
||||
T7_6 --> T8_1
|
||||
T8_1 --> T8_2
|
||||
T8_2 --> T8_3
|
||||
T8_3 --> T8_4
|
||||
T8_4 --> T8_5
|
||||
T8_5 --> T8_6
|
||||
```
|
||||
%% Testing must be complete before deployment
|
||||
T7_6 --> T8_1
|
||||
T8_1 --> T8_2
|
||||
T8_2 --> T8_3
|
||||
T8_3 --> T8_4
|
||||
T8_4 --> T8_5
|
||||
T8_5 --> T8_6
|
||||
```
|
||||
|
||||
## **Phase 0: Infrastructure Setup (สัปดาห์ที่ 1)**
|
||||
|
||||
@@ -289,7 +289,6 @@ src/
|
||||
- **Dependencies:** T0.1 (ต้องมี Docker Network และ Environment พร้อมก่อนสร้าง Project)
|
||||
|
||||
- **[✅] T0.3 Setup Database Connection**
|
||||
|
||||
- Import SQL Schema v1.4.0 เข้า MariaDB
|
||||
- Run Seed Data (organizations, users, roles, permissions)
|
||||
- Configure TypeORM ใน AppModule
|
||||
@@ -774,7 +773,7 @@ src/
|
||||
- [ ] POST /correspondences/:id/routing/start → Start routing
|
||||
- [ ] POST /routing/:id/process → Process routing step
|
||||
- [ ] GET /correspondences/:id/routing → Get routing status
|
||||
- [ ] ตัวอย่าง Implementation Details
|
||||
- [ ] ตัวอย่าง Implementation Details
|
||||
|
||||
- **[ ] T3.4.3 WorkflowEngineModule - State Management**
|
||||
- [ ] สร้าง WorkflowEngineService:
|
||||
@@ -845,7 +844,7 @@ src/
|
||||
- [ ] Schema version upgrades
|
||||
- [ ] Data transformation scenarios
|
||||
- [ ] Backward compatibility
|
||||
民主- **Exit Criteria:** JSON details integrated across all modules
|
||||
民主- **Exit Criteria:** JSON details integrated across all modules
|
||||
|
||||
---
|
||||
|
||||
@@ -1069,7 +1068,7 @@ quality_gates:
|
||||
required: true
|
||||
integration_tests:
|
||||
scenarios: all_core
|
||||
required: true
|
||||
required: true
|
||||
security_tests:
|
||||
vulnerabilities: 0
|
||||
required: true
|
||||
@@ -1156,7 +1155,7 @@ quality_gates:
|
||||
|
||||
### 📊 **Testing Metrics & Exit Criteria**
|
||||
|
||||
**แต่ละ Phase ต้องผ่าน Metrics เหล่านี้:**
|
||||
**แต่ละ Phase ต้องผ่าน Metrics เหล่านี้:**
|
||||
|
||||
#### **Phase Completion Metrics**
|
||||
|
||||
@@ -1261,8 +1260,8 @@ quality_gates:
|
||||
|
||||
## 📊 **สรุป Timeline**
|
||||
|
||||
| Phase | ระยะเวลา | จำนวนงาน | Output หลัก |
|
||||
| ------- | ------------ | ------------ | ------------------------------------ |
|
||||
| Phase | ระยะเวลา | จำนวนงาน | Output หลัก |
|
||||
| ------- | -------------- | ------------ | ------------------------------------ |
|
||||
| Phase 0 | 1 สัปดาห์ | 4 | Infrastructure Ready + Security Base |
|
||||
| Phase 1 | 2 สัปดาห์ | 5 | Auth & User Management + RBAC |
|
||||
| Phase 2 | 1 สัปดาห์ | 4 | Security & File Management |
|
||||
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
### 1. LCBP3-DMS_V1_4_1_Backend_Development_Plan.md (ปรับแก้หลัก)
|
||||
|
||||
```markdown
|
||||
````markdown
|
||||
# 📋 **แผนการพัฒนา Backend (NestJS) - LCBP3-DMS v1.4.1 (ปรับปรุงล่าสุด 18 พ.ย. 2568)**
|
||||
|
||||
**ปรับตาม Review Critical Issues & ข้อเสนอแนะทั้งหมด**
|
||||
|
||||
---
|
||||
---
|
||||
|
||||
### Technology Stack (เพิ่มเติม/ปรับปรุง)
|
||||
|
||||
@@ -50,6 +50,8 @@
|
||||
// หรือใน TypeORM
|
||||
.createQueryBuilder().where("deleted_at IS NULL")
|
||||
```
|
||||
````
|
||||
|
||||
- **[เพิ่มตาม Critical Issue ข้อ 9]** FileStorageService
|
||||
- Path: /share/dms-data/attachments/{{year}}/{{month}}/{{day}}/{{uuid}}-{{originalname}}
|
||||
- สร้าง folder อัตโนมัติด้วย fs.promises.mkdir(..., { recursive: true })
|
||||
@@ -94,7 +96,7 @@
|
||||
- เพิ่ม Security Scheme ตั้งแต่ Phase 1:
|
||||
```ts
|
||||
SwaggerModule.setup('api', app, document, {
|
||||
swaggerOptions: { security: [{ bearer: [] }] }
|
||||
swaggerOptions: { security: [{ bearer: [] }] },
|
||||
});
|
||||
```
|
||||
- ทุก endpoint ใส่ @ApiBearerAuth() + @RequirePermission('permission.name')
|
||||
@@ -106,7 +108,7 @@ services:
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
container_name: lcbp3-redis
|
||||
ports: ["6379:6379"]
|
||||
ports: ['6379:6379']
|
||||
volumes: [redis-data:/data]
|
||||
|
||||
clamav:
|
||||
@@ -115,11 +117,11 @@ services:
|
||||
|
||||
prometheus:
|
||||
image: prom/prometheus
|
||||
volumes: ["./prometheus.yml:/etc/prometheus/prometheus.yml"]
|
||||
volumes: ['./prometheus.yml:/etc/prometheus/prometheus.yml']
|
||||
|
||||
grafana:
|
||||
image: grafana/grafana
|
||||
ports: ["3000:3000"]
|
||||
ports: ['3000:3000']
|
||||
```
|
||||
|
||||
(รายละเอียดเต็มแยกไฟล์)
|
||||
@@ -130,16 +132,20 @@ services:
|
||||
|
||||
```markdown
|
||||
### 2.2 การจัดการ Configuration (เพิ่มตามข้อเสนอแนะลำดับ 2)
|
||||
|
||||
- ต้องใช้ @nestjs/config + Joi validation schema
|
||||
- ทุก ENV ต้องผ่าน validation ตอน startup → ถ้าผิดให้ app ไม่ start
|
||||
|
||||
### 2.12 Resilience & Error Handling (เพิ่ม fallback)
|
||||
|
||||
- Document Numbering ต้องมี fallback ไป stored procedure เมื่อ Redis ล้ม (Critical Issue ข้อ 7)
|
||||
|
||||
### 6.5.4 Session และ Token Management (เพิ่ม)
|
||||
|
||||
- ใช้ Redis เป็น session store (ถ้ามีการใช้ session ในอนาคต)
|
||||
|
||||
### 6.8 Monitoring และ Observability (เพิ่มตาม Critical Issue ข้อ 5)
|
||||
|
||||
- ต้องมี /health endpoint แยกส่วน (DB, Redis, Elasticsearch, ClamAV)
|
||||
- ต้อง expose Prometheus metrics
|
||||
- ต้องมี Grafana dashboard พื้นฐาน
|
||||
@@ -149,20 +155,24 @@ services:
|
||||
|
||||
```markdown
|
||||
### 2.1 หลักการพื้นฐาน (เพิ่ม)
|
||||
* ใช้ @nestjs/config + Joi validation ทุก ENV (ข้อเสนอแนะลำดับ 2)
|
||||
* RBAC ต้อง query v_user_all_permissions view เป็นหลัก และ cache ผลลัพธ์ใน Redis (Critical Issue ข้อ 6)
|
||||
|
||||
- ใช้ @nestjs/config + Joi validation ทุก ENV (ข้อเสนอแนะลำดับ 2)
|
||||
- RBAC ต้อง query v_user_all_permissions view เป็นหลัก และ cache ผลลัพธ์ใน Redis (Critical Issue ข้อ 6)
|
||||
|
||||
### 2.3 ฟังก์ชัน (เพิ่ม)
|
||||
* งานที่ใช้เวลานาน (notification, reindex, cleanup) ต้องใช้ Background Job (BullMQ) ไม่ใช่ Cron โดยตรง (ข้อเสนอแนะลำดับ 4)
|
||||
|
||||
- งานที่ใช้เวลานาน (notification, reindex, cleanup) ต้องใช้ Background Job (BullMQ) ไม่ใช่ Cron โดยตรง (ข้อเสนอแนะลำดับ 4)
|
||||
|
||||
### 3.1 หลักการ (เพิ่ม)
|
||||
* Monitoring: ต้อง implement @nestjs/terminus + Prometheus exporter (Critical Issue ข้อ 5)
|
||||
|
||||
- Monitoring: ต้อง implement @nestjs/terminus + Prometheus exporter (Critical Issue ข้อ 5)
|
||||
```
|
||||
|
||||
### 4. LCBP3-DMS_V1_4_1_Data_Dictionary.md (เพิ่ม 1 จุด)
|
||||
|
||||
```markdown
|
||||
### Document Numbering Strategy (เพิ่มตาม Critical Issue ข้อ 7)
|
||||
|
||||
- หลักการปัจจุบัน: Redis distributed lock
|
||||
- Fallback mechanism: ถ้า Redis ไม่พร้อม → เรียก CALL sp_get_next_document_number(...)
|
||||
- ต้อง log การ fallback ทุกครั้งใน audit_logs ด้วย action = 'DOCUMENT_NUMBER_FALLBACK'
|
||||
@@ -182,6 +192,7 @@ services:
|
||||
### 🆕 **เพิ่มใหม่**
|
||||
|
||||
#### **T0.2.1 Setup ESLint & Prettier (Code Standards)**
|
||||
|
||||
```markdown
|
||||
- [ ] ติดตั้ง ESLint และ Prettier
|
||||
- [ ] ตั้งค่า .eslintrc.js และ .prettierrc
|
||||
@@ -192,6 +203,7 @@ services:
|
||||
```
|
||||
|
||||
#### **T0.5 Database Migration Planning**
|
||||
|
||||
```markdown
|
||||
- [ ] สร้าง Migration Scripts Structure
|
||||
- [ ] วางแผน Database Versioning Strategy
|
||||
@@ -202,6 +214,7 @@ services:
|
||||
```
|
||||
|
||||
#### **T0.6 Environment Management Strategy**
|
||||
|
||||
```markdown
|
||||
- [ ] สร้าง Configuration Service
|
||||
- [ ] วางแผน Environment Variables Management
|
||||
@@ -212,6 +225,7 @@ services:
|
||||
```
|
||||
|
||||
#### **T1.6 Error Handling Strategy**
|
||||
|
||||
```markdown
|
||||
- [ ] สร้าง Global Exception Filter
|
||||
- [ ] สร้าง Error Response Standard
|
||||
@@ -222,6 +236,7 @@ services:
|
||||
```
|
||||
|
||||
#### **T6.5 API Versioning Strategy**
|
||||
|
||||
```markdown
|
||||
- [ ] สร้าง API Versioning Middleware
|
||||
- [ ] วางแผน Versioning Strategy (URI vs Header)
|
||||
@@ -232,6 +247,7 @@ services:
|
||||
```
|
||||
|
||||
#### **T7.7 Load Testing Simulation**
|
||||
|
||||
```markdown
|
||||
- [ ] สร้าง Load Testing Scripts
|
||||
- [ ] จำลองการใช้งานจริง (100 concurrent users)
|
||||
@@ -242,6 +258,7 @@ services:
|
||||
```
|
||||
|
||||
#### **T8.7 Backup & Recovery Planning**
|
||||
|
||||
```markdown
|
||||
- [ ] สร้าง Backup Scripts (Database + Files)
|
||||
- [ ] วางแผน Recovery Procedures
|
||||
@@ -252,6 +269,7 @@ services:
|
||||
```
|
||||
|
||||
#### **T8.8 Data Privacy & Compliance Implementation**
|
||||
|
||||
```markdown
|
||||
- [ ] สร้าง Data Privacy Policies
|
||||
- [ ] Implement Data Retention Rules
|
||||
@@ -264,6 +282,7 @@ services:
|
||||
### 🔄 **แก้ไข**
|
||||
|
||||
#### **T2.5 JSON Details & Schema Management (ปรับปรุง)**
|
||||
|
||||
```markdown
|
||||
- **เดิม:** เป็นส่วนแยกที่ดูไม่เชื่อมโยง
|
||||
- **ใหม่:** รวมเข้ากับ Phase 2 อย่างเป็นธรรมชาติ
|
||||
@@ -272,6 +291,7 @@ services:
|
||||
```
|
||||
|
||||
#### **T6.4 ResilienceModule (ปรับปรุง)**
|
||||
|
||||
```markdown
|
||||
- **เดิม:** ไม่ระบุว่าจะใช้กับ Services ใด
|
||||
- **ใหม่:** ระบุชัดเจนว่าจะใช้กับ:
|
||||
@@ -282,6 +302,7 @@ services:
|
||||
```
|
||||
|
||||
#### **T8.1 API Documentation (ปรับปรุง)**
|
||||
|
||||
```markdown
|
||||
- **เดิม:** แค่บอกว่าต้องสร้าง Swagger
|
||||
- **ใหม่:** เพิ่มรายละเอียด:
|
||||
@@ -298,6 +319,7 @@ services:
|
||||
### 🆕 **เพิ่มใหม่**
|
||||
|
||||
#### **2.13 Database Migration และ Schema Versioning**
|
||||
|
||||
```markdown
|
||||
- ต้องมี database migration scripts สำหรับทุก schema change
|
||||
- ต้องรองรับ rollback ของ migration ได้
|
||||
@@ -307,6 +329,7 @@ services:
|
||||
```
|
||||
|
||||
#### **2.14 Code Standards และ Quality Assurance**
|
||||
|
||||
```markdown
|
||||
- ต้องมี ESLint และ Prettier สำหรับรักษามาตรฐานโค้ด
|
||||
- ต้องมี pre-commit hooks สำหรับตรวจสอบโค้ด
|
||||
@@ -315,6 +338,7 @@ services:
|
||||
```
|
||||
|
||||
#### **6.10 API Versioning Strategy**
|
||||
|
||||
```markdown
|
||||
- ต้องมี API versioning strategy ที่ชัดเจน
|
||||
- รองรับ backward compatibility อย่างน้อย 2 versions
|
||||
@@ -323,6 +347,7 @@ services:
|
||||
```
|
||||
|
||||
#### **6.11 Data Privacy และ Compliance Implementation**
|
||||
|
||||
```markdown
|
||||
- ต้องมี data privacy policies ที่ชัดเจน
|
||||
- ต้องมี data retention rules ตามกฎหมาย
|
||||
@@ -333,6 +358,7 @@ services:
|
||||
### 🔄 **แก้ไข**
|
||||
|
||||
#### **2.12 กลยุทธ์ความทนทานและการจัดการข้อผิดพลาด**
|
||||
|
||||
```markdown
|
||||
- **เพิ่ม:** รายละเอียดเกี่ยวกับ Error Handling Strategy
|
||||
- **เพิ่ม:** รายละเอียดเกี่ยวกับ Monitoring Integration
|
||||
@@ -340,6 +366,7 @@ services:
|
||||
```
|
||||
|
||||
#### **3.11 การจัดการ JSON Details**
|
||||
|
||||
```markdown
|
||||
- **ปรับ:** ทำให้เป็นส่วนหนึ่งของ Requirements หลัก
|
||||
- **เพิ่ม:** รายละเอียดเกี่ยวกับ Schema Versioning
|
||||
@@ -353,6 +380,7 @@ services:
|
||||
### 🆕 **เพิ่มใหม่**
|
||||
|
||||
#### **3.16 Database Migration Strategy**
|
||||
|
||||
```typescript
|
||||
// Migration Scripts Structure
|
||||
src/
|
||||
@@ -369,6 +397,7 @@ src/
|
||||
```
|
||||
|
||||
#### **3.17 Environment Configuration Management**
|
||||
|
||||
```typescript
|
||||
// Configuration Service Example
|
||||
@Injectable()
|
||||
@@ -387,6 +416,7 @@ export class ConfigService {
|
||||
```
|
||||
|
||||
#### **3.18 API Versioning Implementation**
|
||||
|
||||
```typescript
|
||||
// API Versioning Middleware
|
||||
@Controller('api/v1')
|
||||
@@ -403,6 +433,7 @@ export class CorrespondenceControllerV2 {
|
||||
### 🔄 **แก้ไข**
|
||||
|
||||
#### **3.8 Error Handling และ Monitoring**
|
||||
|
||||
```typescript
|
||||
// Global Exception Filter
|
||||
@Catch()
|
||||
@@ -416,22 +447,23 @@ export class AllExceptionsFilter implements ExceptionFilter {
|
||||
```
|
||||
|
||||
#### **4.5 Frontend Testing Strategy**
|
||||
|
||||
```typescript
|
||||
// Testing Stack Configuration
|
||||
const testingConfig = {
|
||||
unit: {
|
||||
framework: 'Vitest',
|
||||
library: 'React Testing Library',
|
||||
coverage: '80%'
|
||||
coverage: '80%',
|
||||
},
|
||||
integration: {
|
||||
tool: 'MSW',
|
||||
scenarios: 'API mocking'
|
||||
scenarios: 'API mocking',
|
||||
},
|
||||
e2e: {
|
||||
tool: 'Playwright',
|
||||
scenarios: 'User workflows'
|
||||
}
|
||||
scenarios: 'User workflows',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -442,6 +474,7 @@ const testingConfig = {
|
||||
### 🆕 **เพิ่มใหม่**
|
||||
|
||||
#### **5. JSON Schema Definitions Table**
|
||||
|
||||
```sql
|
||||
CREATE TABLE json_schema_definitions (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
@@ -456,6 +489,7 @@ CREATE TABLE json_schema_definitions (
|
||||
```
|
||||
|
||||
#### **6. Migration History Table**
|
||||
|
||||
```sql
|
||||
CREATE TABLE migration_history (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
@@ -468,6 +502,7 @@ CREATE TABLE migration_history (
|
||||
```
|
||||
|
||||
#### **7. Configuration Management Table**
|
||||
|
||||
```sql
|
||||
CREATE TABLE configuration_management (
|
||||
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||
@@ -484,18 +519,20 @@ CREATE TABLE configuration_management (
|
||||
### 🔄 **แก้ไข**
|
||||
|
||||
#### **3.9 correspondence_revisions Table**
|
||||
|
||||
```sql
|
||||
-- เพิ่ม JSON fields
|
||||
ALTER TABLE correspondence_revisions
|
||||
ALTER TABLE correspondence_revisions
|
||||
ADD COLUMN details JSON NULL,
|
||||
ADD COLUMN schema_version VARCHAR(20) NULL,
|
||||
ADD INDEX idx_correspondence_details ((CAST(details AS CHAR(255) ARRAY)));
|
||||
```
|
||||
|
||||
#### **4.5 rfa_revisions Table**
|
||||
|
||||
```sql
|
||||
-- เพิ่ม JSON fields
|
||||
ALTER TABLE rfa_revisions
|
||||
ALTER TABLE rfa_revisions
|
||||
ADD COLUMN details JSON NULL,
|
||||
ADD COLUMN schema_version VARCHAR(20) NULL,
|
||||
ADD INDEX idx_rfa_details ((CAST(details AS CHAR(255) ARRAY)));
|
||||
@@ -505,17 +542,18 @@ ADD INDEX idx_rfa_details ((CAST(details AS CHAR(255) ARRAY)));
|
||||
|
||||
## 📊 **สรุปการปรับปกป้องทั้งหมด**
|
||||
|
||||
| ประเภท | จำนวนที่ปรับ | หัวข้อหลักที่ปรับ |
|
||||
| -------------- | --------- | ------------------------------------------------------------------ |
|
||||
| เพิ่มใหม่ | 15 รายการ | Migration, Environment, Error Handling, API Versioning, Testing |
|
||||
| แก้ไข | 8 รายการ | JSON Integration, Circuit Breaker, Documentation, Testing Strategy |
|
||||
| ปรับปรุงโครงสร้าง | 3 ตาราง | JSON Schema, Migration History, Configuration |
|
||||
| ประเภท | จำนวนที่ปรับ | หัวข้อหลักที่ปรับ |
|
||||
| ----------------- | ------------ | ------------------------------------------------------------------ |
|
||||
| เพิ่มใหม่ | 15 รายการ | Migration, Environment, Error Handling, API Versioning, Testing |
|
||||
| แก้ไข | 8 รายการ | JSON Integration, Circuit Breaker, Documentation, Testing Strategy |
|
||||
| ปรับปรุงโครงสร้าง | 3 ตาราง | JSON Schema, Migration History, Configuration |
|
||||
|
||||
### 🎯 **ผลลัพธ์ที่ได้:**
|
||||
|
||||
1. **ความสมบูรณ์ของแผนการพัฒนา** - ครอบคลุมทุกด้านที่จำเป็น
|
||||
2. **ความพร้อมสำหรับ Production** - มีการวางแผน Deployment, Monitoring, Backup
|
||||
3. **มาตรฐานการพัฒนา** - มี Code Standards, Testing, Documentation
|
||||
4. **ความปลอดภัยและ Compliance** - มี Data Privacy, Security Measures
|
||||
5. **การบำรุงรักษาที่ง่าย** - มี Migration, Versioning, Configuration Management
|
||||
|
||||
การปรับปรุงเหล่านี้ทำให้เอกสารทั้ง 4 ชุดมีความสอดคล้องกันและพร้อมสำหรับการนำไปปฏิบัติจริงครับ
|
||||
การปรับปรุงเหล่านี้ทำให้เอกสารทั้ง 4 ชุดมีความสอดคล้องกันและพร้อมสำหรับการนำไปปฏิบัติจริงครับ
|
||||
|
||||
@@ -617,15 +617,15 @@
|
||||
|
||||
**Purpose**: เก็บข้อมูลแม่แบบ (Template) ของสายงานการส่งต่อเอกสารเพื่อขออนุมัติ ทำให้ไม่ต้องกำหนดขั้นตอนซ้ำทุกครั้ง สามารถสร้างเป็นแม่แบบทั่วไป หรือเฉพาะสำหรับโครงการใดโครงการหนึ่งได้
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------- | ------------ | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลัก (Primary Key) ของแม่แบบ รันค่าอัตโนมัติ |
|
||||
| template_name | VARCHAR(255) | NOT NULL | ชื่อของแม่แบบ เช่น "เสนอโครงการ", "ขออนุมัติจัดซื้อ" |
|
||||
| description | TEXT | NULL | คำอธิบายรายละเอียดเกี่ยวกับแม่แบบนี้ |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| ------------- | ------------ | --------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลัก (Primary Key) ของแม่แบบ รันค่าอัตโนมัติ |
|
||||
| template_name | VARCHAR(255) | NOT NULL | ชื่อของแม่แบบ เช่น "เสนอโครงการ", "ขออนุมัติจัดซื้อ" |
|
||||
| description | TEXT | NULL | คำอธิบายรายละเอียดเกี่ยวกับแม่แบบนี้ |
|
||||
| project_id | INT | NULL | ID ของโครงการที่แม่แบบนี้สังกัดอยู่ (ถ้ามี) **ค่า NULL หมายถึง** เป็น "แม่แบบทั่วไป" ที่สามารถใช้กับทุกโครงการได้ |
|
||||
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | วันที่และเวลาที่สร้างแม่แบบนี้ |
|
||||
| updated_at | TIMESTAMP | NOT NULL,`DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | วันที่และเวลาที่แก้ไขข้อมูลในแม่แบบนี้ล่าสุด |
|
||||
| is_active | BOOLEAN | DEFAULT TRUE | สถานะใช้งาน |
|
||||
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | วันที่และเวลาที่สร้างแม่แบบนี้ |
|
||||
| updated_at | TIMESTAMP | NOT NULL,`DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP | วันที่และเวลาที่แก้ไขข้อมูลในแม่แบบนี้ล่าสุด |
|
||||
| is_active | BOOLEAN | DEFAULT TRUE | สถานะใช้งาน |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -642,14 +642,14 @@
|
||||
|
||||
**Purpose**: เก็บรายละเอียดของแต่ละขั้นตอน (Steps) ภายในแม่แบบสายงาน (correspondence_routing_templates) กำหนดว่าจะส่งไปที่องค์กรไหน ลำดับเป็นเท่าไร และเพื่อวัตถุประสงค์อะไร
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :----------------- | --------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของขั้นตอน |
|
||||
| template_id | INT | NOT NULL | ID ของแม่แบบที่ขั้นตอนนี้สังกัดอยู่ |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอน (1, 2, 3, ...) |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรที่เป็นผู้รับในขั้นตอนนี้ |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| :----------------- | --------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของขั้นตอน |
|
||||
| template_id | INT | NOT NULL | ID ของแม่แบบที่ขั้นตอนนี้สังกัดอยู่ |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอน (1, 2, 3, ...) |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรที่เป็นผู้รับในขั้นตอนนี้ |
|
||||
| step_purpose | ENUM | NOT NULL,DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้ **ค่าที่เป็นไปได้:** [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ] |
|
||||
| expected_days | INT | NULL | วันที่คาดหวัง |
|
||||
| expected_days | INT | NULL | วันที่คาดหวัง |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -668,21 +668,21 @@
|
||||
|
||||
**Purpose**: เป็นตารางที่เก็บข้อมูลการส่งต่อเอกสารจริง (Instance/Run-time) ติดตามประวัติการเคลื่อนย้ายของแต่ละเอกสาร ว่าผ่านใครมาบ้าง อยู่ที่ใคร และสถานะปัจจุบันคืออะไร
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------- | --------- | ----------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของรายการส่งต่อ |
|
||||
| correspondence_id | INT | NOT NUL | ID ของเอกสาร (FK ไปยัง correspondence_revisions) |
|
||||
| template_id | INT | NULL | ID ของแม่แบบที่ใช้สร้างสายงานนี้ (เก็บไว้เป็นข้อมูลอ้างอิง) |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอนการส่งต่อจริง |
|
||||
| from_organization_id | INT | NOT NULL | ID ขององค์กรผู้ส่ง |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรผู้รับ |
|
||||
| step_purpose | ENUM | NOT NULL, DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้จริง **ค่าที่เป็นไปได้:** [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ, FOR_ACTION: เพื่อดำเนินการ] |
|
||||
| status | ENUM | NOT NULL, DEFAULT SENT | [ACTIONED: ดำเนินการแล้ว, FORWARDED: ส่งต่อแล้ว, REPLIE: ตอบกลับแล้ว] |
|
||||
| comments | TEXT | NULL | หมายเหตุหรือความคิดเห็นในการส่งต่อ |
|
||||
| due_date | DATETIME | NULL | วันที่ครบกำหนดที่ต้องดำเนินการในขั้นตอนนี้ |
|
||||
| processed_by_user_id | INT | NULL | ID ของผู้ใช้ที่ดำเนินการในขั้นตอนนี้จริงๆ |
|
||||
| processed_at | TIMESTAMP | NULL | เวลาที่ผู้ใช้ดำเนินการเสร็จสิ้น |
|
||||
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | เวลาที่สร้างรายการส่งต่อนี้ |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------------- | --------- | ----------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| id | INT | PRIMARY KEY, AUTO_INCREMENT | ID หลักของรายการส่งต่อ |
|
||||
| correspondence_id | INT | NOT NUL | ID ของเอกสาร (FK ไปยัง correspondence_revisions) |
|
||||
| template_id | INT | NULL | ID ของแม่แบบที่ใช้สร้างสายงานนี้ (เก็บไว้เป็นข้อมูลอ้างอิง) |
|
||||
| sequence | INT | NOT NULL | ลำดับของขั้นตอนการส่งต่อจริง |
|
||||
| from_organization_id | INT | NOT NULL | ID ขององค์กรผู้ส่ง |
|
||||
| to_organization_id | INT | NOT NULL | ID ขององค์กรผู้รับ |
|
||||
| step_purpose | ENUM | NOT NULL, DEFAULT FOR_REVIEW | วัตถุประสงค์ของการส่งต่อในขั้นตอนนี้จริง **ค่าที่เป็นไปได้:** [FOR_APPROVAL: เพื่ออนุมัติ, FOR_REVIEW: เพื่อตรวจสอบ/พิจารณา, FOR_INFORMATION: เพื่อทราบ, FOR_ACTION: เพื่อดำเนินการ] |
|
||||
| status | ENUM | NOT NULL, DEFAULT SENT | [ACTIONED: ดำเนินการแล้ว, FORWARDED: ส่งต่อแล้ว, REPLIE: ตอบกลับแล้ว] |
|
||||
| comments | TEXT | NULL | หมายเหตุหรือความคิดเห็นในการส่งต่อ |
|
||||
| due_date | DATETIME | NULL | วันที่ครบกำหนดที่ต้องดำเนินการในขั้นตอนนี้ |
|
||||
| processed_by_user_id | INT | NULL | ID ของผู้ใช้ที่ดำเนินการในขั้นตอนนี้จริงๆ |
|
||||
| processed_at | TIMESTAMP | NULL | เวลาที่ผู้ใช้ดำเนินการเสร็จสิ้น |
|
||||
| created_at | TIMESTAMP | NOT NULL, DEFAULT CURRENT_TIMESTAMP | เวลาที่สร้างรายการส่งต่อนี้ |
|
||||
|
||||
**Indexes**:
|
||||
|
||||
@@ -707,11 +707,11 @@
|
||||
|
||||
**Purpose**: ตารางนี้ใช้กำหนดกฎ (State Machine) ว่าสถานะใดสามารถเปลี่ยนไปเป็นสถานะใดได้บ้าง โดยขึ้นอยู่กับประเภทของหนังสือ เพื่อควบคุมการไหลของสถานะให้ถูกต้องตามข้อบังคับ
|
||||
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------- | --------- | ----------- | ----------------------------------------------- |
|
||||
| Column Name | Data Type | Constraints | Description |
|
||||
| -------------- | --------- | ----------- | ------------------------------------------------------ |
|
||||
| type_id | INT | PRIMARY KEY | ID ของประเภทหนังสือ (เช่น หนังสือภายใน, หนังสือภายนอก) |
|
||||
| from_status_id | INT | PRIMARY KEY | ID ของสถานะต้นทาง (เช่น ร่าง) |
|
||||
| to_status_id | INT | PRIMARY KEY | ID ของสถานะปลายทาง (เช่น รออนุมัติ) |
|
||||
| from_status_id | INT | PRIMARY KEY | ID ของสถานะต้นทาง (เช่น ร่าง) |
|
||||
| to_status_id | INT | PRIMARY KEY | ID ของสถานะปลายทาง (เช่น รออนุมัติ) |
|
||||
|
||||
**คีย์หลัก (Primary Key):**
|
||||
|
||||
@@ -2320,28 +2320,23 @@ CALL sp_get_next_document_number(
|
||||
**Additional Performance Indexes**:
|
||||
|
||||
1. **Correspondence Tables**:
|
||||
|
||||
- `idx_correspondences_type_project` on (correspondence_type_id, project_id)
|
||||
- `idx_corr_revisions_current_status` on (is_current, correspondence_status_id)
|
||||
- `idx_corr_revisions_correspondence_current` on (correspondence_id, is_current)
|
||||
- `idx_correspondences_project_type` on (project_id, correspondence_type_id)
|
||||
|
||||
2. **RFA Tables**:
|
||||
|
||||
- `idx_rfa_revisions_current_status` on (is_current, rfa_status_code_id)
|
||||
- `idx_rfa_revisions_rfa_current` on (rfa_id, is_current)
|
||||
|
||||
3. **Circulation Tables**:
|
||||
|
||||
- `idx_circulation_routings_status_assigned` on (status, assigned_to)
|
||||
- `idx_circulation_routings_circulation_status` on (circulation_id, status)
|
||||
|
||||
4. **Document Numbering**:
|
||||
|
||||
- `idx_doc_counter_composite` on (project_id, originator_organization_id, correspondence_type_id, current_year)
|
||||
|
||||
5. **Audit & Notifications**:
|
||||
|
||||
- `idx_audit_logs_reporting` on (created_at, entity_type, action)
|
||||
- `idx_notifications_user_unread` on (user_id, is_read, created_at)
|
||||
|
||||
@@ -2369,12 +2364,10 @@ CALL sp_get_next_document_number(
|
||||
### Unique Constraints
|
||||
|
||||
1. **Globally Unique**:
|
||||
|
||||
- usernames, emails
|
||||
- shop_drawing.drawing_number
|
||||
|
||||
2. **Unique Within Scope**:
|
||||
|
||||
- (project_id, correspondence_number)
|
||||
- (project_id, condwg_no)
|
||||
- (correspondence_id, revision_number)
|
||||
@@ -2393,13 +2386,11 @@ CALL sp_get_next_document_number(
|
||||
### Business Rule Constraints
|
||||
|
||||
1. **Soft Delete Pattern**:
|
||||
|
||||
- deleted_at timestamp instead of hard delete
|
||||
- Preserves audit trail and relationships
|
||||
- Applied to: correspondences, rfas, shop_drawings, contract_drawings
|
||||
|
||||
2. **Current Revision Pattern**:
|
||||
|
||||
- is_current flag with UNIQUE constraint
|
||||
- Ensures only one current revision per document
|
||||
|
||||
@@ -2584,13 +2575,11 @@ ANALYZE TABLE correspondences;
|
||||
### Business Logic Validation
|
||||
|
||||
1. **Document Workflow**:
|
||||
|
||||
- Cannot edit submitted documents (unless Document Control)
|
||||
- Cannot skip workflow steps (unless forced)
|
||||
- Must provide approval comments
|
||||
|
||||
2. **User Management**:
|
||||
|
||||
- Cannot delete users with active assignments
|
||||
- Cannot deactivate own account
|
||||
- Must have valid organization for non-Global roles
|
||||
@@ -2706,19 +2695,16 @@ ANALYZE TABLE correspondences;
|
||||
### Integration Points
|
||||
|
||||
1. **Document Numbering**:
|
||||
|
||||
- Call sp_get_next_document_number
|
||||
- Format with template from document_number_formats
|
||||
- Store in correspondences.correspondence_number
|
||||
|
||||
2. **File Upload**:
|
||||
|
||||
- Upload to QNAP /share/dms-data/
|
||||
- Create attachment record
|
||||
- Link via junction table
|
||||
|
||||
3. **Workflow Execution**:
|
||||
|
||||
- Check rfa_workflow_templates
|
||||
- Create rfa_workflows records
|
||||
- Update status as steps complete
|
||||
@@ -2830,4 +2816,4 @@ SELECT * FROM information_schema.INNODB_LOCK_WAITS;
|
||||
|
||||
---
|
||||
|
||||
_End of Data Dictionary
|
||||
\_End of Data Dictionary
|
||||
|
||||
@@ -35,72 +35,72 @@
|
||||
|
||||
### **โครงสร้างโปรเจกต์**
|
||||
|
||||
```tree
|
||||
app/
|
||||
├── (public)/ # Public routes (Landing, Login)
|
||||
│ ├── page.tsx # Landing Page
|
||||
│ └── login/ # Login Page
|
||||
├── (protected)/ # Protected routes
|
||||
│ ├── layout.tsx # App Shell (Navbar + Sidebar)
|
||||
│ ├── dashboard/ # Dashboard
|
||||
│ ├── correspondences/ # Correspondence Management
|
||||
│ ├── rfas/ # RFA Management
|
||||
│ ├── drawings/ # Drawing Management
|
||||
│ ├── circulations/ # Circulation Management
|
||||
│ ├── transmittals/ # Transmittal Management
|
||||
│ ├── search/ # Advanced Search
|
||||
│ ├── reports/ # Reports
|
||||
│ ├── admin/ # Admin Panel
|
||||
│ └── profile/ # User Profile
|
||||
├── api/ # API Routes (if needed)
|
||||
components/
|
||||
├── ui/ # shadcn/ui components
|
||||
├── features/ # Feature-specific components
|
||||
│ ├── auth/
|
||||
│ ├── correspondence/
|
||||
│ ├── rfa/
|
||||
│ ├── drawing/
|
||||
│ ├── circulation/
|
||||
│ ├── common/
|
||||
│ ├── security/ # NEW: Security components
|
||||
│ │ ├── file-upload-security.tsx
|
||||
│ │ ├── virus-scan-status.tsx
|
||||
│ │ └── security-audit-log.tsx
|
||||
│ ├── json-details/ # NEW: JSON Details management
|
||||
│ │ ├── json-details-form.tsx
|
||||
│ │ ├── schema-validator.tsx
|
||||
│ │ └── dynamic-form-generator.tsx
|
||||
│ ├── routing/ # NEW: Correspondence routing
|
||||
│ │ ├── routing-template-manager.tsx
|
||||
│ │ ├── routing-workflow-visualizer.tsx
|
||||
│ └── pending-routings-list.tsx
|
||||
│ └── monitoring/ # NEW: Performance monitoring
|
||||
│ ├── performance-metrics.tsx
|
||||
│ ├── real-time-monitor.tsx
|
||||
│ └── cache-status.tsx
|
||||
└── layouts/ # Layout components
|
||||
lib/
|
||||
├── api/ # API client & hooks
|
||||
├── stores/ # Zustand stores
|
||||
├── utils/ # Utility functions
|
||||
├── hooks/ # Custom hooks
|
||||
├── types/ # TypeScript types
|
||||
├── security/ # NEW: Security utilities
|
||||
│ ├── file-scanner.ts
|
||||
│ ├── virus-scan-client.ts
|
||||
│ └── security-headers.ts
|
||||
├── json-schemas/ # NEW: JSON schema management
|
||||
│ ├── schemas/
|
||||
│ ├── validators/
|
||||
│ └── transformers/
|
||||
└── monitoring/ # NEW: Monitoring utilities
|
||||
│ ├── performance.ts
|
||||
│ ├── error-tracking.ts
|
||||
│ └── metrics-collector.ts
|
||||
public/
|
||||
├── images/
|
||||
└── fonts/
|
||||
```
|
||||
```tree
|
||||
app/
|
||||
├── (public)/ # Public routes (Landing, Login)
|
||||
│ ├── page.tsx # Landing Page
|
||||
│ └── login/ # Login Page
|
||||
├── (protected)/ # Protected routes
|
||||
│ ├── layout.tsx # App Shell (Navbar + Sidebar)
|
||||
│ ├── dashboard/ # Dashboard
|
||||
│ ├── correspondences/ # Correspondence Management
|
||||
│ ├── rfas/ # RFA Management
|
||||
│ ├── drawings/ # Drawing Management
|
||||
│ ├── circulations/ # Circulation Management
|
||||
│ ├── transmittals/ # Transmittal Management
|
||||
│ ├── search/ # Advanced Search
|
||||
│ ├── reports/ # Reports
|
||||
│ ├── admin/ # Admin Panel
|
||||
│ └── profile/ # User Profile
|
||||
├── api/ # API Routes (if needed)
|
||||
components/
|
||||
├── ui/ # shadcn/ui components
|
||||
├── features/ # Feature-specific components
|
||||
│ ├── auth/
|
||||
│ ├── correspondence/
|
||||
│ ├── rfa/
|
||||
│ ├── drawing/
|
||||
│ ├── circulation/
|
||||
│ ├── common/
|
||||
│ ├── security/ # NEW: Security components
|
||||
│ │ ├── file-upload-security.tsx
|
||||
│ │ ├── virus-scan-status.tsx
|
||||
│ │ └── security-audit-log.tsx
|
||||
│ ├── json-details/ # NEW: JSON Details management
|
||||
│ │ ├── json-details-form.tsx
|
||||
│ │ ├── schema-validator.tsx
|
||||
│ │ └── dynamic-form-generator.tsx
|
||||
│ ├── routing/ # NEW: Correspondence routing
|
||||
│ │ ├── routing-template-manager.tsx
|
||||
│ │ ├── routing-workflow-visualizer.tsx
|
||||
│ └── pending-routings-list.tsx
|
||||
│ └── monitoring/ # NEW: Performance monitoring
|
||||
│ ├── performance-metrics.tsx
|
||||
│ ├── real-time-monitor.tsx
|
||||
│ └── cache-status.tsx
|
||||
└── layouts/ # Layout components
|
||||
lib/
|
||||
├── api/ # API client & hooks
|
||||
├── stores/ # Zustand stores
|
||||
├── utils/ # Utility functions
|
||||
├── hooks/ # Custom hooks
|
||||
├── types/ # TypeScript types
|
||||
├── security/ # NEW: Security utilities
|
||||
│ ├── file-scanner.ts
|
||||
│ ├── virus-scan-client.ts
|
||||
│ └── security-headers.ts
|
||||
├── json-schemas/ # NEW: JSON schema management
|
||||
│ ├── schemas/
|
||||
│ ├── validators/
|
||||
│ └── transformers/
|
||||
└── monitoring/ # NEW: Monitoring utilities
|
||||
│ ├── performance.ts
|
||||
│ ├── error-tracking.ts
|
||||
│ └── metrics-collector.ts
|
||||
public/
|
||||
├── images/
|
||||
└── fonts/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
@@ -111,7 +111,6 @@
|
||||
**Milestone:** สร้างโครงสร้างพื้นฐานและ Development Environment
|
||||
|
||||
- **T0.1 Initialize Next.js Project**
|
||||
|
||||
- สร้างโปรเจกต์ด้วย create-next-app:
|
||||
|
||||
```bash
|
||||
@@ -123,56 +122,56 @@
|
||||
- ✅ ESLint
|
||||
- ✅ Tailwind CSS
|
||||
- ✅ App Router
|
||||
- ✅ Import alias (@/*)
|
||||
- ✅ Import alias (@/\*)
|
||||
- Setup .gitignore, README.md
|
||||
- Deliverable: ✅ โปรเจกต์เริ่มต้นพร้อม
|
||||
|
||||
- **T0.2 Install Core Dependencies**
|
||||
|
||||
```bash
|
||||
# State Management & Data Fetching
|
||||
npm install @tanstack/react-query zustand
|
||||
npm install axios
|
||||
npm install react-hook-form @hookform/resolvers zod
|
||||
```bash
|
||||
# State Management & Data Fetching
|
||||
npm install @tanstack/react-query zustand
|
||||
npm install axios
|
||||
npm install react-hook-form @hookform/resolvers zod
|
||||
|
||||
# UI Components & Styling
|
||||
npm install clsx tailwind-merge
|
||||
npm install lucide-react
|
||||
npm install date-fns
|
||||
# UI Components & Styling
|
||||
npm install clsx tailwind-merge
|
||||
npm install lucide-react
|
||||
npm install date-fns
|
||||
|
||||
# File Upload
|
||||
npm install react-dropzone
|
||||
# File Upload
|
||||
npm install react-dropzone
|
||||
|
||||
# Authentication
|
||||
npm install next-auth
|
||||
# Authentication
|
||||
npm install next-auth
|
||||
|
||||
# Development Tools
|
||||
npm install -D @types/node
|
||||
# Development Tools
|
||||
npm install -D @types/node
|
||||
|
||||
# Security & File Processing
|
||||
npm install clamscan js-file-download
|
||||
npm install dompurify @types/dompurify
|
||||
# Security & File Processing
|
||||
npm install clamscan js-file-download
|
||||
npm install dompurify @types/dompurify
|
||||
|
||||
# JSON Schema & Validation
|
||||
npm install ajv ajv-formats
|
||||
npm install jsonpath json-schema-ref-parser
|
||||
# JSON Schema & Validation
|
||||
npm install ajv ajv-formats
|
||||
npm install jsonpath json-schema-ref-parser
|
||||
|
||||
# Performance Monitoring
|
||||
npm install web-vitals
|
||||
npm install @axe-core/react
|
||||
# Performance Monitoring
|
||||
npm install web-vitals
|
||||
npm install @axe-core/react
|
||||
|
||||
# Advanced UI Components
|
||||
npm install react-json-view-lite
|
||||
npm install react-window # สำหรับ Virtual Scrolling
|
||||
```
|
||||
# Advanced UI Components
|
||||
npm install react-json-view-lite
|
||||
npm install react-window # สำหรับ Virtual Scrolling
|
||||
```
|
||||
|
||||
- Deliverable: ✅ Dependencies ติดตั้งสมบูรณ์
|
||||
|
||||
- **T0.3 Setup shadcn/ui**
|
||||
|
||||
```bash
|
||||
npx shadcn-ui@latest init
|
||||
```
|
||||
```bash
|
||||
npx shadcn-ui@latest init
|
||||
```
|
||||
|
||||
- เลือก Style: Default
|
||||
- เลือก Base Color: Slate
|
||||
@@ -278,7 +277,7 @@
|
||||
'use client';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { useState } from 'react';
|
||||
|
||||
|
||||
export function Providers({ children }: { children: React.ReactNode }) {
|
||||
const [queryClient] = useState(() => new QueryClient({
|
||||
defaultOptions: {
|
||||
@@ -288,7 +287,7 @@
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
return (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
{children}
|
||||
@@ -307,7 +306,7 @@
|
||||
```typescript
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
|
||||
interface User {
|
||||
user_id: number;
|
||||
username: string;
|
||||
@@ -317,7 +316,7 @@
|
||||
primary_organization_id: number;
|
||||
permissions: string[];
|
||||
}
|
||||
|
||||
|
||||
interface AuthStore {
|
||||
user: User | null;
|
||||
token: string | null;
|
||||
@@ -325,7 +324,7 @@
|
||||
clearAuth: () => void;
|
||||
hasPermission: (permission: string) => boolean;
|
||||
}
|
||||
|
||||
|
||||
export const useAuthStore = create<AuthStore>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
@@ -367,19 +366,19 @@
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { useAuthStore } from '@/lib/stores/auth-store';
|
||||
import { apiClient } from '@/lib/api/client';
|
||||
|
||||
|
||||
const loginSchema = z.object({
|
||||
username: z.string().min(1, 'กรุณากรอกชื่อผู้ใช้'),
|
||||
password: z.string().min(1, 'กรุณากรอกรหัสผ่าน'),
|
||||
});
|
||||
|
||||
|
||||
export default function LoginPage() {
|
||||
const router = useRouter();
|
||||
const setAuth = useAuthStore((state) => state.setAuth);
|
||||
const form = useForm({
|
||||
resolver: zodResolver(loginSchema),
|
||||
});
|
||||
|
||||
|
||||
const handleLogin = async (data: z.infer<typeof loginSchema>) => {
|
||||
try {
|
||||
const response = await apiClient.post('/auth/login', data);
|
||||
@@ -391,7 +390,7 @@
|
||||
// แสดง Toast Error
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return (
|
||||
<div className="flex min-h-screen items-center justify-center">
|
||||
<form onSubmit={form.handleSubmit(handleLogin)} className="w-96">
|
||||
@@ -424,19 +423,19 @@
|
||||
import { useAuthStore } from '@/lib/stores/auth-store';
|
||||
import Navbar from '@/components/layouts/navbar';
|
||||
import Sidebar from '@/components/layouts/sidebar';
|
||||
|
||||
|
||||
export default function ProtectedLayout({ children }: { children: React.ReactNode }) {
|
||||
const router = useRouter();
|
||||
const user = useAuthStore((state) => state.user);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!user) {
|
||||
router.push('/login');
|
||||
}
|
||||
}, [user, router]);
|
||||
|
||||
|
||||
if (!user) return null;
|
||||
|
||||
|
||||
return (
|
||||
<div className="flex h-screen">
|
||||
<Sidebar />
|
||||
@@ -490,62 +489,66 @@
|
||||
|
||||
```typescript
|
||||
|
||||
```
|
||||
|
||||
// สร้าง lib/error-handling/global-error-handler.ts
|
||||
export class GlobalErrorHandler {
|
||||
static setup() {
|
||||
// API Error Interceptors
|
||||
apiClient.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
this.handleApiError(error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
static setup() {
|
||||
// API Error Interceptors
|
||||
apiClient.interceptors.response.use(
|
||||
(response) => response,
|
||||
(error) => {
|
||||
this.handleApiError(error);
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
// Frontend Error Boundary
|
||||
window.addEventListener('error', this.handleWindowError);
|
||||
window.addEventListener('unhandledrejection', this.handlePromiseRejection);
|
||||
}
|
||||
|
||||
static handleApiError(error: any) {
|
||||
// Circuit Breaker Pattern
|
||||
if (error.response?.status >= 500) {
|
||||
this.circuitBreaker.recordFailure();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static handleApiError(error: any) {
|
||||
// Circuit Breaker Pattern
|
||||
if (error.response?.status >= 500) {
|
||||
this.circuitBreaker.recordFailure();
|
||||
}
|
||||
|
||||
// User-friendly Error Messages
|
||||
const userMessage = this.getUserFriendlyMessage(error);
|
||||
this.showErrorToast(userMessage);
|
||||
|
||||
|
||||
// Error Reporting
|
||||
this.reportErrorToService(error);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
````
|
||||
|
||||
T1.10 Setup Security Foundation
|
||||
|
||||
```typescript
|
||||
```typescript
|
||||
// สร้าง lib/security/security-config.ts
|
||||
export const SecurityConfig = {
|
||||
fileUpload: {
|
||||
allowedTypes: ['pdf', 'dwg', 'docx', 'xlsx', 'zip'],
|
||||
maxSize: 50 * 1024 * 1024, // 50MB
|
||||
virusScanRequired: true,
|
||||
scanTimeout: 30000 // 30 seconds
|
||||
},
|
||||
rateLimiting: {
|
||||
maxRequests: {
|
||||
anonymous: 100,
|
||||
viewer: 500,
|
||||
editor: 1000,
|
||||
documentControl: 2000,
|
||||
admin: 5000
|
||||
}
|
||||
fileUpload: {
|
||||
allowedTypes: ['pdf', 'dwg', 'docx', 'xlsx', 'zip'],
|
||||
maxSize: 50 * 1024 * 1024, // 50MB
|
||||
virusScanRequired: true,
|
||||
scanTimeout: 30000 // 30 seconds
|
||||
},
|
||||
rateLimiting: {
|
||||
maxRequests: {
|
||||
anonymous: 100,
|
||||
viewer: 500,
|
||||
editor: 1000,
|
||||
documentControl: 2000,
|
||||
admin: 5000
|
||||
}
|
||||
}
|
||||
};
|
||||
```
|
||||
````
|
||||
|
||||
---
|
||||
|
||||
@@ -596,7 +599,7 @@ export const SecurityConfig = {
|
||||
```typescript
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { apiClient } from '../client';
|
||||
|
||||
|
||||
export function useMyTasks() {
|
||||
return useQuery({
|
||||
queryKey: ['my-tasks'],
|
||||
@@ -783,16 +786,16 @@ export const SecurityConfig = {
|
||||
```typescript
|
||||
import { useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
import { apiClient } from '../client';
|
||||
|
||||
|
||||
export function useCompleteWorkflowStep() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
|
||||
return useMutation({
|
||||
mutationFn: async ({ rfaId, stepNumber, action, comments }) => {
|
||||
const response = await apiClient.post(
|
||||
`/rfas/${rfaId}/workflow/steps/${stepNumber}/complete`,
|
||||
{ action, comments }
|
||||
);
|
||||
const response = await apiClient.post(`/rfas/${rfaId}/workflow/steps/${stepNumber}/complete`, {
|
||||
action,
|
||||
comments,
|
||||
});
|
||||
return response.data;
|
||||
},
|
||||
onSuccess: (_, variables) => {
|
||||
@@ -1051,7 +1054,7 @@ export const SecurityConfig = {
|
||||
```typescript
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { apiClient } from '../client';
|
||||
|
||||
|
||||
interface SearchFilters {
|
||||
q?: string;
|
||||
types?: string[];
|
||||
@@ -1063,7 +1066,7 @@ export const SecurityConfig = {
|
||||
page?: number;
|
||||
pageSize?: number;
|
||||
}
|
||||
|
||||
|
||||
export function useSearch(filters: SearchFilters) {
|
||||
return useQuery({
|
||||
queryKey: ['search', filters],
|
||||
@@ -1422,6 +1425,7 @@ npm install recharts
|
||||
|
||||
- ลบ Dependencies ที่ไม่ใช้
|
||||
- Tree Shaking
|
||||
|
||||
- Deliverable: ✅ Performance Metrics ดีขึ้น
|
||||
|
||||
- **T10.6 Accessibility (a11y) Testing**
|
||||
@@ -1545,6 +1549,7 @@ npm install recharts
|
||||
|
||||
- ตรวจสอบ Build Output
|
||||
- แก้ไข Build Errors/Warnings
|
||||
|
||||
- **Environment Variables**:
|
||||
- สร้างไฟล์ `.env.production`
|
||||
- กำหนดค่าใน docker-compose.yml:
|
||||
@@ -1564,6 +1569,7 @@ npm install recharts
|
||||
```
|
||||
|
||||
- Test Image Locally
|
||||
|
||||
- Deliverable: ✅ Production Build พร้อม
|
||||
|
||||
- **T11.5 Deploy to QNAP**
|
||||
@@ -1577,6 +1583,7 @@ npm install recharts
|
||||
|
||||
- Upload ผ่าน QNAP File Station
|
||||
- Import ใน Container Station
|
||||
|
||||
- **Update docker-compose.yml** บน QNAP:
|
||||
|
||||
```yaml
|
||||
@@ -1664,8 +1671,8 @@ npm install recharts
|
||||
|
||||
## 📊 สรุป Timeline
|
||||
|
||||
| Phase | ระยะเวลา | จำนวนงาน | Output หลัก |
|
||||
| -------- | ------------ | ------------ | ----------------------------- |
|
||||
| Phase | ระยะเวลา | จำนวนงาน | Output หลัก |
|
||||
| -------- | -------------- | ------------ | ----------------------------- |
|
||||
| Phase 0 | 1 สัปดาห์ | 6 | Infrastructure Ready |
|
||||
| Phase 1 | 2 สัปดาห์ | 8 | Auth & App Shell |
|
||||
| Phase 2 | 1 สัปดาห์ | 3 | Dashboard & Components |
|
||||
@@ -1850,11 +1857,11 @@ Unit Tests (60%) <- Vitest
|
||||
|
||||
```typescript
|
||||
const breakpoints = {
|
||||
sm: '640px', // Mobile Landscape
|
||||
md: '768px', // Tablet Portrait
|
||||
lg: '1024px', // Tablet Landscape / Desktop
|
||||
xl: '1280px', // Desktop
|
||||
'2xl': '1536px' // Large Desktop
|
||||
sm: '640px', // Mobile Landscape
|
||||
md: '768px', // Tablet Portrait
|
||||
lg: '1024px', // Tablet Landscape / Desktop
|
||||
xl: '1280px', // Desktop
|
||||
'2xl': '1536px', // Large Desktop
|
||||
};
|
||||
```
|
||||
|
||||
@@ -1866,16 +1873,14 @@ const breakpoints = {
|
||||
// Desktop: Fixed Sidebar
|
||||
// Mobile: Collapsible (Hamburger Menu)
|
||||
|
||||
<aside className="hidden lg:block w-64 bg-gray-50">
|
||||
{/* Sidebar Content */}
|
||||
</aside>
|
||||
<aside className="hidden lg:block w-64 bg-gray-50">{/* Sidebar Content */}</aside>;
|
||||
|
||||
{/* Mobile Sidebar (Sheet) */}
|
||||
{
|
||||
/* Mobile Sidebar (Sheet) */
|
||||
}
|
||||
<Sheet open={isMobileMenuOpen} onOpenChange={setIsMobileMenuOpen}>
|
||||
<SheetContent side="left">
|
||||
{/* Sidebar Content */}
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
<SheetContent side="left">{/* Sidebar Content */}</SheetContent>
|
||||
</Sheet>;
|
||||
```
|
||||
|
||||
**DataTable:**
|
||||
@@ -1949,13 +1954,13 @@ module.exports = {
|
||||
|
||||
```typescript
|
||||
const typography = {
|
||||
h1: 'text-4xl font-bold', // Headings
|
||||
h1: 'text-4xl font-bold', // Headings
|
||||
h2: 'text-3xl font-bold',
|
||||
h3: 'text-2xl font-semibold',
|
||||
h4: 'text-xl font-semibold',
|
||||
body: 'text-base', // Body Text
|
||||
small: 'text-sm', // Helper Text
|
||||
xs: 'text-xs', // Captions
|
||||
body: 'text-base', // Body Text
|
||||
small: 'text-sm', // Helper Text
|
||||
xs: 'text-xs', // Captions
|
||||
};
|
||||
```
|
||||
|
||||
@@ -2076,13 +2081,10 @@ const formSchema = z.object({
|
||||
// ✅ Dynamic Import สำหรับ Heavy Components
|
||||
import dynamic from 'next/dynamic';
|
||||
|
||||
const WorkflowVisualizer = dynamic(
|
||||
() => import('@/components/features/rfa/workflow-visualizer'),
|
||||
{
|
||||
loading: () => <Skeleton className="h-96" />,
|
||||
ssr: false // ถ้าไม่ต้องการ SSR
|
||||
}
|
||||
);
|
||||
const WorkflowVisualizer = dynamic(() => import('@/components/features/rfa/workflow-visualizer'), {
|
||||
loading: () => <Skeleton className="h-96" />,
|
||||
ssr: false, // ถ้าไม่ต้องการ SSR
|
||||
});
|
||||
```
|
||||
|
||||
### 2. Image Optimization
|
||||
@@ -2097,7 +2099,7 @@ import Image from 'next/image';
|
||||
width={200}
|
||||
height={50}
|
||||
priority // สำหรับรูปสำคัญ (Above the fold)
|
||||
/>
|
||||
/>;
|
||||
```
|
||||
|
||||
### 3. Data Fetching Optimization
|
||||
@@ -2151,7 +2153,7 @@ const virtualizer = useVirtualizer({
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>;
|
||||
```
|
||||
|
||||
---
|
||||
@@ -2234,16 +2236,16 @@ const nextConfig = {
|
||||
output: 'standalone', // สำหรับ Docker
|
||||
reactStrictMode: true,
|
||||
swcMinify: true, // ใช้ SWC แทน Terser (เร็วกว่า)
|
||||
|
||||
|
||||
// Image Optimization
|
||||
images: {
|
||||
domains: ['backend.np-dms.work'], // ถ้ามี Image จาก Backend
|
||||
formats: ['image/webp'],
|
||||
},
|
||||
|
||||
|
||||
// Compression
|
||||
compress: true,
|
||||
|
||||
|
||||
// Security Headers
|
||||
async headers() {
|
||||
return [
|
||||
@@ -2284,14 +2286,14 @@ services:
|
||||
environment:
|
||||
# Public (ถูก Replace ตอน Build)
|
||||
- NEXT_PUBLIC_API_URL=https://backend.np-dms.work/api
|
||||
|
||||
|
||||
# Server-side Only
|
||||
- NEXTAUTH_URL=https://lcbp3.np-dms.work
|
||||
- NEXTAUTH_SECRET=${NEXTAUTH_SECRET}
|
||||
- DATABASE_URL=mysql://user:pass@mariadb:3306/dms_db
|
||||
restart: unless-stopped
|
||||
healthcheck:
|
||||
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:3000/api/health"]
|
||||
test: ['CMD', 'wget', '--quiet', '--tries=1', '--spider', 'http://localhost:3000/api/health']
|
||||
interval: 30s
|
||||
timeout: 10s
|
||||
retries: 3
|
||||
@@ -2420,13 +2422,13 @@ export function setupErrorTracking() {
|
||||
|
||||
### User Metrics
|
||||
|
||||
| Metric | Target | Measurement |
|
||||
| -------------------- | ------------------ | ------------ |
|
||||
| Metric | Target | Measurement |
|
||||
| -------------------- | ------------------- | ------------ |
|
||||
| User Adoption | 90% (ภายใน 3 เดือน) | Analytics |
|
||||
| Daily Active Users | 50+ | Analytics |
|
||||
| Task Completion Rate | > 85% | User Testing |
|
||||
| User Satisfaction | > 4.0/5.0 | Survey |
|
||||
| Support Tickets | < 10/week | Helpdesk |
|
||||
| Daily Active Users | 50+ | Analytics |
|
||||
| Task Completion Rate | > 85% | User Testing |
|
||||
| User Satisfaction | > 4.0/5.0 | Survey |
|
||||
| Support Tickets | < 10/week | Helpdesk |
|
||||
|
||||
---
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
# 📝 **Documents Management System Version 1.4.1: Application Requirements Specification (ปรับปรุงโดย deepseek)**
|
||||
|
||||
**ปรับปรุงตามการ review และข้อเสนอแนะล่าสุด*
|
||||
\*_ปรับปรุงตามการ review และข้อเสนอแนะล่าสุด_
|
||||
|
||||
## 📌**1. วัตถุประสงค์**
|
||||
|
||||
@@ -233,21 +233,7 @@
|
||||
- รองรับการขยายตัวของระบบโดยไม่ต้องเปลี่ยนแปลง database schema
|
||||
- จัดการ metadata และข้อมูลประกอบสำหรับ correspondence, routing, และ workflows
|
||||
- **3.11.2 โครงสร้าง JSON Schema**
|
||||
ระบบต้องมี predefined JSON schemas สำหรับประเภทเอกสารต่างๆ:
|
||||
- **3.11.2.1 Correspondence Types**
|
||||
- **GENERIC**: ข้อมูลพื้นฐานสำหรับเอกสารทั่วไป
|
||||
- **RFI**: รายละเอียดคำถามและข้อมูลทางเทคนิค
|
||||
- **RFA**: ข้อมูลการขออนุมัติแบบและวัสดุ
|
||||
- **TRANSMITTAL**: รายการเอกสารที่ส่งต่อ
|
||||
- **LETTER**: ข้อมูลจดหมายทางการ
|
||||
- **EMAIL**: ข้อมูลอีเมล
|
||||
- **3.11.2.2 Routing Types**
|
||||
- **ROUTING_TEMPLATE**: กฎและเงื่อนไขการส่งต่อ
|
||||
- **ROUTING_INSTANCE**: สถานะและประวัติการส่งต่อ
|
||||
- **ROUTING_ACTION**: การดำเนินการในแต่ละขั้นตอน
|
||||
- **3.11.2.3 Audit Types**
|
||||
- **AUDIT_LOG**: ข้อมูลการตรวจสอบ
|
||||
- **SECURITY_SCAN**: ผลการตรวจสอบความปลอดภัย
|
||||
ระบบต้องมี predefined JSON schemas สำหรับประเภทเอกสารต่างๆ: - **3.11.2.1 Correspondence Types** - **GENERIC**: ข้อมูลพื้นฐานสำหรับเอกสารทั่วไป - **RFI**: รายละเอียดคำถามและข้อมูลทางเทคนิค - **RFA**: ข้อมูลการขออนุมัติแบบและวัสดุ - **TRANSMITTAL**: รายการเอกสารที่ส่งต่อ - **LETTER**: ข้อมูลจดหมายทางการ - **EMAIL**: ข้อมูลอีเมล - **3.11.2.2 Routing Types** - **ROUTING_TEMPLATE**: กฎและเงื่อนไขการส่งต่อ - **ROUTING_INSTANCE**: สถานะและประวัติการส่งต่อ - **ROUTING_ACTION**: การดำเนินการในแต่ละขั้นตอน - **3.11.2.3 Audit Types** - **AUDIT_LOG**: ข้อมูลการตรวจสอบ - **SECURITY_SCAN**: ผลการตรวจสอบความปลอดภัย
|
||||
- **3.11.3 Validation Rules**
|
||||
- ต้องมี JSON schema validation สำหรับแต่ละประเภท
|
||||
- ต้องรองรับ versioning ของ schema
|
||||
@@ -367,7 +353,6 @@
|
||||
- **6.3. การทำรายงาน (Reporting):** สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
|
||||
|
||||
- **6.4. ประสิทธิภาพ (Performance):** มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
|
||||
- **6.4.1 ตัวชี้วัดประสิทธิภาพ:**
|
||||
- **API Response Time:** < 200ms (90th percentile) สำหรับ operation ทั่วไป
|
||||
- **Search Query Performance:** < 500ms สำหรับการค้นหาขั้นสูง
|
||||
@@ -661,7 +646,7 @@
|
||||
|
||||
## **Document Control:**
|
||||
|
||||
- Document for Application Requirements Specification DMS v1.4.1
|
||||
- Document for Application Requirements Specification DMS v1.4.1
|
||||
- Version: 1.4.1
|
||||
- Date: 2025-11-16
|
||||
- Author: System Architecture Team
|
||||
@@ -670,4 +655,4 @@
|
||||
|
||||
---
|
||||
|
||||
_End of Requirements Specification
|
||||
\_End of Requirements Specification
|
||||
|
||||
@@ -1,54 +1,54 @@
|
||||
# 📝 **LCBP3-DMS Documents Management System Version 1.4.2: Application Requirements Specification (by DeepSeek)**
|
||||
|
||||
* **ปรับปรุงตามข้อเสนอแนะจาก FullStackJS Guidelines และแผนการพัฒนา**
|
||||
- **ปรับปรุงตามข้อเสนอแนะจาก FullStackJS Guidelines และแผนการพัฒนา**
|
||||
|
||||
## 📌 **1. วัตถุประสงค์**
|
||||
|
||||
สร้างเว็บแอปพลิเคชั่นสำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System) ที่สามารถจัดการและควบคุม การสื่อสารด้วยเอกสารที่ซับซ้อน อย่างมีประสิทธิภาพ
|
||||
|
||||
* มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
* ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
* เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
* **เสริม:** ปรับปรุงความปลอดภัยของระบบด้วยมาตรการป้องกันที่ทันสมัย
|
||||
* **เสริม:** เพิ่มความทนทานของระบบด้วยกลไก resilience patterns
|
||||
* **เสริม:** สร้างระบบ monitoring และ observability ที่ครอบคลุม
|
||||
- มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
- ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
- เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
- **เสริม:** ปรับปรุงความปลอดภัยของระบบด้วยมาตรการป้องกันที่ทันสมัย
|
||||
- **เสริม:** เพิ่มความทนทานของระบบด้วยกลไก resilience patterns
|
||||
- **เสริม:** สร้างระบบ monitoring และ observability ที่ครอบคลุม
|
||||
|
||||
## 🛠️ **2. สถาปัตยกรรมและเทคโนโลยี (System Architecture & Technology Stack)**
|
||||
|
||||
### **2.1 Infrastructure & Environment:**
|
||||
|
||||
* **Server:** QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
* **Containerization:** Container Station (Docker & Docker Compose)
|
||||
* **Domain:** np-dms.work, <www.np-dms.work>
|
||||
* **IP:** 159.192.126.103
|
||||
* **Docker Network:** ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3
|
||||
* **Data Storage:** /share/dms-data บน QNAP
|
||||
* **ข้อจำกัด:** ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
- **Server:** QNAP (Model: TS-473A, RAM: 32GB, CPU: AMD Ryzen V1500B)
|
||||
- **Containerization:** Container Station (Docker & Docker Compose)
|
||||
- **Domain:** np-dms.work, <www.np-dms.work>
|
||||
- **IP:** 159.192.126.103
|
||||
- **Docker Network:** ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3
|
||||
- **Data Storage:** /share/dms-data บน QNAP
|
||||
- **ข้อจำกัด:** ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
|
||||
### **2.2 Technology Stack:**
|
||||
|
||||
* Backend:
|
||||
* framework: NestJS (TypeScript, ESM)
|
||||
* database: MariaDB 10.11
|
||||
* orm: TypeORM
|
||||
* auth: JWT + Passport + CASL
|
||||
* fileProcessing: Multer + ClamAV
|
||||
* search: Elasticsearch
|
||||
* caching: Redis
|
||||
* resilience: Circuit Breaker, Retry Patterns
|
||||
- Backend:
|
||||
- framework: NestJS (TypeScript, ESM)
|
||||
- database: MariaDB 10.11
|
||||
- orm: TypeORM
|
||||
- auth: JWT + Passport + CASL
|
||||
- fileProcessing: Multer + ClamAV
|
||||
- search: Elasticsearch
|
||||
- caching: Redis
|
||||
- resilience: Circuit Breaker, Retry Patterns
|
||||
|
||||
* frontend:
|
||||
* framework: Next.js 14 (App Router, React, TypeScript, ESM)
|
||||
* styling: Tailwind CSS + PostCSS
|
||||
* components: shadcn/ui + Radix UI
|
||||
* stateManagement: Zustand + TanStack Query
|
||||
* forms: React Hook Form + Zod
|
||||
- frontend:
|
||||
- framework: Next.js 14 (App Router, React, TypeScript, ESM)
|
||||
- styling: Tailwind CSS + PostCSS
|
||||
- components: shadcn/ui + Radix UI
|
||||
- stateManagement: Zustand + TanStack Query
|
||||
- forms: React Hook Form + Zod
|
||||
|
||||
* infrastructure:
|
||||
* reverseProxy: Nginx Proxy Manager
|
||||
* containerization: Docker + Docker Compose
|
||||
* monitoring: Winston + Health Checks
|
||||
* workflow: n8n
|
||||
- infrastructure:
|
||||
- reverseProxy: Nginx Proxy Manager
|
||||
- containerization: Docker + Docker Compose
|
||||
- monitoring: Winston + Health Checks
|
||||
- workflow: n8n
|
||||
|
||||
### **2.3 Performance Targets:**
|
||||
|
||||
@@ -58,22 +58,22 @@ const PERFORMANCE_TARGETS = {
|
||||
responseTime: '< 200ms (90th percentile)',
|
||||
searchPerformance: '< 500ms',
|
||||
concurrentUsers: '100 users',
|
||||
errorRate: '< 1%'
|
||||
errorRate: '< 1%',
|
||||
},
|
||||
frontend: {
|
||||
firstContentfulPaint: '< 1.5s',
|
||||
largestContentfulPaint: '< 2.5s',
|
||||
bundleSize: '< 500KB (gzipped)'
|
||||
bundleSize: '< 500KB (gzipped)',
|
||||
},
|
||||
database: {
|
||||
queryTime: '< 100ms (p95)',
|
||||
connectionPool: '20-50 connections'
|
||||
connectionPool: '20-50 connections',
|
||||
},
|
||||
files: {
|
||||
uploadTime: '< 30s (50MB files)',
|
||||
downloadTime: '< 5s (50MB files)',
|
||||
virusScanTime: '< 10s'
|
||||
}
|
||||
virusScanTime: '< 10s',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -114,17 +114,17 @@ interface RFIDetails extends BaseDetails {
|
||||
|
||||
### **3.2 Enhanced Document Management:**
|
||||
|
||||
* **3.2.1** ระบบต้องรองรับการจัดการเอกสารแบบ Real-time Collaboration
|
||||
* **3.2.2** ต้องมีระบบ Version Control ที่ชัดเจนสำหรับทุกเอกสาร
|
||||
* **3.2.3** รองรับการค้นหา Full-text Search ผ่าน Elasticsearch
|
||||
* **3.2.4** ระบบต้องรองรับ Bulk Operations สำหรับการจัดการเอกสารจำนวนมาก
|
||||
- **3.2.1** ระบบต้องรองรับการจัดการเอกสารแบบ Real-time Collaboration
|
||||
- **3.2.2** ต้องมีระบบ Version Control ที่ชัดเจนสำหรับทุกเอกสาร
|
||||
- **3.2.3** รองรับการค้นหา Full-text Search ผ่าน Elasticsearch
|
||||
- **3.2.4** ระบบต้องรองรับ Bulk Operations สำหรับการจัดการเอกสารจำนวนมาก
|
||||
|
||||
### **3.3 Advanced Workflow Management:**
|
||||
|
||||
* **3.3.1** รองรับ Conditional Workflow Routing ตาม business rules
|
||||
* **3.3.2** ระบบต้องมี Escalation Mechanisms สำหรับงานที่เลยกำหนด
|
||||
* **3.3.3** รองรับ Parallel Workflow Steps เมื่อเหมาะสม
|
||||
* **3.3.4** ต้องมีระบบ Notification Preferences สำหรับผู้ใช้
|
||||
- **3.3.1** รองรับ Conditional Workflow Routing ตาม business rules
|
||||
- **3.3.2** ระบบต้องมี Escalation Mechanisms สำหรับงานที่เลยกำหนด
|
||||
- **3.3.3** รองรับ Parallel Workflow Steps เมื่อเหมาะสม
|
||||
- **3.3.4** ต้องมีระบบ Notification Preferences สำหรับผู้ใช้
|
||||
|
||||
## 🔐 **4. ข้อกำหนดด้านสิทธิ์และการเข้าถึง (Access Control Requirements)**
|
||||
|
||||
@@ -137,17 +137,17 @@ const PERMISSION_HIERARCHY = {
|
||||
features: {
|
||||
dynamicRoles: 'Admin สามารถสร้างบทบาทใหม่ได้',
|
||||
permissionTemplates: 'ใช้ template สำหรับบทบาทมาตรฐาน',
|
||||
timeBoundPermissions: 'สิทธิ์ชั่วคราวตามระยะเวลา'
|
||||
}
|
||||
timeBoundPermissions: 'สิทธิ์ชั่วคราวตามระยะเวลา',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### **4.2 Advanced Security Controls:**
|
||||
|
||||
* **4.2.1** ต้องมี Session Management ที่ปลอดภัย
|
||||
* **4.2.2** รองรับ Multi-factor Authentication (MFA)
|
||||
* **4.2.3** ต้องมีระบบ Audit Trail ที่ครอบคลุม
|
||||
* **4.2.4** รองรับ Security Policy Enforcement
|
||||
- **4.2.1** ต้องมี Session Management ที่ปลอดภัย
|
||||
- **4.2.2** รองรับ Multi-factor Authentication (MFA)
|
||||
- **4.2.3** ต้องมีระบบ Audit Trail ที่ครอบคลุม
|
||||
- **4.2.4** รองรับ Security Policy Enforcement
|
||||
|
||||
## 👥 **5. ข้อกำหนดด้านผู้ใช้งาน (User Interface & Experience)**
|
||||
|
||||
@@ -174,16 +174,16 @@ const PERMISSION_HIERARCHY = {
|
||||
const STATE_MANAGEMENT = {
|
||||
serverState: {
|
||||
tool: 'TanStack Query',
|
||||
useCases: ['API data', 'Search results', 'User profiles']
|
||||
useCases: ['API data', 'Search results', 'User profiles'],
|
||||
},
|
||||
clientState: {
|
||||
tool: 'Zustand',
|
||||
useCases: ['UI state', 'Form state', 'User preferences']
|
||||
useCases: ['UI state', 'Form state', 'User preferences'],
|
||||
},
|
||||
formState: {
|
||||
tool: 'React Hook Form + Zod',
|
||||
useCases: ['All forms', 'Validation', 'Form wizard']
|
||||
}
|
||||
useCases: ['All forms', 'Validation', 'Form wizard'],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -196,18 +196,18 @@ const PERFORMANCE_REQUIREMENTS = {
|
||||
scalability: {
|
||||
concurrentUsers: '100+ users',
|
||||
documentStorage: '10,000+ documents',
|
||||
fileStorage: '1TB+ capacity'
|
||||
fileStorage: '1TB+ capacity',
|
||||
},
|
||||
reliability: {
|
||||
uptime: '99.9%',
|
||||
backupRecovery: '4-hour RTO, 1-hour RPO',
|
||||
errorHandling: 'Graceful degradation'
|
||||
errorHandling: 'Graceful degradation',
|
||||
},
|
||||
security: {
|
||||
authentication: 'JWT with refresh tokens',
|
||||
authorization: 'RBAC with 4-level hierarchy',
|
||||
dataProtection: 'Encryption at rest and in transit'
|
||||
}
|
||||
dataProtection: 'Encryption at rest and in transit',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -215,33 +215,23 @@ const PERFORMANCE_REQUIREMENTS = {
|
||||
|
||||
```typescript
|
||||
const MONITORING_REQUIREMENTS = {
|
||||
applicationMetrics: [
|
||||
'api_response_times',
|
||||
'error_rates',
|
||||
'user_activity',
|
||||
'workflow_completion_rates'
|
||||
],
|
||||
applicationMetrics: ['api_response_times', 'error_rates', 'user_activity', 'workflow_completion_rates'],
|
||||
businessMetrics: [
|
||||
'documents_created_daily',
|
||||
'average_approval_time',
|
||||
'sla_compliance_rates',
|
||||
'user_satisfaction_scores'
|
||||
'user_satisfaction_scores',
|
||||
],
|
||||
securityMetrics: [
|
||||
'failed_login_attempts',
|
||||
'file_scan_results',
|
||||
'permission_changes',
|
||||
'security_incidents'
|
||||
]
|
||||
securityMetrics: ['failed_login_attempts', 'file_scan_results', 'permission_changes', 'security_incidents'],
|
||||
};
|
||||
```
|
||||
|
||||
### **6.3 Enhanced Security Requirements:**
|
||||
|
||||
* **6.3.1** ต้องมี Comprehensive Input Validation
|
||||
* **6.3.2** ต้องป้องกัน OWASP Top 10 vulnerabilities
|
||||
* **6.3.3** ต้องมี Rate Limiting ที่ configuraable
|
||||
* **6.3.4** ต้องมี Security Headers และ CSP
|
||||
- **6.3.1** ต้องมี Comprehensive Input Validation
|
||||
- **6.3.2** ต้องป้องกัน OWASP Top 10 vulnerabilities
|
||||
- **6.3.3** ต้องมี Rate Limiting ที่ configuraable
|
||||
- **6.3.4** ต้องมี Security Headers และ CSP
|
||||
|
||||
### **6.4 Database Optimization Requirements:**
|
||||
|
||||
@@ -250,13 +240,13 @@ const DATABASE_REQUIREMENTS = {
|
||||
performance: {
|
||||
queryOptimization: 'All queries under 100ms',
|
||||
indexingStrategy: 'Composite indexes for common queries',
|
||||
connectionPooling: '20-50 connections'
|
||||
connectionPooling: '20-50 connections',
|
||||
},
|
||||
maintenance: {
|
||||
backup: 'Daily full + hourly incremental',
|
||||
cleanup: 'Automated archive of old records',
|
||||
monitoring: 'Slow query logging and alerting'
|
||||
}
|
||||
monitoring: 'Slow query logging and alerting',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -269,28 +259,28 @@ const TESTING_STRATEGY = {
|
||||
unitTesting: {
|
||||
coverage: '80% minimum',
|
||||
focus: 'Business logic and utilities',
|
||||
tools: ['Jest', 'React Testing Library']
|
||||
tools: ['Jest', 'React Testing Library'],
|
||||
},
|
||||
integrationTesting: {
|
||||
coverage: 'Critical user journeys',
|
||||
focus: 'API endpoints and database operations',
|
||||
tools: ['Supertest', 'Testcontainers']
|
||||
tools: ['Supertest', 'Testcontainers'],
|
||||
},
|
||||
e2eTesting: {
|
||||
coverage: 'Core business workflows',
|
||||
focus: 'User registration to document approval',
|
||||
tools: ['Playwright', 'Jest']
|
||||
tools: ['Playwright', 'Jest'],
|
||||
},
|
||||
performanceTesting: {
|
||||
coverage: 'Critical paths under load',
|
||||
focus: 'API response times and concurrent users',
|
||||
tools: ['k6', 'Artillery']
|
||||
tools: ['k6', 'Artillery'],
|
||||
},
|
||||
securityTesting: {
|
||||
coverage: 'OWASP Top 10 vulnerabilities',
|
||||
focus: 'Authentication, authorization, input validation',
|
||||
tools: ['OWASP ZAP', 'Snyk']
|
||||
}
|
||||
tools: ['OWASP ZAP', 'Snyk'],
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -298,24 +288,9 @@ const TESTING_STRATEGY = {
|
||||
|
||||
```typescript
|
||||
const QUALITY_GATES = {
|
||||
preCommit: [
|
||||
'ESLint with no errors',
|
||||
'Prettier formatting',
|
||||
'TypeScript compilation',
|
||||
'Unit tests passing'
|
||||
],
|
||||
preMerge: [
|
||||
'All tests passing',
|
||||
'Code review completed',
|
||||
'Security scan clean',
|
||||
'Performance benchmarks met'
|
||||
],
|
||||
preDeploy: [
|
||||
'Integration tests passing',
|
||||
'E2E tests passing',
|
||||
'Load tests successful',
|
||||
'Security audit completed'
|
||||
]
|
||||
preCommit: ['ESLint with no errors', 'Prettier formatting', 'TypeScript compilation', 'Unit tests passing'],
|
||||
preMerge: ['All tests passing', 'Code review completed', 'Security scan clean', 'Performance benchmarks met'],
|
||||
preDeploy: ['Integration tests passing', 'E2E tests passing', 'Load tests successful', 'Security audit completed'],
|
||||
};
|
||||
```
|
||||
|
||||
@@ -328,27 +303,27 @@ const OPERATIONAL_REQUIREMENTS = {
|
||||
monitoring: {
|
||||
healthChecks: '/health, /ready, /live endpoints',
|
||||
alerting: 'Real-time alerts for critical issues',
|
||||
logging: 'Structured JSON logs with request IDs'
|
||||
logging: 'Structured JSON logs with request IDs',
|
||||
},
|
||||
backup: {
|
||||
frequency: 'Daily full + hourly incremental',
|
||||
retention: '30 days for backups, 7 years for audit logs',
|
||||
verification: 'Automated backup validation'
|
||||
verification: 'Automated backup validation',
|
||||
},
|
||||
updates: {
|
||||
securityPatches: 'Applied within 24 hours of release',
|
||||
minorUpdates: 'Monthly maintenance windows',
|
||||
majorUpdates: 'Quarterly with thorough testing'
|
||||
}
|
||||
majorUpdates: 'Quarterly with thorough testing',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### **8.2 Disaster Recovery:**
|
||||
|
||||
* **8.2.1** Recovery Time Objective (RTO): < 4 ชั่วโมง
|
||||
* **8.2.2** Recovery Point Objective (RPO): < 1 ชั่วโมง
|
||||
* **8.2.3** ต้องมี Automated Recovery Procedures
|
||||
* **8.2.4** ต้องมี Regular Disaster Recovery Testing
|
||||
- **8.2.1** Recovery Time Objective (RTO): < 4 ชั่วโมง
|
||||
- **8.2.2** Recovery Point Objective (RPO): < 1 ชั่วโมง
|
||||
- **8.2.3** ต้องมี Automated Recovery Procedures
|
||||
- **8.2.4** ต้องมี Regular Disaster Recovery Testing
|
||||
|
||||
## 👥 **9. ข้อกำหนดด้านการพัฒนา (Development Requirements)**
|
||||
|
||||
@@ -359,18 +334,18 @@ const DEVELOPMENT_WORKFLOW = {
|
||||
environmentSetup: {
|
||||
time: '30 minutes maximum',
|
||||
tools: ['Docker', 'Node.js 18+', 'VS Code'],
|
||||
commands: ['npm run setup', 'npm run dev', 'npm run test']
|
||||
commands: ['npm run setup', 'npm run dev', 'npm run test'],
|
||||
},
|
||||
gitWorkflow: {
|
||||
branching: 'Feature branches with PR reviews',
|
||||
commitConventions: 'Conventional commits',
|
||||
codeReview: '2 reviewers minimum'
|
||||
codeReview: '2 reviewers minimum',
|
||||
},
|
||||
collaboration: {
|
||||
communication: 'Daily standups, weekly planning',
|
||||
documentation: 'Auto-generated API docs, ADRs',
|
||||
knowledgeSharing: 'Pair programming, tech talks'
|
||||
}
|
||||
knowledgeSharing: 'Pair programming, tech talks',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -381,18 +356,18 @@ const CODE_QUALITY_STANDARDS = {
|
||||
backend: {
|
||||
language: 'TypeScript with strict mode',
|
||||
style: 'NestJS style guide with ESLint',
|
||||
testing: '80% coverage, Arrange-Act-Assert pattern'
|
||||
testing: '80% coverage, Arrange-Act-Assert pattern',
|
||||
},
|
||||
frontend: {
|
||||
language: 'TypeScript with strict mode',
|
||||
style: 'Next.js style guide with Prettier',
|
||||
testing: '70% coverage, React Testing Library'
|
||||
testing: '70% coverage, React Testing Library',
|
||||
},
|
||||
database: {
|
||||
naming: 'Consistent snake_case convention',
|
||||
indexing: 'Strategic indexes for performance',
|
||||
migrations: 'TypeORM migrations with rollback'
|
||||
}
|
||||
migrations: 'TypeORM migrations with rollback',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -400,10 +375,10 @@ const CODE_QUALITY_STANDARDS = {
|
||||
|
||||
### **10.1 Business Intelligence:**
|
||||
|
||||
* **10.1.1** ต้องมี Real-time Dashboard สำหรับ Key Metrics
|
||||
* **10.1.2** รองรับ Custom Reports และ Exports
|
||||
* **10.1.3** ต้องมี Predictive Analytics สำหรับ Workflow Optimization
|
||||
* **10.1.4** รองรับ Data Visualization ที่หลากหลาย
|
||||
- **10.1.1** ต้องมี Real-time Dashboard สำหรับ Key Metrics
|
||||
- **10.1.2** รองรับ Custom Reports และ Exports
|
||||
- **10.1.3** ต้องมี Predictive Analytics สำหรับ Workflow Optimization
|
||||
- **10.1.4** รองรับ Data Visualization ที่หลากหลาย
|
||||
|
||||
### **10.2 Advanced Analytics:**
|
||||
|
||||
@@ -413,19 +388,19 @@ const ANALYTICS_REQUIREMENTS = {
|
||||
'document_processing_times',
|
||||
'workflow_bottlenecks',
|
||||
'user_engagement_metrics',
|
||||
'system_utilization_rates'
|
||||
'system_utilization_rates',
|
||||
],
|
||||
businessMetrics: [
|
||||
'sla_compliance_rates',
|
||||
'document_approval_rates',
|
||||
'user_satisfaction_scores',
|
||||
'cost_savings_analytics'
|
||||
'cost_savings_analytics',
|
||||
],
|
||||
predictiveAnalytics: [
|
||||
'workflow_completion_predictions',
|
||||
'resource_utilization_forecasts',
|
||||
'capacity_planning_insights'
|
||||
]
|
||||
'capacity_planning_insights',
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
@@ -433,10 +408,10 @@ const ANALYTICS_REQUIREMENTS = {
|
||||
|
||||
### **11.1 Scalability & Extensibility:**
|
||||
|
||||
* **11.1.1** ระบบต้องรองรับ Horizontal Scaling
|
||||
* **11.1.2** ต้องมี Clean Architecture สำหรับการขยาย功能
|
||||
* **11.1.3** รองรับ Plugin Architecture สำหรับฟีเจอร์เพิ่มเติม
|
||||
* **11.1.4** ต้องมี API Versioning Strategy
|
||||
- **11.1.1** ระบบต้องรองรับ Horizontal Scaling
|
||||
- **11.1.2** ต้องมี Clean Architecture สำหรับการขยาย功能
|
||||
- **11.1.3** รองรับ Plugin Architecture สำหรับฟีเจอร์เพิ่มเติม
|
||||
- **11.1.4** ต้องมี API Versioning Strategy
|
||||
|
||||
### **11.2 Integration Capabilities:**
|
||||
|
||||
@@ -446,14 +421,14 @@ const INTEGRATION_REQUIREMENTS = {
|
||||
'LINE Messaging API',
|
||||
'Email Services (SMTP)',
|
||||
'External Storage Systems',
|
||||
'Third-party Authentication'
|
||||
'Third-party Authentication',
|
||||
],
|
||||
apiStandards: {
|
||||
rest: 'JSON API standards',
|
||||
webhooks: 'Event-driven notifications',
|
||||
webSockets: 'Real-time updates',
|
||||
graphql: 'Optional for complex queries'
|
||||
}
|
||||
graphql: 'Optional for complex queries',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -466,27 +441,27 @@ const SECURITY_FRAMEWORK = {
|
||||
authentication: {
|
||||
primary: 'JWT with refresh tokens',
|
||||
secondary: 'Multi-factor authentication ready',
|
||||
session: 'Secure session management'
|
||||
session: 'Secure session management',
|
||||
},
|
||||
authorization: {
|
||||
model: 'RBAC with 4-level hierarchy',
|
||||
enforcement: 'Attribute-based access control',
|
||||
auditing: 'Comprehensive permission logging'
|
||||
auditing: 'Comprehensive permission logging',
|
||||
},
|
||||
dataProtection: {
|
||||
encryption: 'At rest and in transit',
|
||||
masking: 'Sensitive data masking',
|
||||
retention: 'Automated data lifecycle management'
|
||||
}
|
||||
retention: 'Automated data lifecycle management',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### **12.2 Security Monitoring:**
|
||||
|
||||
* **12.2.1** ต้องมี Real-time Threat Detection
|
||||
* **12.2.2** รองรับ Security Incident Response
|
||||
* **12.2.3** ต้องมี Vulnerability Management Program
|
||||
* **12.2.4** รองรับ Compliance Auditing
|
||||
- **12.2.1** ต้องมี Real-time Threat Detection
|
||||
- **12.2.2** รองรับ Security Incident Response
|
||||
- **12.2.3** ต้องมี Vulnerability Management Program
|
||||
- **12.2.4** รองรับ Compliance Auditing
|
||||
|
||||
## 📈 **13. ข้อกำหนดด้านประสิทธิภาพขั้นสูง (Advanced Performance Requirements)**
|
||||
|
||||
@@ -497,27 +472,27 @@ const ADVANCED_PERFORMANCE_TARGETS = {
|
||||
database: {
|
||||
queryOptimization: 'All complex queries under 50ms',
|
||||
connectionManagement: 'Intelligent connection pooling',
|
||||
cachingStrategy: 'Multi-level caching architecture'
|
||||
cachingStrategy: 'Multi-level caching architecture',
|
||||
},
|
||||
application: {
|
||||
memoryManagement: 'Efficient garbage collection',
|
||||
cpuUtilization: 'Optimal resource usage',
|
||||
responseTimes: 'Progressive performance improvements'
|
||||
responseTimes: 'Progressive performance improvements',
|
||||
},
|
||||
frontend: {
|
||||
loadingOptimization: 'Lazy loading and code splitting',
|
||||
renderingPerformance: 'Optimized virtual DOM',
|
||||
assetDelivery: 'CDN and compression strategies'
|
||||
}
|
||||
assetDelivery: 'CDN and compression strategies',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### **13.2 Load Handling:**
|
||||
|
||||
* **13.2.1** ต้องรองรับ Peak Loads ได้ 3x Normal Capacity
|
||||
* **13.2.2** ต้องมี Auto-scaling Capabilities
|
||||
* **13.2.3** รองรับ Graceful Degradation
|
||||
* **13.2.4** ต้องมี Comprehensive Load Testing
|
||||
- **13.2.1** ต้องรองรับ Peak Loads ได้ 3x Normal Capacity
|
||||
- **13.2.2** ต้องมี Auto-scaling Capabilities
|
||||
- **13.2.3** รองรับ Graceful Degradation
|
||||
- **13.2.4** ต้องมี Comprehensive Load Testing
|
||||
|
||||
## 🔄 **14. ข้อกำหนดด้านการอัปเกรดและความเข้ากันได้ (Upgrade & Compatibility Requirements)**
|
||||
|
||||
@@ -528,22 +503,22 @@ const VERSION_MANAGEMENT = {
|
||||
apiVersioning: {
|
||||
strategy: 'URL versioning with backward compatibility',
|
||||
deprecation: '6-month deprecation notice',
|
||||
migration: 'Automated migration tools'
|
||||
migration: 'Automated migration tools',
|
||||
},
|
||||
databaseMigrations: {
|
||||
strategy: 'TypeORM migrations with rollback capability',
|
||||
testing: 'Comprehensive migration testing',
|
||||
automation: 'CI/CD integrated migration pipelines'
|
||||
}
|
||||
automation: 'CI/CD integrated migration pipelines',
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
### **14.2 Compatibility Requirements:**
|
||||
|
||||
* **14.2.1** ต้องรองรับ Browser ที่ทันสมัย (Latest 2 versions)
|
||||
* **14.2.2** รองรับ Mobile Responsive Design
|
||||
* **14.2.3** ต้องมี Accessibility Compliance (WCAG 2.1 AA)
|
||||
* **14.2.4** รองรับ Internationalization (i18n)
|
||||
- **14.2.1** ต้องรองรับ Browser ที่ทันสมัย (Latest 2 versions)
|
||||
- **14.2.2** รองรับ Mobile Responsive Design
|
||||
- **14.2.3** ต้องมี Accessibility Compliance (WCAG 2.1 AA)
|
||||
- **14.2.4** รองรับ Internationalization (i18n)
|
||||
|
||||
---
|
||||
|
||||
@@ -595,7 +570,7 @@ const VERSION_MANAGEMENT = {
|
||||
|
||||
## 📊 **Implementation Metrics**
|
||||
|
||||
| หมวดหมู่ | เป้าหมาย | วิธีการวัดผล |
|
||||
| หมวดหมู่ | เป้าหมาย | วิธีการวัดผล |
|
||||
| ------------------- | ----------------------------- | -------------------------- |
|
||||
| **Performance** | API Response < 200ms | 90th percentile monitoring |
|
||||
| **Security** | Zero Critical Vulnerabilities | Regular security scans |
|
||||
@@ -608,11 +583,11 @@ const VERSION_MANAGEMENT = {
|
||||
|
||||
**Document Control:**
|
||||
|
||||
* Document: Application Requirements Specification DMS v1.4.2
|
||||
* Version: 1.4.2
|
||||
* Date: 2025-11-16
|
||||
* Author: System Architecture Team
|
||||
* Status: FINAL
|
||||
* Classification: Internal Technical Documentation
|
||||
- Document: Application Requirements Specification DMS v1.4.2
|
||||
- Version: 1.4.2
|
||||
- Date: 2025-11-16
|
||||
- Author: System Architecture Team
|
||||
- Status: FINAL
|
||||
- Classification: Internal Technical Documentation
|
||||
|
||||
_End of Requirements Specification_
|
||||
|
||||
@@ -107,4 +107,4 @@ This document presents a curated set of emoji and image-based icons across multi
|
||||
| 🏫 | School |
|
||||
|
||||
---
|
||||
```
|
||||
```
|
||||
|
||||
+753
-753
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user