Prepare to version 1.5 use spec-kit
This commit is contained in:
1
specs/00-overview/README.md
Normal file
1
specs/00-overview/README.md
Normal file
@@ -0,0 +1 @@
|
||||
# Project overview
|
||||
1
specs/00-overview/glossary.md
Normal file
1
specs/00-overview/glossary.md
Normal file
@@ -0,0 +1 @@
|
||||
# คำศัพท์เทคนิค
|
||||
21
specs/01-requirements/01-objectives.md
Normal file
21
specs/01-requirements/01-objectives.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# 📌 Section 1: Objectives (วัตถุประสงค์)
|
||||
|
||||
---
|
||||
|
||||
title: 'Objectives'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related: -
|
||||
|
||||
---
|
||||
|
||||
สร้างเว็บแอปพลิเคชันสำหรับระบบบริหารจัดการเอกสารโครงการ (Document Management System - DMS) แบบครบวงจร ที่เน้นความปลอดภัยสูงสุด ความถูกต้องของข้อมูล (Data Integrity) และรองรับการขยายตัวในอนาคต (Scalability) โดยแก้ไขปัญหา Race Condition และเพิ่มความเสถียรในการจัดการไฟล์ และใช้ Unified Workflow Engine ในการจัดการกระบวนการอนุมัติทั้งหมดเพื่อความยืดหยุ่น
|
||||
|
||||
- มีฟังก์ชันหลักในการอัปโหลด จัดเก็บ ค้นหา แชร์ และควบคุมสิทธิ์การเข้าถึงเอกสาร
|
||||
- ช่วยลดการใช้เอกสารกระดาษ เพิ่มความปลอดภัยในการจัดเก็บข้อมูล
|
||||
- เพิ่มความสะดวกในการทำงานร่วมกันระหว่างองกรณ์
|
||||
- ปรับปรุงความปลอดภัยของระบบด้วยมาตรการป้องกันที่ทันสมัย
|
||||
- เพิ่มความทนทานของระบบด้วยกลไก resilience patterns
|
||||
- สร้างระบบ monitoring และ observability ที่ครอบคลุม
|
||||
142
specs/01-requirements/02-architecture.md
Normal file
142
specs/01-requirements/02-architecture.md
Normal file
@@ -0,0 +1,142 @@
|
||||
# 🛠️ Section 2: System Architecture (สถาปัตยกรรมและเทคโนโลยี)
|
||||
|
||||
---
|
||||
|
||||
title: 'System Architecture'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related: -
|
||||
specs/01-objectives.md
|
||||
|
||||
---
|
||||
|
||||
ชื่อกำหนด สถาปัตยกรรมแบบ Headless/API-First ที่ทันสมัย ทำงานทั้งหมดบน QNAP Server ผ่าน Container Station เพื่อความสะดวกในการจัดการและบำรุงรักษา
|
||||
|
||||
## **2.1 Infrastructure & Environment:**
|
||||
|
||||
- Domain: `np-dms.work`, `www.np-dms.work`
|
||||
- IP: 159.192.126.103
|
||||
- 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/Cursor on Windows 11
|
||||
- Data Storage: /share/dms-data บน QNAP
|
||||
- ข้อจำกัด: ไม่สามารถใช้ .env ในการกำหนดตัวแปรภายนอกได้ ต้องกำหนดใน docker-compose.yml เท่านั้น
|
||||
|
||||
## **2.2 การจัดการ Configuration (ปรับปรุง):**
|
||||
|
||||
- ใช้ docker-compose.yml สำหรับ environment variables ตามข้อจำกัดของ QNAP
|
||||
- Secrets Management:
|
||||
- ห้ามระบุ Sensitive Secrets (Password, Keys) ใน docker-compose.yml หลัก
|
||||
- ต้องใช้ไฟล์ docker-compose.override.yml (ที่ถูก gitignore) สำหรับ Inject Environment Variables ที่เป็นความลับในแต่ละ Environment (Dev/Prod)
|
||||
- ไฟล์ docker-compose.yml หลักให้ใส่ค่า Dummy หรือว่างไว้
|
||||
- แต่ต้องมี mechanism สำหรับจัดการ sensitive secrets อย่างปลอดภัย โดยใช้:
|
||||
- Docker secrets (ถ้ารองรับ)
|
||||
- External secret management (Hashicorp Vault) หรือ
|
||||
- Encrypted environment variables
|
||||
- Development environment ยังใช้ .env ได้ แต่ต้องไม่ commit เข้า version control
|
||||
- ต้องมี configuration validation during application startup
|
||||
- ต้องแยก configuration ตาม environment (development, staging, production)
|
||||
- Docker Network: ทุก Service จะเชื่อมต่อผ่านเครือข่ายกลางชื่อ lcbp3 เพื่อให้สามารถสื่อสารกันได้
|
||||
|
||||
## **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
|
||||
- Framework: NestJS (Node.js, TypeScript, ESM)
|
||||
- หน้าที่: จัดการโครงสร้างข้อมูล (Data Models), สร้าง API, จัดการสิทธิ์ผู้ใช้ (Roles & Permissions), และสร้าง Workflow ทั้งหมดของระบบ
|
||||
|
||||
- Database: MariaDB 10.11
|
||||
|
||||
- Application name: lcbp3-db
|
||||
- Service name: mariadb
|
||||
- Domain: db.np-dms.work
|
||||
- หน้าที่: ฐานข้อมูลหลักสำหรับเก็บข้อมูลทั้งหมด
|
||||
- Tooling: DBeaver (Community Edition), phpmyadmin สำหรับการออกแบบและจัดการฐานข้อมูล
|
||||
|
||||
- Database Management: phpMyAdmin
|
||||
|
||||
- Application name: lcbp3-db
|
||||
- Service: phpmyadmin:5-apache
|
||||
- Service name: pma
|
||||
- Domain: pma.np-dms.work
|
||||
- หน้าที่: จัดการฐานข้อมูล mariadb ผ่าน Web UI
|
||||
|
||||
- Frontend: Next.js
|
||||
|
||||
- Application name: lcbp3-frontend
|
||||
- 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
|
||||
|
||||
- Workflow Automation: n8n
|
||||
|
||||
- Application name: lcbp3-n8n
|
||||
- Service: n8nio/n8n:latest
|
||||
- Service name: n8n
|
||||
- Domain: n8n.np-dms.work
|
||||
- หน้าที่: จัดการ workflow ระหว่าง Backend และ Line
|
||||
|
||||
- Reverse Proxy: Nginx Proxy Manager
|
||||
|
||||
- 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) ให้อัตโนมัติ
|
||||
|
||||
- Search Engine: Elasticsearch
|
||||
- Cache: Redis
|
||||
|
||||
## **2.4 Business Logic & Consistency (ปรับปรุง):**
|
||||
|
||||
- 2.4.1 Unified Workflow Engine (หลัก):
|
||||
|
||||
- ระบบการเดินเอกสารทั้งหมด (Correspondence, RFA, Circulation) ต้อง ใช้ Engine กลางเดียวกัน โดยกำหนด Logic ผ่าน Workflow DSL (JSON Configuration) แทนการเขียน Hard-coded ลงในตาราง
|
||||
- Workflow Versioning (เพิ่ม): ระบบต้องรองรับการกำหนด Version ของ Workflow Definition โดยเอกสารที่เริ่มกระบวนการไปแล้ว (In-progress instances) จะต้องใช้ Workflow Version เดิม จนกว่าจะสิ้นสุดกระบวนการ หรือได้รับคำสั่ง Migrate จาก Admin เพื่อป้องกันความขัดแย้งของ State
|
||||
|
||||
- 2.4.2 Separation of Concerns:
|
||||
|
||||
- Module ต่างๆ (Correspondence, RFA, Circulation) จะเก็บเฉพาะข้อมูลของเอกสาร (Data) ส่วนสถานะและการเปลี่ยนสถานะ (State Transition) จะถูกจัดการโดย Workflow Engine
|
||||
|
||||
- 2.4.3 Idempotency & Locking:
|
||||
|
||||
- ใช้กลไกเดิมในการป้องกันการทำรายการซ้ำ
|
||||
|
||||
- 2.4.4 Optimistic Locking:
|
||||
|
||||
- ใช้ Version Column ใน Database ควบคู่กับ Redis Lock สำหรับการสร้างเลขที่เอกสาร เพื่อเป็น Safety Net ชั้นสุดท้าย
|
||||
|
||||
- 2.4.5 จะไม่มีการใช้ SQL Triggers
|
||||
- เพื่อป้องกันตรรกะซ่อนเร้น (Hidden Logic) และความซับซ้อนในการดีบัก
|
||||
|
||||
## **2.5 Data Migration และ Schema Versioning:**
|
||||
|
||||
- ต้องมี database migration scripts สำหรับทุก schema change โดยใช้ TypeORM migrations
|
||||
- ต้องรองรับ rollback ของ migration ได้
|
||||
- ต้องมี data seeding strategy สำหรับ environment ต่างๆ (development, staging, production)
|
||||
- ต้องมี version compatibility between schema versions
|
||||
- Migration scripts ต้องผ่านการทดสอบใน staging environment ก่อน production
|
||||
- ต้องมี database backup ก่อนทำ migration ใน production
|
||||
|
||||
## **2.6 กลยุทธ์ความทนทานและการจัดการข้อผิดพลาด (Resilience & Error Handling Strategy)**
|
||||
|
||||
- 2.6.1 Circuit Breaker Pattern: ใช้สำหรับ external service calls (Email, LINE, Elasticsearch)
|
||||
- 2.6.2 Retry Mechanism: ด้วย exponential backoff สำหรับ transient failures
|
||||
- 2.6.3 Fallback Strategies: Graceful degradation เมื่อบริการภายนอกล้มเหลว
|
||||
- 2.6.4 Error Handling: Error messages ต้องไม่เปิดเผยข้อมูล sensitive
|
||||
- 2.6.5 Monitoring: Centralized error monitoring และ alerting system
|
||||
75
specs/01-requirements/03-functional-requirements.md
Normal file
75
specs/01-requirements/03-functional-requirements.md
Normal file
@@ -0,0 +1,75 @@
|
||||
# 📦Section 3: ข้อกำหนดด้านฟังก์ชันการทำงาน (Functional Requirements)
|
||||
|
||||
---
|
||||
|
||||
title: "Functional Requirements: Correspondence Management"
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03.1-project-management.md
|
||||
- specs/01-requirements/03.2-correspondence.md
|
||||
- specs/01-requirements/03.3-rfa.md
|
||||
- specs/01-requirements/03.4-contract-drawing.md
|
||||
- specs/01-requirements/03.5-shop-drawing.md
|
||||
- specs/01-requirements/03.6-unified-workflow.md
|
||||
- specs/01-requirements/03.7-transmittals.md
|
||||
- specs/01-requirements/03.8-circulation-sheet.md
|
||||
- specs/01-requirements/03.9-logs.md
|
||||
- specs/01-requirements/03.10-file-handling.md
|
||||
- specs/01-requirements/03.11-document-numbering.md
|
||||
- specs/01-requirements/03.12-json-details.md
|
||||
|
||||
---
|
||||
|
||||
## 3.1 การจัดการโครงสร้างโครงการและองค์กร (Project Management)
|
||||
|
||||
[specs/01-requirements/03.1-project-management.md](./03.1-project-management.md)
|
||||
|
||||
## 3.2 การจัดการเอกสารโครงการ (Correspondence)
|
||||
|
||||
[specs/01-requirements/03.2-correspondence.md](./03.2-correspondence.md)
|
||||
|
||||
## 3.3 การจัดการเอกสารโครงการ (RFA)
|
||||
|
||||
[specs/01-requirements/03.3-rfa.md](./03.3-rfa.md)
|
||||
|
||||
## 3.4 การจัดการแบบคู่สัญญา (Contract Drawing)
|
||||
|
||||
[specs/01-requirements/03.4-contract-drawing.md](./03.4-contract-drawing.md)
|
||||
|
||||
## 3.5 การจัดกาแบบก่อสร้าง (Shop Drawing)
|
||||
|
||||
[specs/01-requirements/03.5-shop-drawing.md](./03.5-shop-drawing.md)
|
||||
|
||||
## 3.6 การจัดการ Workflow (Unified Workflow)
|
||||
|
||||
[specs/01-requirements/03.6-unified-workflow.md](./03.6-unified-workflow.md)
|
||||
|
||||
## 3.7 การจัดการเอกสารนำส่ง (Transmittals)
|
||||
|
||||
[specs/01-requirements/03.7-transmittals.md](./03.7-transmittals.md)
|
||||
|
||||
## 3.8 การจัดการใบเวียนเอกสาร (Circulation Sheet)
|
||||
|
||||
[specs/01-requirements/03.8-circulation-sheet.md](./03.8-circulation-sheet.md)
|
||||
|
||||
## 3.9 ประวัติการแก้ไข (logs)
|
||||
|
||||
[specs/01-requirements/03.9-logs.md](./03.9-logs.md)
|
||||
|
||||
## 3.10 การจัดเก็บไฟล์ (File Handling)
|
||||
|
||||
[specs/01-requirements/03.10-file-handling.md](./03.10-file-handling.md)
|
||||
|
||||
## 3.11 การจัดการเลขที่เอกสาร (Document Numbering)
|
||||
|
||||
[specs/01-requirements/03.11-document-numbering.md](./03.11-document-numbering.md)
|
||||
|
||||
## 3.12 การจัดการ JSON Details (JSON & Performance - ปรับปรุง)
|
||||
|
||||
[specs/01-requirements/03.12-json-details.md](./03.12-json-details.md)
|
||||
24
specs/01-requirements/03.1-project-management.md
Normal file
24
specs/01-requirements/03.1-project-management.md
Normal file
@@ -0,0 +1,24 @@
|
||||
# 3.1 Project Management (การจัดการโครงสร้างโครงการและองค์กร)
|
||||
|
||||
---
|
||||
|
||||
title: "Functional Requirements: Project Management"
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## Details (รายละเอียด)
|
||||
|
||||
- 3.1.1. โครงการ (Projects): ระบบต้องสามารถจัดการเอกสารภายในหลายโครงการได้ (ปัจจุบันมี 4 โครงการ และจะเพิ่มขึ้นในอนาคต)
|
||||
- 3.1.2. สัญญา (Contracts): ระบบต้องสามารถจัดการเอกสารภายในแต่ละสัญญาได้ ในแต่ละโครงการ มีได้หลายสัญญา หรืออย่างน้อย 1 สัญญา
|
||||
- 3.1.3. องค์กร (Organizations):
|
||||
- มีหลายองค์กรในโครงการ องค์กรณ์ที่เป็น Owner, Designer และ Consultant สามารถอยู่ในหลายโครงการและหลายสัญญาได้
|
||||
- Contractor จะถือ 1 สัญญา และอยู่ใน 1 โครงการเท่านั้น
|
||||
39
specs/01-requirements/03.10-file-handling.md
Normal file
39
specs/01-requirements/03.10-file-handling.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 3.10 File Handling Management (การจัดการไฟล์)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: File Handling Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.10.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.10.2 Security:
|
||||
|
||||
- Virus Scan (ClamAV) ก่อนย้ายเข้า permanent
|
||||
- Whitelist File Types: PDF, DWG, DOCX, XLSX, ZIP
|
||||
- Max Size: 50MB
|
||||
- Access Control: ตรวจสอบสิทธิ์ผ่าน Junction Table ก่อนให้ Download Link
|
||||
|
||||
## 3.10.3 ความปลอดภัยของการจัดเก็บไฟล์:
|
||||
|
||||
- ต้องมีการ scan virus สำหรับไฟล์ที่อัปโหลดทั้งหมด โดยใช้ ClamAV หรือบริการ third-party
|
||||
- จำกัดประเภทไฟล์ที่อนุญาต: PDF, DWG, DOCX, XLSX, ZIP (ต้องระบุรายการที่ชัดเจน)
|
||||
- ขนาดไฟล์สูงสุด: 50MB ต่อไฟล์
|
||||
- ไฟล์ต้องถูกเก็บนอก web root และเข้าถึงได้ผ่าน authenticated endpoint เท่านั้น
|
||||
- ต้องมี file integrity check (checksum) เพื่อป้องกันการแก้ไขไฟล์
|
||||
- Download links ต้องมี expiration time (default: 24 ชั่วโมง)
|
||||
- ต้องบันทึก audit log ทุกครั้งที่มีการดาวน์โหลดไฟล์สำคัญ
|
||||
60
specs/01-requirements/03.11-document-numbering.md
Normal file
60
specs/01-requirements/03.11-document-numbering.md
Normal file
@@ -0,0 +1,60 @@
|
||||
# 3.11 Document Numbering Management (การจัดการเลขที่เอกสาร)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: Document Numbering Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.11.1. วัตถุประสงค์:
|
||||
|
||||
- ระบบต้องสามารถสร้างเลขที่เอกสาร (Running Number) ได้โดยอัตโนมัติและยืดหยุ่นสูง
|
||||
|
||||
## 3.11.2. Logic การนับเลข (Counter Logic):
|
||||
|
||||
- การนับเลขจะต้องรองรับการแยกตาม Key ที่ซับซ้อนขึ้น:
|
||||
- Project + Originator + Type + Discipline (ถ้ามี) + Sub-Type (ถ้ามี) + Year
|
||||
|
||||
## 3.11.3. Format Template:
|
||||
|
||||
- รองรับการกำหนดรูปแบบด้วย Token Replacement เช่น:
|
||||
- รองรับ Token: `{ORG}-{TYPE}-{DISCIPLINE}-{SEQ:4}-{REV}` -> `TEAM-RFA-STR-0001-A`
|
||||
- รองรับ Token: `{PROJECT}`, `{ORG}`, `{TYPE}`, `{DISCIPLINE}`, `{SUBTYPE}`, `{SUBTYPE_NUM}`, `{YEAR}`, `{YEAR_SHORT}`, `{SEQ:n}`
|
||||
|
||||
## 3.11.4. Transmittal Logic:
|
||||
|
||||
- รองรับเงื่อนไขพิเศษสำหรับ Transmittal ที่เลขอาจเปลี่ยนตามผู้รับ (To Owner vs To Contractor)
|
||||
|
||||
## 3.11.5. กลไกความปลอดภัย:
|
||||
|
||||
- ยังคงใช้ Redis Distributed Lock และ Optimistic Locking เพื่อป้องกันเลขซ้ำหรือข้าม
|
||||
|
||||
## 3.11.6. ต้องมี retry mechanism และ fallback strategy เมื่อการ generate เลขที่เอกสารล้มเหลว
|
||||
|
||||
## 3.11.7. Fallback Logic (เพิ่ม):
|
||||
|
||||
- กรณีที่เอกสารประเภทนั้นไม่มี discipline_id หรือ sub_type_id (เป็นค่า NULL หรือไม่ระบุ) ให้ระบบใช้ค่า Default (เช่น 0) ในการจัดกลุ่ม Counter เพื่อป้องกัน Error และรับประกันความถูกต้องของ Running Number (Uniqueness Guarantee)
|
||||
- Scenario 1: Redis Unavailable
|
||||
- Fallback เป็น database-only locking (pessimistic lock)
|
||||
- Log warning และแจ้ง ops team
|
||||
- ระบบยังใช้งานได้แต่ performance ลดลง
|
||||
- Scenario 2: Lock Acquisition Timeout
|
||||
- Retry 5 ครั้งด้วย exponential backoff (1s, 2s, 4s, 8s, 16s)
|
||||
- หลัง 5 ครั้ง: Return error 503 "Service Temporarily Unavailable"
|
||||
- Frontend แสดง user-friendly message: "ระบบกำลังยุ่ง กรุณาลองใหม่ภายหลัง"
|
||||
- Scenario 3: Version Conflict After Lock
|
||||
- Retry transaction อีก 2 ครั้ง
|
||||
- หากยังล้มเหลว: Log error พร้อม context และ return 409 Conflict
|
||||
- Frontend แสดง user-friendly message: "เลขที่เอกสารถูกเปลี่ยน กรุณาลองใหม่"
|
||||
- Monitoring:
|
||||
- Alert ถ้า lock acquisition failures > 5% ใน 5 นาที
|
||||
- Dashboard แสดง lock wait time percentiles
|
||||
100
specs/01-requirements/03.12-json-details.md
Normal file
100
specs/01-requirements/03.12-json-details.md
Normal file
@@ -0,0 +1,100 @@
|
||||
# 3.12 JSON Details Management (การจัดการ JSON Details)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: JSON Details Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.12.1 วัตถุประสงค์
|
||||
|
||||
- จัดเก็บข้อมูลแบบไดนามิกที่เฉพาะเจาะจงกับแต่ละประเภทของเอกสาร
|
||||
- รองรับการขยายตัวของระบบโดยไม่ต้องเปลี่ยนแปลง database schema
|
||||
- จัดการ metadata และข้อมูลประกอบสำหรับ correspondence, routing, และ workflows
|
||||
|
||||
## 3.12.2 โครงสร้าง JSON Schema
|
||||
|
||||
- ระบบต้องมี predefined JSON schemas สำหรับประเภทเอกสารต่างๆ:
|
||||
|
||||
- 3.12.2.1 Correspondence Types
|
||||
- GENERIC: ข้อมูลพื้นฐานสำหรับเอกสารทั่วไป
|
||||
- RFI: รายละเอียดคำถามและข้อมูลทางเทคนิค
|
||||
- RFA: ข้อมูลการขออนุมัติแบบและวัสดุ
|
||||
- TRANSMITTAL: รายการเอกสารที่ส่งต่อ
|
||||
- LETTER: ข้อมูลจดหมายทางการ
|
||||
- EMAIL: ข้อมูลอีเมล
|
||||
- 3.12.2.2 Rworkflow Types
|
||||
- workflow_definitions: กฎและเงื่อนไขการส่งต่อ
|
||||
- workflow_histories: สถานะและประวัติการส่งต่อ
|
||||
- workflow_instances: การดำเนินการในแต่ละขั้นตอน
|
||||
- 3.12.2.3 Audit Types
|
||||
- AUDIT_LOG: ข้อมูลการตรวจสอบ
|
||||
- SECURITY_SCAN: ผลการตรวจสอบความปลอดภัย
|
||||
|
||||
## 3.12.3 Virtual Columns (ปรับปรุง)
|
||||
|
||||
- สำหรับ Field ใน JSON ที่ต้องใช้ในการค้นหา (Search) หรือจัดเรียง (Sort) บ่อยๆ ต้องสร้าง Generated Column (Virtual Column) ใน Database และทำ Index ไว้ เพื่อประสิทธิภาพสูงสุด
|
||||
- Schema Consistency: Field ที่ถูกกำหนดเป็น Virtual Column ห้าม เปลี่ยนแปลง Key Name หรือ Data Type ใน JSON Schema Version ถัดไป หากจำเป็นต้องเปลี่ยน ต้องมีแผนการ Re-index หรือ Migration ข้อมูลเดิมที่ชัดเจน
|
||||
|
||||
## 3.12.4 Validation Rules
|
||||
|
||||
- ต้องมี JSON schema validation สำหรับแต่ละประเภท
|
||||
- ต้องรองรับ versioning ของ schema
|
||||
- ต้องมี default values สำหรับ field ที่ไม่บังคับ
|
||||
- ต้องตรวจสอบ data types และ format ให้ถูกต้อง
|
||||
|
||||
## 3.12.5 Performance Requirements
|
||||
|
||||
- JSON field ต้องมีขนาดไม่เกิน 50KB
|
||||
- ต้องรองรับ indexing สำหรับ field ที่ใช้ค้นหาบ่อย
|
||||
- ต้องมี compression สำหรับ JSON ขนาดใหญ่
|
||||
|
||||
## 3.12.6 Security Requirements
|
||||
|
||||
- ต้อง sanitize JSON input เพื่อป้องกัน injection attacks
|
||||
- ต้อง validate JSON structure ก่อนบันทึก
|
||||
- ต้อง encrypt sensitive data ใน JSON fields
|
||||
|
||||
## 3.12.7 JSON Schema Migration Strategy (เพิ่มเติม)
|
||||
|
||||
- สำหรับ Schema Breaking Changes:
|
||||
|
||||
- Phase 1 - Add New Column
|
||||
ALTER TABLE correspondence_revisions
|
||||
ADD COLUMN ref_project_id_v2 INT GENERATED ALWAYS AS
|
||||
(JSON_UNQUOTE(JSON_EXTRACT(details, '$.newProjectIdPath'))) VIRTUAL;
|
||||
|
||||
- Phase 2 - Backfill Old Records
|
||||
- ใช้ background job แปลง JSON format เก่าเป็นใหม่
|
||||
- Update `details` JSON ทีละ batch (1000 records)
|
||||
- Phase 3 - Switch Application Code
|
||||
- Deploy code ที่ใช้ path ใหม่
|
||||
- Phase 4 - Remove Old Column
|
||||
|
||||
- หลังจาก verify แล้วว่าไม่มี error
|
||||
- Drop old virtual column
|
||||
|
||||
- สำหรับ Non-Breaking Changes
|
||||
- เพิ่ม optional field ใน schema
|
||||
- Old records ที่ไม่มี field = ใช้ default value
|
||||
|
||||
## 3.13. ข้อกำหนดพิเศษ
|
||||
|
||||
- ผู้ใช้งานที่มีสิทธิ์ระดับสูง (Global) หรือผู้ได้รับอนุญาตเป็นกรณีพิเศษ
|
||||
- สามารถเลือก สร้างในนามองค์กร (Create on behalf of) ได้ เพื่อให้สามารถออกเลขที่เอกสาร (Running Number) ขององค์กรอื่นได้โดยไม่ต้องล็อกอินใหม่
|
||||
- สามารถทำงานแทนผู้ใช้งานอื่นได้ Routing & Workflow ของ Correspondence, RFA, Circulation Sheet
|
||||
|
||||
## 3.14. การจัดการข้อมูลหลักขั้นสูง (Admin Panel for Master Data)
|
||||
|
||||
- 3.14.1. Disciplines Management: Admin ต้องสามารถ เพิ่ม/ลบ/แก้ไข สาขางาน (Disciplines) แยกตามสัญญา (Contract) ได้
|
||||
- 3.14.2. Sub-Type Mapping: Admin ต้องสามารถกำหนด Correspondence Sub-types และ Mapping รหัสตัวเลข (เช่น MAT = 11) ได้
|
||||
- 3.14.3. Numbering Format Configuration: Admin ต้องมี UI สำหรับตั้งค่า Format Template ของแต่ละ Project/Type ได้โดยไม่ต้องแก้โค้ด
|
||||
39
specs/01-requirements/03.2-correspondence.md
Normal file
39
specs/01-requirements/03.2-correspondence.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 3.2 การจัดการเอกสารโต้ตอบ (Correspondence Management)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: Correspondence Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.2.1. วัตถุประสงค์:
|
||||
|
||||
- เอกสารโต้ตอบ (Correspondences) ระหว่างองค์กรณ์-องค์กรณ์ ภายใน โครงการ (Projects) และระหว่าง องค์กรณ์-องค์กรณ์ ภายนอก โครงการ (Projects), รองรับ To (ผู้รับหลัก) และ CC (ผู้รับสำเนา) หลายองค์กรณ์
|
||||
|
||||
## 3.2.2. ประเภทเอกสาร:
|
||||
|
||||
- ระบบต้องรองรับเอกสารรูปแบบ ไฟล์ PDF, ZIP
|
||||
- เอกสารโต้ตอบ (Correspondence) สามารถมีได้หลายประเภท (Types) เช่น จดหมาย (Letter), อีเมล์ (Email), Request for Information (RFI), รวมถึง เอกสารขออนุมัติ (RFA) แต่ละ revision และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
|
||||
|
||||
## 3.2.3. การสร้างเอกสาร (Correspondence):
|
||||
|
||||
- ผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารรอไว้ในสถานะ ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
|
||||
- เมื่อกด "Submitted" แล้ว การแก้ไข, ถอนเอกสารกลับไปสถานะ Draft, หรือยกเลิก (Cancel) จะต้องทำโดยผู้ใช้ระดับ Admin ขึ้นไป พร้อมระบุเหตุผล
|
||||
|
||||
## 3.2.4. การอ้างอิงและจัดกลุ่ม:
|
||||
|
||||
- เอกสารสามารถอ้างถึง (Reference) เอกสารฉบับก่อนหน้าได้หลายฉบับ
|
||||
- สามารถกำหนด Tag ได้หลาย Tag เพื่อจัดกลุ่มและใช้ในการค้นหาขั้นสูง
|
||||
|
||||
## 3.2.5. Workflow (Unified Workflow):
|
||||
|
||||
- ระบบต้องรองรับ Workflow ที่เป็นแบบ Unified Workflow
|
||||
39
specs/01-requirements/03.3-rfa.md
Normal file
39
specs/01-requirements/03.3-rfa.md
Normal file
@@ -0,0 +1,39 @@
|
||||
# 3.3 RFA Management (การจัดการเอกสาขออนุมัติ)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: RFA Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.3.1. วัตถุประสงค์:
|
||||
|
||||
- เอกสารขออนุมัติ (RFA) ภายใน โครงการ (Projects)
|
||||
|
||||
## 3.3.2. ประเภทเอกสาร:
|
||||
|
||||
- ระบบต้องรองรับเอกสารรูปแบบ ไฟล์ PDF
|
||||
- เอกสารขออนุมัติ (RFA) สามารถมีได้หลาย revision
|
||||
- มีประถทของเอกสาร ได้หลายประเภท (RFA Types) และสามารถเพิ่มประเภทใหม่ได้ในภายหลัง
|
||||
|
||||
## 3.3.3. การสร้างเอกสาร:
|
||||
|
||||
- ผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารขออนุมัติ (RFA) รอไว้ในสถานะ ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
|
||||
- เมื่อกด "Submitted" แล้ว การแก้ไข, ถอนเอกสารกลับไปสถานะ Draft, หรือยกเลิก (Cancel) จะต้องทำโดยผู้ใช้ระดับ Admin ขึ้นไป พร้อมระบุเหตุผล
|
||||
|
||||
## 3.3.4. การอ้างอิงและจัดกลุ่ม:
|
||||
|
||||
- RFA สามารถอ้างถึง (Reference) แบบก่อสร้าง (Shop Drawing) ได้หลายฉบับ
|
||||
|
||||
## 3.3.5. Workflow (Unified Workflow):
|
||||
|
||||
- ระบบต้องรองรับ Workflow ที่เป็นแบบ Unified Workflow
|
||||
32
specs/01-requirements/03.4-contract-drawing.md
Normal file
32
specs/01-requirements/03.4-contract-drawing.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# 3.4 Contract Drawing Management (การจัดการแบบคู่สัญญา)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: Contract Drawing Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.4.1. วัตถุประสงค์:
|
||||
|
||||
- แบบคู่สัญญา (Contract Drawing) ใช้เพื่ออ้างอิงและใช้ในการตรวจสอบ
|
||||
|
||||
## 3.4.2. ประเภทเอกสาร:
|
||||
|
||||
- ไฟล์ PDF
|
||||
|
||||
## 3.4.3. การสร้างเอกสาร:
|
||||
|
||||
- ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
|
||||
## 3.4.4. การอ้างอิงและจัดกลุ่ม:
|
||||
|
||||
- ใช้สำหรับอ้างอิง ใน Shop Drawings, มีการจัดหมวดหมู่ของ Contract Drawing
|
||||
32
specs/01-requirements/03.5-shop-drawing.md
Normal file
32
specs/01-requirements/03.5-shop-drawing.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# 3.5 Shop Drawing Management (การจัดการแบบก่อสร้าง)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: Shop Drawing Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.5.1. วัตถุประสงค์:
|
||||
|
||||
- แบบก่อสร้าง (Shop Drawing) ใช้เในการตรวจสอบ โดยจัดส่งด้วย Request for Approval (RFA)
|
||||
|
||||
## 3.5.2. ประเภทเอกสาร:
|
||||
|
||||
- ไฟล์ PDF, DWG, ZIP
|
||||
|
||||
## 3.5.3. การสร้างเอกสาร:
|
||||
|
||||
- ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้ โดยผู้ใช้ที่มีสิทธิ์ (เช่น Document Control) สามารถสร้างเอกสารรอไว้ในสถานะ ฉบับร่าง" (Draft) ได้ ซึ่งผู้ใช้งานต่างองค์กรจะมองไม่เห็น
|
||||
|
||||
## 3.5.4. การอ้างอิงและจัดกลุ่ม:
|
||||
|
||||
- ใช้สำหรับอ้างอิง ใน RFA, มีการจัดหมวดหมู่ของ Shop Drawings โดยทุก แบบก่อสร้าง (Shop Drawing) แต่ละ revision ต้องมี RFA ได้เพียง 1 ฉบับ
|
||||
43
specs/01-requirements/03.6-unified-workflow.md
Normal file
43
specs/01-requirements/03.6-unified-workflow.md
Normal file
@@ -0,0 +1,43 @@
|
||||
# 3.6 Unified Workflow Management (การจัดการ Workflow)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: Unified Workflow Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.6.1 Workflow Definition:
|
||||
|
||||
- Admin ต้องสามารถสร้าง/แก้ไข Workflow Rule ได้ผ่านหน้าจอ UI (DSL Editor)
|
||||
- รองรับการกำหนด State, Transition, Required Role, Condition (JS Expression)
|
||||
|
||||
## 3.6.2 Workflow Execution:
|
||||
|
||||
- ระบบต้องรองรับการสร้าง Instance ของ Workflow ผูกกับเอกสาร (Polymorphic)
|
||||
- รองรับการเปลี่ยนสถานะ (Action) เช่น Approve, Reject, Comment, Return
|
||||
- Auto-Action: รองรับการเปลี่ยนสถานะอัตโนมัติเมื่อครบเงื่อนไข (เช่น Review ครบทุกคน)
|
||||
|
||||
## 3.6.3 Flexibility:
|
||||
|
||||
- รองรับ Parallel Review (ส่งให้หลายคนตรวจพร้อมกัน)
|
||||
- รองรับ Conditional Flow (เช่น ถ้ายอดเงิน > X ให้เพิ่มผู้อนุมัติ)
|
||||
|
||||
## 3.6.4 Workflow การอนุมัติ:
|
||||
|
||||
- รองรับกระบวนการอนุมัติที่ซับซ้อนและเป็นลำดับ เช่น ส่งจาก Originator -> Organization 1 -> Organization 2 -> Organization 3 แล้วส่งผลกลับตามลำดับเดิม (โดยถ้า องกรณ์ใดใน Workflow ให้ส่งกลับ ก็สามารถส่งผลกลับตามลำดับเดิมโดยไม่ต้องรอให้ถึง องกรณืในลำดับถัดไป)
|
||||
|
||||
## 3.6.5 การจัดการ:
|
||||
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ได้
|
||||
- มีระบบแจ้งเตือน ให้ผู้รับผิดชอบของ องกรณ์ ที่อยู่ใน Workflow ทราบ เมื่อมี RFA ใหม่ หรือมีการเปลี่ยนสถานะ
|
||||
- สามารถข้ามขั้นตอนได้ในกรณีพิเศษ (โดยผู้มีสิทธิ์)
|
||||
- สามารถส่งกลับขั้นตอนก่อนหน้าได้
|
||||
32
specs/01-requirements/03.7-transmittals.md
Normal file
32
specs/01-requirements/03.7-transmittals.md
Normal file
@@ -0,0 +1,32 @@
|
||||
# 3.7 Transmittals Management (การจัดการเอกสารนำส่ง)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: Transmittals Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.7.1. วัตถุประสงค์:
|
||||
|
||||
- เอกสารนำส่ง ใช้สำหรับ นำส่ง Request for Approval (RFAS) หลายฉบับ ไปยังองค์กรอื่น
|
||||
|
||||
## 3.7.2. ประเภทเอกสาร:
|
||||
|
||||
- ไฟล์ PDF
|
||||
|
||||
## 3.7.3. การสร้างเอกสาร:
|
||||
|
||||
- ผู้ใช้ที่มีสิทธิ์ สามารถสร้างและแก้ไขได้
|
||||
|
||||
## 3.7.4. การอ้างอิงและจัดกลุ่ม:
|
||||
|
||||
- เอกสารนำส่ง เป็นส่วนหนึ่งใน Correspondence
|
||||
41
specs/01-requirements/03.8-circulation-sheet.md
Normal file
41
specs/01-requirements/03.8-circulation-sheet.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# 3.8 Circulation Sheet Management (การจัดการใบเวียนเอกสาร)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: Circulation Sheet Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.8.1. วัตถุประสงค์:
|
||||
|
||||
- การสื่อสาร เอกสาร (Correspondence) ทุกฉบับ จะมีใบเวียนเอกสารเพื่อควบคุมและมอบหมายงานภายในองค์กร (สามารถดูและแก้ไขได้เฉพาะคนในองค์กร)
|
||||
|
||||
## 3.8.2. ประเภทเอกสาร:
|
||||
|
||||
- ไฟล์ PDF
|
||||
|
||||
## 3.8.3. การสร้างเอกสาร:
|
||||
|
||||
- ผู้ใช้ที่มีสิทธิ์ในองค์กรนั้น สามารถสร้างและแก้ไขได้
|
||||
|
||||
## 3.8.4. การอ้างอิงและจัดกลุ่ม:
|
||||
|
||||
- การระบุผู้รับผิดชอบ:
|
||||
- ผู้รับผิดชอบหลัก (Main): มีได้หลายคน
|
||||
- ผู้ร่วมปฏิบัติงาน (Action): มีได้หลายคน
|
||||
- ผู้ที่ต้องรับทราบ (Information): มีได้หลายคน
|
||||
|
||||
## 3.8.5. การติดตามงาน:
|
||||
|
||||
- สามารถกำหนดวันแล้วเสร็จ (Deadline) สำหรับผู้รับผิดชอบประเภท Main และ Action ได้
|
||||
- มีระบบแจ้งเตือนเมื่อมี Circulation ใหม่ และแจ้งเตือนล่วงหน้าก่อนถึงวันแล้วเสร็จ
|
||||
- สามารถปิด Circulation ได้เมื่อดำเนินการตอบกลับไปยังองค์กรผู้ส่ง (Originator) แล้ว หรือ รับทราบแล้ว (For Information)
|
||||
21
specs/01-requirements/03.9-logs.md
Normal file
21
specs/01-requirements/03.9-logs.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# 3.9 Logs Management (ประวัติการแก้ไข)
|
||||
|
||||
---
|
||||
|
||||
title: 'Functional Requirements: Logs Management'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/01-requirements/01-objectives.md
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/03-functional-requirements.md
|
||||
|
||||
---
|
||||
|
||||
## 3.9.1. วัตถุประสงค์:
|
||||
|
||||
- เพื่อ บันทึกการกระทำ CRUD ของเอกสารทั้งหมด รวมถึงการ เข้าใช้งาน ของ users
|
||||
- admin สามารถดูประวัติการแก้ไขของเอกสารทั้งหมด พร้อม จัดทำรายงายตามข้อกำหนดที่ ต้องการได้
|
||||
84
specs/01-requirements/04-access-control.md
Normal file
84
specs/01-requirements/04-access-control.md
Normal file
@@ -0,0 +1,84 @@
|
||||
# 🔐 Section 4: Access Control (ข้อกำหนดด้านสิทธิ์และการเข้าถึง)
|
||||
|
||||
---
|
||||
|
||||
title: 'Access Control'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/02-architecture/data-model.md#correspondence
|
||||
- specs/03-implementation/backend-guidelines.md#correspondencemodule
|
||||
|
||||
---
|
||||
|
||||
## 4.1. Overview:
|
||||
|
||||
- Users and organizations can view and edit documents based on the permissions they have. The system's permissions will be based on Role-Based Access Control (RBAC).
|
||||
|
||||
## 4.2. Permission Hierarchy:
|
||||
|
||||
- Global: The highest level of permissions in the system
|
||||
- Organization: Permissions within an organization, which is the basic permission for users
|
||||
- Project: Permissions specific to a project, which will be considered when the user is in that project
|
||||
- Contract: Permissions specific to a contract, which will be considered when the user is in that contract
|
||||
|
||||
## 4.3. Permission Enforcement:
|
||||
|
||||
- When checking permissions, the system will consider permissions from all levels that the user has and use the most permissive permission as the decision
|
||||
- Example: User A is a Viewer in the organization, but is assigned as an Editor in Project X when in Project X, User A will have the right to edit
|
||||
|
||||
## 4.4. Role and Scope:
|
||||
|
||||
| Role | Scope | Description | Key Permissions |
|
||||
| :------------------- | :----------- | :------------------------- | :-------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Superadmin** | Global | System administrator | Do everything in the system, manage organizations, manage global data |
|
||||
| **Org Admin** | Organization | Organization administrator | Manage users in the organization, manage roles/permissions within the organization, view organization reports |
|
||||
| **Document Control** | Organization | Document controller | Add/edit/delete documents, set document permissions within the organization |
|
||||
| **Editor** | Organization | Document editor | Edit documents that have been assigned to them |
|
||||
| **Viewer** | Organization | Document viewer | View documents that have access permissions |
|
||||
| **Project Manager** | Project | Project manager | Manage members in the project (add/delete/assign roles), create/manage contracts in the project, view project reports |
|
||||
| **Contract Admin** | Contract | Contract administrator | Manage users in the contract, manage roles/permissions within the contract, view contract reports |
|
||||
|
||||
## 4.5. Token Management (ปรับปรุง)
|
||||
|
||||
- **Payload Optimization:** ใน JWT Access Token ให้เก็บเฉพาะ `userId` และ `scope` ปัจจุบันเท่านั้น
|
||||
- **Permission Caching:** สิทธิ์ละเอียด (Permissions List) ให้เก็บใน **Redis** และดึงมาตรวจสอบเมื่อ Request เข้ามา เพื่อลดขนาด Token และเพิ่มความเร็ว
|
||||
|
||||
## 4.6. Onboarding Workflow
|
||||
|
||||
- 4.6.1. Create Organization
|
||||
- **Superadmin** creates a new organization (e.g. Company A)
|
||||
- **Superadmin** appoints at least 1 user as **Org Admin** or **Document Control** of Company A
|
||||
- 4.6.2. Add Users to Organization
|
||||
- **Org Admin** of Company A adds other users (Editor, Viewer) to the organization
|
||||
- 4.6.3. Assign Users to Project
|
||||
- **Project Manager** of Project X (which may come from Company A or another company) invites or assigns users from different organizations to join Project X
|
||||
- In this step, **Project Manager** will assign **Project Role** (e.g. Project Member, or may use organization-level permissions)
|
||||
- 4.6.4. Assign Users to Contract
|
||||
- **Contract Admin** of Contract Y (which is part of Project X) selects users from Project X and assigns them to Contract Y
|
||||
- In this step, **Contract Admin** will assign **Contract Role** (e.g. Contract Member) and specific permissions
|
||||
- 4.6.5 Security Onboarding:
|
||||
- Force users to change password for the first time
|
||||
- Security awareness training for users with high permissions
|
||||
- Safe password reset process
|
||||
- Audit log recording every permission change
|
||||
|
||||
### **4.7. Master Data Management**
|
||||
|
||||
| Master Data | Manager | Scope |
|
||||
| :-------------------------------------- | :------------------------------ | :--------------------------------- |
|
||||
| Document Type (Correspondence, RFA) | **Superadmin** | Global |
|
||||
| Document Status (Draft, Approved, etc.) | **Superadmin** | Global |
|
||||
| Shop Drawing Category | **Project Manager** | Project (สร้างใหม่ได้ภายในโครงการ) |
|
||||
| Tags | **Org Admin / Project Manager** | Organization / Project |
|
||||
| Custom Roles | **Superadmin / Org Admin** | Global / Organization |
|
||||
| Document Numbering Formats | **Superadmin / Admin** | Global / Organization |
|
||||
|
||||
## 🔐 4.1 การจัดการผู้ใช้ (User Management)
|
||||
|
||||
## 🔐 4.2 การจัดการบทบาท (Role Management)
|
||||
|
||||
## 🔐 4.3 การจัดการสิทธิ์ (Permission Management)
|
||||
86
specs/01-requirements/05-ui-ux.md
Normal file
86
specs/01-requirements/05-ui-ux.md
Normal file
@@ -0,0 +1,86 @@
|
||||
# 👥 Section 5: UI/UX Requirements (ข้อกำหนดด้านผู้ใช้งาน)
|
||||
|
||||
---
|
||||
|
||||
title: 'UI/UX Requirements'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/02-architecture/data-model.md#correspondence
|
||||
- specs/03-implementation/backend-guidelines.md#correspondencemodule
|
||||
|
||||
---
|
||||
|
||||
## 5.1. Layout หลัก
|
||||
|
||||
- หน้าเว็บใช้รูปแบบ App Shell ที่ประกอบด้วย
|
||||
- Navbar (ส่วนบน): แสดงชื่อระบบ, เมนูผู้ใช้ (Profile), เมนูสำหรับ Document Control/เมนูสำหรับ 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 ที่ผู้ใช้ต้องดำเนินการ
|
||||
- Security Metrics: แสดงจำนวน files scanned, security incidents, failed login attempts
|
||||
|
||||
## 5.4. การติดตามสถานะ
|
||||
|
||||
- องค์กรสามารถติดตามสถานะเอกสารทั้งของตนเอง (Originator) และสถานะเอกสารที่ส่งมาถึงตนเอง (Recipient)
|
||||
|
||||
## 5.5. การจัดการข้อมูลส่วนตัว (Profile Page)
|
||||
|
||||
- ผู้ใช้สามารถจัดการข้อมูลส่วนตัวและเปลี่ยนรหัสผ่านของตนเองได้
|
||||
|
||||
## 5.6. การจัดการเอกสารทางเทคนิค (RFA)
|
||||
|
||||
- ผู้ใช้สามารถดู RFA ในรูปแบบ Workflow Diagram ทั้งหมดได้ในหน้าเดียว
|
||||
- Interactive History (เพิ่ม): ในแผนภาพ Workflow ผู้ใช้ต้องสามารถ คลิกที่ Node หรือ Step เก่าที่ผ่านมาแล้ว เพื่อดู Audit Log ย่อยของ Step นั้นได้ทันที (เช่น ใครเป็นคนกด Approve, เวลาไหน, มี Comment อะไร) โดยไม่ต้องสลับไปดูใน Tab History แยกต่างหาก
|
||||
- ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ disabled
|
||||
- สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active)
|
||||
- สิทธิ์ Document Control ขึ้นไป สามารถกด "Force Proceed" ไปยังขั้นตอนต่อไปได้ทุกขั้นตอน หรือ "Revert" กลับขั้นตอนก่อนหน้าได้
|
||||
|
||||
## 5.7. การจัดการใบเวียนเอกสาร (Circulation)
|
||||
|
||||
- ผู้ใช้สามารถดู Circulation ในรูปแบบ Workflow ทั้งหมดได้ในหน้าเดียว,ขั้นตอนที่ยังไม่ถึงหรือผ่านไปแล้วจะเป็นรูปแบบ diable, สามารถดำเนินการได้เฉพาะในขั้นตอนที่ได้รับมอบหมายงาน (active) เช่น ตรวจสอบแล้ว เพื่อไปยังขั้นตอนต่อไป, สิทธิ์ Document Control ขึ้นไป สามรถกด ไปยังขั้นตอนต่อไป ได้ทุกขั้นตอน, การย้อนกลับ ไปขั้นตอนก่อนหน้า สามารถทำได้โดย สิทธิ์ Document Control ขึ้นไป
|
||||
|
||||
## 5.8. การจัดการเอกสารนำส่ง (Transmittals)
|
||||
|
||||
- ผู้ใช้สามารถดู Transmittals ในรูปแบบรายการทั้งหมดได้ในหน้าเดียว
|
||||
|
||||
## 5.9. ข้อกำหนด UI/UX การแนบไฟล์ (File Attachment UX)
|
||||
|
||||
- ระบบต้องรองรับการอัปโหลดไฟล์หลายไฟล์พร้อมกัน (Multi-file upload) เช่น การลากและวาง (Drag-and-Drop)
|
||||
- ในหน้าอัปโหลด (เช่น สร้าง RFA หรือ Correspondence) ผู้ใช้ต้องสามารถกำหนดได้ว่าไฟล์ใดเป็น "เอกสารหลัก" (Main Document เช่น PDF) และไฟล์ใดเป็น "เอกสารแนบประกอบ" (Supporting Attachments เช่น .dwg, .docx, .zip)
|
||||
- **Security Feedback:** แสดง security warnings สำหรับ file types ที่เสี่ยงหรือ files ที่ fail virus scan
|
||||
- **File Type Indicators:** แสดง file type icons และ security status
|
||||
|
||||
## 5.10 Form & Interaction
|
||||
|
||||
- **Dynamic Form Generator:** ใช้ Component กลางที่รับ JSON Schema แล้ว Render Form ออกมาอัตโนมัติ เพื่อลดความซ้ำซ้อนของโค้ดหน้าบ้าน และรองรับเอกสารประเภทใหม่ๆ ได้ทันที
|
||||
- **Optimistic Updates:** การเปลี่ยนสถานะ (เช่น กด Approve, กด Read) ให้ UI เปลี่ยนสถานะทันทีให้ผู้ใช้เห็นก่อนรอ API Response (Rollback ถ้า Failed)
|
||||
|
||||
## 5.11 Mobile Responsiveness
|
||||
|
||||
- **Table Visualization:** บนหน้าจอมือถือ ตารางข้อมูลที่มีหลาย Column (เช่น Correspondence List) ต้องเปลี่ยนการแสดงผลเป็นแบบ **Card View** อัตโนมัติ
|
||||
- **Navigation:** Sidebar ต้องเป็นแบบ Collapsible Drawer
|
||||
|
||||
## 5.12 Resilience & Offline Support
|
||||
|
||||
- **Auto-Save Draft:** ระบบต้องบันทึกข้อมูลฟอร์มที่กำลังกรอกลง **LocalStorage** อัตโนมัติ เพื่อป้องกันข้อมูลหายกรณีเน็ตหลุดหรือปิด Browser โดยไม่ได้ตั้งใจ
|
||||
- **State Management:** ใช้ State Management ที่เหมาะสมและไม่ซับซ้อนเกินไป โดยเน้นการใช้ React Query สำหรับ Server State และ React Hook Form สำหรับ Form State
|
||||
- **Graceful Degradation:** หาก Service รอง (เช่น Search, Notification) ล่ม ระบบหลัก (CRUD) ต้องยังทำงานต่อได้
|
||||
|
||||
## 5.13. Secure In-App PDF Viewer (ใหม่)
|
||||
|
||||
- 5.13.1 Viewer Capabilities: ระบบต้องมี PDF Viewer ภายในแอปพลิเคชันที่สามารถเปิดดูไฟล์เอกสารหลัก (PDF) ได้ทันทีโดยไม่ต้องดาวน์โหลดลงเครื่อง เพื่อความสะดวกในการตรวจทาน (Review/Approve)
|
||||
- 5.13.2 Security: การแสดงผลไฟล์ต้อง ห้าม (Disable) การทำ Browser Cache สำหรับไฟล์ Sensitive เพื่อป้องกันการกู้คืนไฟล์จากเครื่อง Client ภายหลัง
|
||||
- 5.13.3 Performance: ต้องรองรับการส่งข้อมูลแบบ Streaming (Range Requests) เพื่อให้เปิดดูไฟล์ขนาดใหญ่ (เช่น แบบแปลน 50MB+) ได้รวดเร็วโดยไม่ต้องรอโหลดเสร็จทั้งไฟล์
|
||||
212
specs/01-requirements/06-non-functional.md
Normal file
212
specs/01-requirements/06-non-functional.md
Normal file
@@ -0,0 +1,212 @@
|
||||
# 🛡️ Section 6: Non-Functional Requirements (ข้อกำหนดที่ไม่ใช่ฟังก์ชันการทำงาน)
|
||||
|
||||
---
|
||||
|
||||
title: 'Non-Functional Requirements'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/02-architecture/data-model.md#correspondence
|
||||
- specs/03-implementation/backend-guidelines.md#correspondencemodule
|
||||
|
||||
---
|
||||
|
||||
## 6.1. การบันทึกการกระทำ (Audit Log)
|
||||
|
||||
- ทุกการกระทำที่สำคัญของผู้ใช้ (สร้าง, แก้ไข, ลบ, ส่ง) จะถูกบันทึกไว้ใน audit_logs เพื่อการตรวจสอบย้อนหลัง
|
||||
- ขอบเขตการบันทึก Audit Log:
|
||||
- ทุกการสร้าง/แก้ไข/ลบ ข้อมูลสำคัญ (correspondences, RFAs, drawings, users, permissions)
|
||||
- ทุกการเข้าถึงข้อมูล sensitive (user data, financial information)
|
||||
- ทุกการเปลี่ยนสถานะ workflow (status transitions)
|
||||
- ทุกการดาวน์โหลดไฟล์สำคัญ (contract documents, financial reports)
|
||||
- ทุกการเปลี่ยนแปลง permission และ role assignment
|
||||
- ทุกการล็อกอินที่สำเร็จและล้มเหลว
|
||||
- ทุกการส่งคำขอ API ที่สำคัญ
|
||||
- ข้อมูลที่ต้องบันทึกใน Audit Log:
|
||||
- ผู้ใช้งาน (user_id)
|
||||
- การกระทำ (action)
|
||||
- ชนิดของ entity (entity_type)
|
||||
- ID ของ entity (entity_id)
|
||||
- ข้อมูลก่อนการเปลี่ยนแปลง (old_values) - สำหรับ update operations
|
||||
- ข้อมูลหลังการเปลี่ยนแปลง (new_values) - สำหรับ update operations
|
||||
- IP address
|
||||
- User agent
|
||||
- Timestamp
|
||||
- Request ID สำหรับ tracing
|
||||
|
||||
## 6.2. Data Archiving & Partitioning
|
||||
|
||||
- สำหรับตารางที่มีขนาดใหญ่และโตเร็ว (เช่น `audit_logs`, `notifications`, `correspondence_revisions`) ต้องออกแบบโดยรองรับ **Table Partitioning** (แบ่งตาม Range วันที่ หรือ List) เพื่อประสิทธิภาพในระยะยาว
|
||||
|
||||
## 6.3. การค้นหา (Search):
|
||||
|
||||
- ระบบต้องมีฟังก์ชันการค้นหาขั้นสูง ที่สามารถค้นหาเอกสาร **correspondence**, **rfa**, **shop_drawing**, **contract-drawing**, **transmittal** และ **ใบเวียน (Circulations)** จากหลายเงื่อนไขพร้อมกันได้ เช่น ค้นหาจากชื่อเรื่อง, ประเภท, วันที่, และ Tag
|
||||
|
||||
## 6.4. การทำรายงาน (Reporting):
|
||||
|
||||
- สามารถจัดทำรายงานสรุปแยกประเภทของ Correspondence ประจำวัน, สัปดาห์, เดือน, และปีได้
|
||||
|
||||
## 6.5. ประสิทธิภาพ (Performance):
|
||||
|
||||
- มีการใช้ Caching กับข้อมูลที่เรียกใช้บ่อย และใช้ Pagination ในตารางข้อมูลเพื่อจัดการข้อมูลจำนวนมาก
|
||||
|
||||
- ตัวชี้วัดประสิทธิภาพ:
|
||||
|
||||
- **API Response Time:** < 200ms (90th percentile) สำหรับ operation ทั่วไป
|
||||
- **Search Query Performance:** < 500ms สำหรับการค้นหาขั้นสูง
|
||||
- **File Upload Performance:** < 30 seconds สำหรับไฟล์ขนาด 50MB
|
||||
- **Concurrent Users:** รองรับผู้ใช้พร้อมกันอย่างน้อย 100 คน
|
||||
- **Database Connection Pool:** ขนาดเหมาะสมกับ workload (default: min 5, max 20 connections)
|
||||
- **Cache Hit Ratio:** > 80% สำหรับ cached data
|
||||
- **Application Startup Time:** < 30 seconds
|
||||
|
||||
- Caching Strategy:
|
||||
|
||||
- **Master Data Cache:** Roles, Permissions, Organizations, Project metadata (TTL: 1 hour)
|
||||
- **User Session Cache:** User permissions และ profile data (TTL: 30 minutes)
|
||||
- **Search Result Cache:** Frequently searched queries (TTL: 15 minutes)
|
||||
- **File Metadata Cache:** Attachment metadata (TTL: 1 hour)
|
||||
- **Document Cache:** Frequently accessed document metadata (TTL: 30 minutes)
|
||||
- **ต้องมี cache invalidation strategy ที่ชัดเจน:**
|
||||
- Invalidate on update/delete operations
|
||||
- Time-based expiration
|
||||
- Manual cache clearance สำหรับ admin operations
|
||||
- ใช้ Redis เป็น distributed cache backend
|
||||
- ต้องมี cache monitoring (hit/miss ratios)
|
||||
|
||||
- Frontend Performance:
|
||||
- **Bundle Size Optimization:** ต้องควบคุมขนาด Bundle โดยรวมไม่เกิน 2MB
|
||||
- **State Management Efficiency:** ใช้ State Management Libraries อย่างเหมาะสม ไม่เกิน 2 ตัวหลัก
|
||||
- **Memory Management:** ต้องป้องกัน Memory Leak จาก State ที่ไม่จำเป็น
|
||||
|
||||
## 6.6. ความปลอดภัย (Security):
|
||||
|
||||
- มีระบบ Rate Limiting เพื่อป้องกันการโจมตีแบบ Brute-force
|
||||
- การจัดการ Secret (เช่น รหัสผ่าน DB, JWT Secret) จะต้องทำผ่าน Environment Variable ของ Docker เพื่อความปลอดภัยสูงสุด
|
||||
- Rate Limiting Strategy:
|
||||
- **Anonymous Endpoints:** 100 requests/hour ต่อ IP address
|
||||
- **Authenticated Endpoints:**
|
||||
- Viewer: 500 requests/hour
|
||||
- Editor: 1000 requests/hour
|
||||
- Document Control: 2000 requests/hour
|
||||
- Admin/Superadmin: 5000 requests/hour
|
||||
- **File Upload Endpoints:** 50 requests/hour ต่อ user
|
||||
- **Search Endpoints:** 500 requests/hour ต่อ user
|
||||
- **Authentication Endpoints:** 10 requests/minute ต่อ IP address
|
||||
- **ต้องมี mechanism สำหรับยกเว้น rate limiting สำหรับ trusted services**
|
||||
- ต้องบันทึก log เมื่อมีการ trigger rate limiting
|
||||
- Error Handling และ Resilience:
|
||||
- ต้องมี circuit breaker pattern สำหรับ external service calls
|
||||
- ต้องมี retry mechanism ด้วย exponential backoff
|
||||
- ต้องมี graceful degradation เมื่อบริการภายนอกล้มเหลว
|
||||
- Error messages ต้องไม่เปิดเผยข้อมูล sensitive
|
||||
- Input Validation:
|
||||
- ต้องมี input validation ทั้งฝั่ง client และ server (defense in depth)
|
||||
- ต้องป้องกัน OWASP Top 10 vulnerabilities:
|
||||
- SQL Injection (ใช้ parameterized queries ผ่าน ORM)
|
||||
- XSS (input sanitization และ output encoding)
|
||||
- CSRF (CSRF tokens สำหรับ state-changing operations)
|
||||
- ต้อง validate file uploads:
|
||||
- File type (white-list approach)
|
||||
- File size
|
||||
- File content (magic number verification)
|
||||
- ต้อง sanitize user inputs ก่อนแสดงผลใน UI
|
||||
- ต้องใช้ content security policy (CSP) headers
|
||||
- ต้องมี request size limits เพื่อป้องกัน DoS attacks
|
||||
- Session และ Token Management:
|
||||
- **JWT token expiration:** 8 hours สำหรับ access token
|
||||
- **Refresh token expiration:** 7 days
|
||||
- **Refresh token mechanism:** ต้องรองรับ token rotation และ revocation
|
||||
- **Token revocation on logout:** ต้องบันทึก revoked tokens จนกว่าจะ expire
|
||||
- **Concurrent session management:**
|
||||
- จำกัดจำนวน session พร้อมกันได้ (default: 5 devices)
|
||||
- ต้องแจ้งเตือนเมื่อมี login จาก device/location ใหม่
|
||||
- **Device fingerprinting:** สำหรับ security และ audit purposes
|
||||
- **Password policy:**
|
||||
- ความยาวขั้นต่ำ: 8 characters
|
||||
- ต้องมี uppercase, lowercase, number, special character
|
||||
- ต้องเปลี่ยน password ทุก 90 วัน
|
||||
- ต้องป้องกันการใช้ password ที่เคยใช้มาแล้ว 5 ครั้งล่าสุด
|
||||
|
||||
## 6.7. การสำรองข้อมูลและการกู้คืน (Backup & Recovery)
|
||||
|
||||
- ระบบจะต้องมีกลไกการสำรองข้อมูลอัตโนมัติสำหรับฐานข้อมูล MariaDB [cite: 2.4] และไฟล์เอกสารทั้งหมดใน /share/dms-data [cite: 2.1] (เช่น ใช้ HBS 3 ของ QNAP หรือสคริปต์สำรองข้อมูล) อย่างน้อยวันละ 1 ครั้ง
|
||||
- ต้องมีแผนการกู้คืนระบบ (Disaster Recovery Plan) ในกรณีที่ Server หลัก (QNAP) ใช้งานไม่ได้
|
||||
- ขั้นตอนการกู้คืน:
|
||||
- **Database Restoration Procedure:**
|
||||
- สร้างจาก full backup ล่าสุด
|
||||
- Apply transaction logs ถึง point-in-time ที่ต้องการ
|
||||
- Verify data integrity post-restoration
|
||||
- **File Storage Restoration Procedure:**
|
||||
- Restore จาก QNAP snapshot หรือ backup
|
||||
- Verify file integrity และ permissions
|
||||
- **Application Redeployment Procedure:**
|
||||
- Deploy จาก version ล่าสุดที่รู้ว่าทำงานได้
|
||||
- Verify application health
|
||||
- **Data Integrity Verification Post-Recovery:**
|
||||
- Run data consistency checks
|
||||
- Verify critical business data
|
||||
- **Recovery Time Objective (RTO):** < 4 ชั่วโมง
|
||||
- **Recovery Point Objective (RPO):** < 1 ชั่วโมง
|
||||
|
||||
## 6.8. กลยุทธ์การแจ้งเตือน (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]
|
||||
- Grouping/Digest
|
||||
- กรณีมีการแจ้งเตือนประเภทเดียวกันจำนวนมากในช่วงเวลาสั้นๆ (เช่น Approve เอกสาร 10 ฉบับรวด) ระบบต้อง **รวม (Batch)** เป็น 1 Email/Line Notification เพื่อไม่ให้รบกวนผู้ใช้ (Spamming)
|
||||
- Notification Delivery Guarantees
|
||||
- **At-least-once delivery:** สำหรับ important notifications
|
||||
- **Retry mechanism:** ด้วย exponential backoff (max 3 reties)
|
||||
- **Dead letter queue:** สำหรับ notifications ที่ส่งไม่สำเร็จหลังจาก retries
|
||||
- **Delivery status tracking:** ต้องบันทึกสถานะการส่ง notifications
|
||||
- **Fallback channels:** ถ้า Email ล้มเหลว ให้ส่งผ่าน SYSTEM notification
|
||||
- **Notification preferences:** ผู้ใช้ต้องสามารถกำหนด channel preferences ได้
|
||||
|
||||
## 6.9. Maintenance Mode
|
||||
|
||||
- ระบบต้องมีกลไก **Maintenance Mode** ที่ Admin สามารถเปิดใช้งานได้
|
||||
- เมื่อเปิด: ผู้ใช้ทั่วไปจะเห็นหน้า "ปิดปรับปรุง" และไม่สามารถเรียก API ได้ (ยกเว้น Admin)
|
||||
- ใช้สำหรับช่วง Deploy Version ใหม่ หรือ Database Migration
|
||||
|
||||
## 6.10. Monitoring และ Observability
|
||||
|
||||
- Application Monitoring
|
||||
- **Health checks:** /health endpoint สำหรับ load balancer
|
||||
- **Metrics collection:** Response times, error rates, throughput
|
||||
- **Distributed tracing:** สำหรับ request tracing across services
|
||||
- **Log aggregation:** Structured logging ด้วย JSON format
|
||||
- **Alerting:** สำหรับ critical errors และ performance degradation
|
||||
- Business Metrics
|
||||
- จำนวน documents created ต่อวัน
|
||||
- Workflow completion rates
|
||||
- User activity metrics
|
||||
- System utilization rates
|
||||
- Search query performance
|
||||
- Security Monitoring
|
||||
- Failed login attempts
|
||||
- Rate limiting triggers
|
||||
- Virus scan results
|
||||
- File download activities
|
||||
- Permission changes
|
||||
|
||||
## 6.11. JSON Processing & Validation
|
||||
|
||||
- JSON Schema Management
|
||||
- ต้องมี centralized JSON schema registry
|
||||
- ต้องรองรับ schema versioning และ migration
|
||||
- ต้องมี schema validation during runtime
|
||||
- Performance Optimization
|
||||
- **Caching:** Cache parsed JSON structures
|
||||
- **Compression:** ใช้ compression สำหรับ JSON ขนาดใหญ่
|
||||
- **Indexing:** Support JSON path indexing สำหรับ query
|
||||
- Error Handling
|
||||
- ต้องมี graceful degradation เมื่อ JSON validation ล้มเหลว
|
||||
- ต้องมี default fallback values
|
||||
- ต้องบันทึก error logs สำหรับ validation failures
|
||||
65
specs/01-requirements/07-testing.md
Normal file
65
specs/01-requirements/07-testing.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# Section 7: Testing Requirements (ข้อกำหนดด้านการทดสอบ)
|
||||
|
||||
---
|
||||
|
||||
title: 'Testing Requirements'
|
||||
version: 1.5.0
|
||||
status: first-draft
|
||||
owner: Nattanin Peancharoen
|
||||
last_updated: 2025-11-30
|
||||
related:
|
||||
|
||||
- specs/02-architecture/data-model.md#correspondence
|
||||
- specs/03-implementation/backend-guidelines.md#correspondencemodule
|
||||
|
||||
---
|
||||
|
||||
## 7.1 Unit Testing
|
||||
|
||||
- ต้องมี unit tests สำหรับ business logic ทั้งหมด
|
||||
- Code coverage อย่างน้อย 70% สำหรับ backend services
|
||||
- Business Logic: 80%+
|
||||
- Controllers: 70%+
|
||||
- Utilities: 90%+
|
||||
- ต้องทดสอบ RBAC permission logic ทุกระดับ
|
||||
|
||||
## 7.2 Integration Testing
|
||||
|
||||
- ทดสอบการทำงานร่วมกันของ modules
|
||||
- ทดสอบ database migrations และ data integrity
|
||||
- ทดสอบ API endpoints ด้วย realistic data
|
||||
|
||||
## 7.3 End-to-End Testing
|
||||
|
||||
- ทดสอบ complete user workflows
|
||||
- ทดสอบ document lifecycle จาก creation ถึง archival
|
||||
- ทดสอบ cross-module integrations
|
||||
|
||||
## 7.4 Security Testing
|
||||
|
||||
- Penetration Testing: ทดสอบ OWASP Top 10 vulnerabilities
|
||||
- Security Audit: Review code สำหรับ security flaws
|
||||
- Virus Scanning Test: ทดสอบ file upload security
|
||||
- Rate Limiting Test: ทดสอบ rate limiting functionality
|
||||
|
||||
## 7.5. Performance Testing
|
||||
|
||||
- Penetration Testing: ทดสอบ OWASP Top 10 vulnerabilities
|
||||
- Security Audit: Review code สำหรับ security flaws
|
||||
- Virus Scanning Test: ทดสอบ file upload security
|
||||
- **Rate Limiting Test:** ทดสอบ rate limiting functionality
|
||||
- **Load Testing:** ทดสอบด้วย realistic workloads
|
||||
- **Stress Testing:** หา breaking points ของระบบ
|
||||
- **Endurance Testing:** ทดสอบการทำงานต่อเนื่องเป็นเวลานาน
|
||||
|
||||
## 7.6. Disaster Recovery Testing
|
||||
|
||||
- ทดสอบ backup และ restoration procedures
|
||||
- ทดสอบ failover mechanisms
|
||||
- ทดสอบ data integrity หลังการ recovery
|
||||
|
||||
## 7.7 Specific Scenario Testing (เพิ่ม)
|
||||
|
||||
- **Race Condition Test:** ทดสอบยิง Request ขอเลขที่เอกสารพร้อมกัน 100 Request
|
||||
- **Transaction Test:** ทดสอบปิดเน็ตระหว่าง Upload ไฟล์ (ตรวจสอบว่าไม่มี Orphan File หรือ Broken Link)
|
||||
- **Permission Test:** ทดสอบ CASL Integration ทั้งฝั่ง Backend และ Frontend ให้ตรงกัน
|
||||
58
specs/01-requirements/README.md
Normal file
58
specs/01-requirements/README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# 📋 Requirements Specification v1.5.0
|
||||
|
||||
## Status: first-draft
|
||||
|
||||
**Date:** 2025-11-30
|
||||
|
||||
---
|
||||
|
||||
## 📑 Table of Contents
|
||||
|
||||
1. [Objectives & Goals](./01-objectives.md)
|
||||
2. [System Architecture & Technology](./02-architecture.md)
|
||||
3. [Functional Requirements](./03-functional-requirements.md)
|
||||
- [3.1 Project & Organization Management](./03.1-project-management.md)
|
||||
- [3.2 Correspondence Management](./03.2-correspondence.md)
|
||||
- [3.3 RFA Management](./03.3-rfa.md)
|
||||
- [3.4 Contract Drawing Management](./03.4-contract-drawing.md)
|
||||
- [3.5 Shop Drawing Management](./03.5-shop-drawing.md)
|
||||
- [3.6 Unified Workflow](./03.6-unified-workflow.md)
|
||||
- [3.7 Transmittals Management](./03.7-transmittals.md)
|
||||
- [3.8 Circulation Sheet Management](./03.8-circulation-sheet.md)
|
||||
- [3.9 Revisions Management](./03.9-revisions.md)
|
||||
- [3.10 File Handling](./03.10-file-handling.md)
|
||||
- [3.11 Document Numbering](./03.11-document-numbering.md)
|
||||
- [3.12 JSON Details](./03.12-json-details.md)
|
||||
4. [Access Control & RBAC](./04-access-control.md)
|
||||
5. [UI/UX Requirements](./05-ui-ux.md)
|
||||
6. [Non-Functional Requirements](./06-non-functional.md)
|
||||
7. [Testing Requirements](./07-testing.md)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Recent Changes
|
||||
|
||||
See [CHANGELOG.md](../../CHANGELOG.md) for detailed version history.
|
||||
|
||||
### v1.4.5 (2025-11-30)
|
||||
|
||||
- ✅ Added comprehensive security requirements
|
||||
- ✅ Enhanced resilience patterns
|
||||
- ✅ Added performance targets
|
||||
- ⚠️ **Breaking:** Changed document numbering from stored procedure to app-level locking
|
||||
|
||||
---
|
||||
|
||||
## 📊 Compliance Matrix
|
||||
|
||||
| Requirement | Status | Owner | Target Release |
|
||||
| ----------------------------- | ----------- | ------------ | -------------- |
|
||||
| FR-001: Correspondence CRUD | ✅ Done | Backend Team | v1.0 |
|
||||
| FR-002: RFA Workflow | In Progress | Backend Team | v1.1 |
|
||||
| NFR-001: API Response < 200ms | Planned | DevOps | v1.2 |
|
||||
|
||||
---
|
||||
|
||||
## 📬 Feedback
|
||||
|
||||
Found issues? [Open an issue](https://github.com/your-org/lcbp3-dms/issues/new?template=spec-issue.md)
|
||||
58
specs/02-architecture/README.md
Normal file
58
specs/02-architecture/README.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# 📋 Architecture Specification v1.5.0
|
||||
|
||||
## Status: first-draft
|
||||
|
||||
**Date:** 2025-11-30
|
||||
|
||||
---
|
||||
|
||||
## 📑 Table of Contents
|
||||
|
||||
1. [General Philosophy](./01-general-philosophy.md)
|
||||
2. [TypeScript](./02-typescript.md)
|
||||
3. [Functional Requirements](./03-functional-requirements.md)
|
||||
- [3.1 Project & Organization Management](./03.1-project-management.md)
|
||||
- [3.2 Correspondence Management](./03.2-correspondence.md)
|
||||
- [3.3 RFA Management](./03.3-rfa.md)
|
||||
- [3.4 Contract Drawing Management](./03.4-contract-drawing.md)
|
||||
- [3.5 Shop Drawing Management](./03.5-shop-drawing.md)
|
||||
- [3.6 Unified Workflow](./03.6-unified-workflow.md)
|
||||
- [3.7 Transmittals Management](./03.7-transmittals.md)
|
||||
- [3.8 Circulation Sheet Management](./03.8-circulation-sheet.md)
|
||||
- [3.9 Revisions Management](./03.9-revisions.md)
|
||||
- [3.10 File Handling](./03.10-file-handling.md)
|
||||
- [3.11 Document Numbering](./03.11-document-numbering.md)
|
||||
- [3.12 JSON Details](./03.12-json-details.md)
|
||||
4. [Access Control & RBAC](./04-access-control.md)
|
||||
5. [UI/UX Requirements](./05-ui-ux.md)
|
||||
6. [Non-Functional Requirements](./06-non-functional.md)
|
||||
7. [Testing Requirements](./07-testing.md)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Recent Changes
|
||||
|
||||
See [CHANGELOG.md](../../CHANGELOG.md) for detailed version history.
|
||||
|
||||
### v1.4.5 (2025-11-30)
|
||||
|
||||
- ✅ Added comprehensive security requirements
|
||||
- ✅ Enhanced resilience patterns
|
||||
- ✅ Added performance targets
|
||||
- ⚠️ **Breaking:** Changed document numbering from stored procedure to app-level locking
|
||||
|
||||
---
|
||||
|
||||
## 📊 Compliance Matrix
|
||||
|
||||
| Requirement | Status | Owner | Target Release |
|
||||
| ----------------------------- | ----------- | ------------ | -------------- |
|
||||
| FR-001: Correspondence CRUD | ✅ Done | Backend Team | v1.0 |
|
||||
| FR-002: RFA Workflow | In Progress | Backend Team | v1.1 |
|
||||
| NFR-001: API Response < 200ms | Planned | DevOps | v1.2 |
|
||||
|
||||
---
|
||||
|
||||
## 📬 Feedback
|
||||
|
||||
Found issues? [Open an issue](https://github.com/your-org/lcbp3-dms/issues/new?template=spec-issue.md)
|
||||
551
specs/02-architecture/api-design.md
Normal file
551
specs/02-architecture/api-design.md
Normal file
@@ -0,0 +1,551 @@
|
||||
# 🌐 API Design Specification
|
||||
|
||||
---
|
||||
|
||||
**title:** 'API Design'
|
||||
**version:** 1.5.0
|
||||
**status:** first-draft
|
||||
**owner:** Nattanin Peancharoen
|
||||
**last_updated:** 2025-11-30
|
||||
**related:**
|
||||
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/02-architecture/system-architecture.md
|
||||
- specs/03-implementation/fullftack-js-v1.5.0.md
|
||||
|
||||
---
|
||||
|
||||
## 📋ภาพรวม (Overview)
|
||||
|
||||
เอกสารนี้กำหนดมาตรฐานการออกแบบ API สำหรับระบบ LCBP3-DMS โดยใช้แนวทาง **API-First Design** ที่เน้นความชัดเจน ความสอดคล้อง และความปลอดภัย
|
||||
|
||||
## 🎯 หลักการออกแบบ API (API Design Principles)
|
||||
|
||||
### 1.1 API-First Approach
|
||||
|
||||
- **ออกแบบ API ก่อนการ Implement:** ทำการออกแบบ API Endpoint และ Data Contract ให้ชัดเจนก่อนเริ่มเขียนโค้ด
|
||||
- **Documentation-Driven:** ใช้ OpenAPI/Swagger เป็นเอกสารอ้างอิงหลัก
|
||||
- **Contract Testing:** ทดสอบ API ตาม Contract ที่กำหนดไว้
|
||||
|
||||
### 1.2 RESTful Principles
|
||||
|
||||
- ใช้ HTTP Methods อย่างถูกต้อง: `GET`, `POST`, `PUT`, `PATCH`, `DELETE`
|
||||
- ใช้ HTTP Status Codes ที่เหมาะสม
|
||||
- Resource-Based URL Design
|
||||
- Stateless Communication
|
||||
|
||||
### 1.3 Consistency & Predictability
|
||||
|
||||
- **Naming Conventions:** ใช้ `kebab-case` สำหรับ URL paths
|
||||
- **Property Naming:** ใช้ `snake_case` สำหรับ JSON properties (สอดคล้องกับ Database Schema)
|
||||
- **Versioning:** รองรับการ Version API ผ่าน URL path (`/api/v1/...`)
|
||||
|
||||
## 🔐 Authentication & Authorization
|
||||
|
||||
### 2.1 Authentication
|
||||
|
||||
- **JWT-Based Authentication:** ใช้ JSON Web Token สำหรับการยืนยันตัวตน
|
||||
- **Token Management:**
|
||||
- Access Token Expiration: 8 ชั่วโมง
|
||||
- Refresh Token Expiration: 7 วัน
|
||||
- Token Rotation: รองรับการหมุนเวียน Refresh Token
|
||||
- Token Revocation: บันทึก Revoked Tokens จนกว่าจะหมดอายุ
|
||||
|
||||
**Endpoints:**
|
||||
|
||||
```typescript
|
||||
POST / api / v1 / auth / login;
|
||||
POST / api / v1 / auth / logout;
|
||||
POST / api / v1 / auth / refresh;
|
||||
POST / api / v1 / auth / change - password;
|
||||
```
|
||||
|
||||
### 2.2 Authorization (RBAC)
|
||||
|
||||
- **4-Level Permission Hierarchy:**
|
||||
|
||||
1. **Global Level:** System-wide permissions (Superadmin)
|
||||
2. **Organization Level:** Organization-specific permissions
|
||||
3. **Project Level:** Project-specific permissions
|
||||
4. **Contract Level:** Contract-specific permissions
|
||||
|
||||
- **Permission Checking:** ใช้ Decorator `@RequirePermission('resource.action')`
|
||||
|
||||
**Example:**
|
||||
|
||||
```typescript
|
||||
@RequirePermission('correspondence.create')
|
||||
@Post('correspondences')
|
||||
async createCorrespondence(@Body() dto: CreateCorrespondenceDto) {
|
||||
// Implementation
|
||||
}
|
||||
```
|
||||
|
||||
### 2.3 Token Payload Optimization
|
||||
|
||||
- JWT Payload เก็บเฉพาะ `userId` และ `scope` ปัจจุบัน
|
||||
- **Permissions Caching:** เก็บ Permission List ใน Redis และดึงมาตรวจสอบเมื่อมี Request
|
||||
|
||||
## 📡 API Conventions
|
||||
|
||||
### 3.1 Base URL Structure
|
||||
|
||||
```
|
||||
https://backend.np-dms.work/api/v1/{resource}
|
||||
```
|
||||
|
||||
### 3.2 HTTP Methods & Usage
|
||||
|
||||
| Method | Usage | Idempotent | Example |
|
||||
| :------- | :----------------------------- | :--------- | :----------------------------------- |
|
||||
| `GET` | ดึงข้อมูล (Read) | ✅ Yes | `GET /api/v1/correspondences` |
|
||||
| `POST` | สร้างข้อมูลใหม่ (Create) | ❌ No\* | `POST /api/v1/correspondences` |
|
||||
| `PUT` | อัปเดตทั้งหมด (Full Update) | ✅ Yes | `PUT /api/v1/correspondences/:id` |
|
||||
| `PATCH` | อัปเดตบางส่วน (Partial Update) | ✅ Yes | `PATCH /api/v1/correspondences/:id` |
|
||||
| `DELETE` | ลบข้อมูล (Soft Delete) | ✅ Yes | `DELETE /api/v1/correspondences/:id` |
|
||||
|
||||
**Note:** `POST` เป็น Idempotent ได้เมื่อใช้ `Idempotency-Key` Header
|
||||
|
||||
### 3.3 HTTP Status Codes
|
||||
|
||||
| Status Code | Usage |
|
||||
| :-------------------------- | :------------------------------- |
|
||||
| `200 OK` | Request สำเร็จ (GET, PUT, PATCH) |
|
||||
| `201 Created` | สร้างข้อมูลสำเร็จ (POST) |
|
||||
| `204 No Content` | ลบสำเร็จ (DELETE) |
|
||||
| `400 Bad Request` | ข้อมูล Request ไม่ถูกต้อง |
|
||||
| `401 Unauthorized` | ไม่มี Token หรือ Token หมดอายุ |
|
||||
| `403 Forbidden` | ไม่มีสิทธิ์เข้าถึง |
|
||||
| `404 Not Found` | ไม่พบข้อมูล |
|
||||
| `409 Conflict` | ข้อมูลซ้ำ หรือ State Conflict |
|
||||
| `422 Unprocessable Entity` | Validation Error |
|
||||
| `429 Too Many Requests` | Rate Limit Exceeded |
|
||||
| `500 Internal Server Error` | Server Error |
|
||||
| `503 Service Unavailable` | Maintenance Mode |
|
||||
|
||||
### 3.4 Request & Response Format
|
||||
|
||||
**Request Headers:**
|
||||
|
||||
```http
|
||||
Content-Type: application/json
|
||||
Authorization: Bearer <access_token>
|
||||
Idempotency-Key: <uuid> # สำหรับ POST/PUT/DELETE
|
||||
```
|
||||
|
||||
**Success Response Format:**
|
||||
|
||||
```typescript
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
// Resource data
|
||||
},
|
||||
"message": "Operation completed successfully"
|
||||
}
|
||||
```
|
||||
|
||||
**Error Response Format:**
|
||||
|
||||
```typescript
|
||||
{
|
||||
"success": false,
|
||||
"error": {
|
||||
"code": "VALIDATION_ERROR",
|
||||
"message": "Validation failed",
|
||||
"details": [
|
||||
{
|
||||
"field": "email",
|
||||
"message": "Invalid email format"
|
||||
}
|
||||
]
|
||||
},
|
||||
"timestamp": "2025-11-30T13:48:20Z",
|
||||
"path": "/api/v1/users"
|
||||
}
|
||||
```
|
||||
|
||||
## 🔄 Idempotency
|
||||
|
||||
### 4.1 Implementation
|
||||
|
||||
- **ทุก Critical Operation** (Create, Update, Delete) ต้องรองรับ Idempotency
|
||||
- Client ส่ง Header: `Idempotency-Key: <uuid>`
|
||||
- Server เช็คว่า Key นี้เคยประมวลผลสำเร็จแล้วหรือไม่
|
||||
- ถ้าเคยทำแล้ว: ส่งผลลัพธ์เดิมกลับไป (ไม่ทำซ้ำ)
|
||||
|
||||
**Example:**
|
||||
|
||||
```http
|
||||
POST /api/v1/correspondences
|
||||
Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"title": "New Correspondence",
|
||||
"type_id": 1
|
||||
}
|
||||
```
|
||||
|
||||
## 📊 Pagination, Filtering & Sorting
|
||||
|
||||
### 5.1 Pagination (Server-Side)
|
||||
|
||||
**Query Parameters:**
|
||||
|
||||
```
|
||||
GET /api/v1/correspondences?page=1&page_size=20
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```typescript
|
||||
{
|
||||
"success": true,
|
||||
"data": [...],
|
||||
"meta": {
|
||||
"current_page": 1,
|
||||
"page_size": 20,
|
||||
"total_items": 150,
|
||||
"total_pages": 8,
|
||||
"has_next_page": true,
|
||||
"has_previous_page": false
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 Filtering
|
||||
|
||||
```
|
||||
GET /api/v1/correspondences?project_id=1&status=PENDING
|
||||
```
|
||||
|
||||
### 5.3 Sorting
|
||||
|
||||
```
|
||||
GET /api/v1/correspondences?sort=created_at&order=desc
|
||||
```
|
||||
|
||||
### 5.4 Combined Example
|
||||
|
||||
```
|
||||
GET /api/v1/correspondences?project_id=1&status=PENDING&page=1&page_size=20&sort=created_at&order=desc
|
||||
```
|
||||
|
||||
## 🛡️ Security Features
|
||||
|
||||
### 6.1 Rate Limiting
|
||||
|
||||
| Endpoint Type | Limit | Scope |
|
||||
| :------------------ | :----------------- | :---- |
|
||||
| Anonymous Endpoints | 100 requests/hour | IP |
|
||||
| Viewer | 500 requests/hour | User |
|
||||
| Editor | 1000 requests/hour | User |
|
||||
| Document Control | 2000 requests/hour | User |
|
||||
| Admin/Superadmin | 5000 requests/hour | User |
|
||||
| File Upload | 50 requests/hour | User |
|
||||
| Search | 500 requests/hour | User |
|
||||
| Authentication | 10 requests/minute | IP |
|
||||
|
||||
**Rate Limit Headers:**
|
||||
|
||||
```http
|
||||
X-RateLimit-Limit: 1000
|
||||
X-RateLimit-Remaining: 999
|
||||
X-RateLimit-Reset: 1638360000
|
||||
```
|
||||
|
||||
### 6.2 Input Validation
|
||||
|
||||
- **DTOs with Class Validator:** ทุก Request ต้องผ่าน Validation
|
||||
- **XSS Protection:** Input Sanitization
|
||||
- **SQL Injection Prevention:** ใช้ ORM (TypeORM) Parameterized Queries
|
||||
- **CSRF Protection:** CSRF Tokens สำหรับ State-Changing Operations
|
||||
|
||||
### 6.3 File Upload Security
|
||||
|
||||
**Endpoint:**
|
||||
|
||||
```
|
||||
POST /api/v1/files/upload
|
||||
```
|
||||
|
||||
**Security Measures:**
|
||||
|
||||
- **Virus Scanning:** ใช้ ClamAV scan ทุกไฟล์
|
||||
- **File Type Validation:** White-list (PDF, DWG, DOCX, XLSX, ZIP)
|
||||
- **File Size Limit:** 50MB per file
|
||||
- **Two-Phase Storage:**
|
||||
1. Upload to `temp/` folder
|
||||
2. Commit to `permanent/{YYYY}/{MM}/` when operation succeeds
|
||||
|
||||
**Response:**
|
||||
|
||||
```typescript
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"temp_id": "uuid",
|
||||
"filename": "document.pdf",
|
||||
"size": 1024000,
|
||||
"mime_type": "application/pdf",
|
||||
"scan_status": "CLEAN"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📦 Core Module APIs
|
||||
|
||||
### 7.1 Correspondence Module
|
||||
|
||||
**Base Path:** `/api/v1/correspondences`
|
||||
|
||||
| Method | Endpoint | Permission | Description |
|
||||
| :----- | :--------------------------------- | :---------------------- | :-------------------- |
|
||||
| GET | `/correspondences` | `correspondence.view` | รายการ Correspondence |
|
||||
| GET | `/correspondences/:id` | `correspondence.view` | รายละเอียด |
|
||||
| POST | `/correspondences` | `correspondence.create` | สร้างใหม่ |
|
||||
| PUT | `/correspondences/:id` | `correspondence.update` | อัปเดตทั้งหมด |
|
||||
| PATCH | `/correspondences/:id` | `correspondence.update` | อัปเดตบางส่วน |
|
||||
| DELETE | `/correspondences/:id` | `correspondence.delete` | ลบ (Soft Delete) |
|
||||
| POST | `/correspondences/:id/revisions` | `correspondence.update` | สร้าง Revision ใหม่ |
|
||||
| GET | `/correspondences/:id/revisions` | `correspondence.view` | ดู Revisions ทั้งหมด |
|
||||
| POST | `/correspondences/:id/attachments` | `correspondence.update` | เพิ่มไฟล์แนบ |
|
||||
|
||||
### 7.2 RFA Module
|
||||
|
||||
**Base Path:** `/api/v1/rfas`
|
||||
|
||||
| Method | Endpoint | Permission | Description |
|
||||
| :----- | :-------------------- | :------------- | :----------------- |
|
||||
| GET | `/rfas` | `rfas.view` | รายการ RFA |
|
||||
| GET | `/rfas/:id` | `rfas.view` | รายละเอียด |
|
||||
| POST | `/rfas` | `rfas.create` | สร้างใหม่ |
|
||||
| PUT | `/rfas/:id` | `rfas.update` | อัปเดต |
|
||||
| DELETE | `/rfas/:id` | `rfas.delete` | ลบ |
|
||||
| POST | `/rfas/:id/respond` | `rfas.respond` | ตอบกลับ RFA |
|
||||
| POST | `/rfas/:id/approve` | `rfas.approve` | อนุมัติ RFA |
|
||||
| POST | `/rfas/:id/revisions` | `rfas.update` | สร้าง Revision |
|
||||
| GET | `/rfas/:id/workflow` | `rfas.view` | ดู Workflow Status |
|
||||
|
||||
### 7.3 Drawing Module
|
||||
|
||||
**Base Path:** `/api/v1/drawings`
|
||||
|
||||
**Shop Drawings:**
|
||||
|
||||
| Method | Endpoint | Permission | Description |
|
||||
| :----- | :----------------------------- | :---------------- | :------------------ |
|
||||
| GET | `/shop-drawings` | `drawings.view` | รายการ Shop Drawing |
|
||||
| POST | `/shop-drawings` | `drawings.upload` | อัปโหลดใหม่ |
|
||||
| GET | `/shop-drawings/:id/revisions` | `drawings.view` | ดู Revisions |
|
||||
|
||||
**Contract Drawings:**
|
||||
|
||||
| Method | Endpoint | Permission | Description |
|
||||
| :----- | :------------------- | :---------------- | :---------------------- |
|
||||
| GET | `/contract-drawings` | `drawings.view` | รายการ Contract Drawing |
|
||||
| POST | `/contract-drawings` | `drawings.upload` | อัปโหลดใหม่ |
|
||||
|
||||
### 7.4 Project Module
|
||||
|
||||
**Base Path:** `/api/v1/projects`
|
||||
|
||||
| Method | Endpoint | Permission | Description |
|
||||
| :----- | :------------------------ | :----------------------- | :----------------- |
|
||||
| GET | `/projects` | `projects.view` | รายการโครงการ |
|
||||
| GET | `/projects/:id` | `projects.view` | รายละเอียด |
|
||||
| POST | `/projects` | `projects.create` | สร้างโครงการใหม่ |
|
||||
| PUT | `/projects/:id` | `projects.update` | อัปเดต |
|
||||
| POST | `/projects/:id/contracts` | `contracts.create` | สร้าง Contract |
|
||||
| GET | `/projects/:id/parties` | `projects.view` | ดู Project Parties |
|
||||
| POST | `/projects/:id/parties` | `project_parties.manage` | เพิ่ม Party |
|
||||
|
||||
### 7.5 User & Auth Module
|
||||
|
||||
**Base Path:** `/api/v1/users`, `/api/v1/auth`
|
||||
|
||||
**Authentication:**
|
||||
|
||||
```typescript
|
||||
POST / api / v1 / auth / login;
|
||||
POST / api / v1 / auth / logout;
|
||||
POST / api / v1 / auth / refresh;
|
||||
POST / api / v1 / auth / change - password;
|
||||
POST / api / v1 / auth / reset - password;
|
||||
```
|
||||
|
||||
**User Management:**
|
||||
|
||||
```typescript
|
||||
GET /api/v1/users # List users
|
||||
GET /api/v1/users/:id # User details
|
||||
POST /api/v1/users # Create user
|
||||
PUT /api/v1/users/:id # Update user
|
||||
DELETE /api/v1/users/:id # Delete user
|
||||
POST /api/v1/users/:id/roles # Assign roles
|
||||
GET /api/v1/users/me # Current user info
|
||||
GET /api/v1/users/me/permissions # Current user permissions
|
||||
```
|
||||
|
||||
### 7.6 Search Module
|
||||
|
||||
**Base Path:** `/api/v1/search`
|
||||
|
||||
```typescript
|
||||
GET /api/v1/search?q=<query>&type=<correspondence|rfa|drawing>&project_id=<id>
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```typescript
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"results": [...],
|
||||
"aggregations": {
|
||||
"by_type": { "correspondence": 10, "rfa": 5 },
|
||||
"by_status": { "PENDING": 8, "APPROVED": 7 }
|
||||
}
|
||||
},
|
||||
"meta": {
|
||||
"total": 15,
|
||||
"took_ms": 45
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 🔔 Notification API
|
||||
|
||||
**Base Path:** `/api/v1/notifications`
|
||||
|
||||
```typescript
|
||||
GET /api/v1/notifications # List notifications
|
||||
GET /api/v1/notifications/:id # Notification details
|
||||
PATCH /api/v1/notifications/:id/read # Mark as read
|
||||
DELETE /api/v1/notifications/:id # Delete notification
|
||||
```
|
||||
|
||||
## 📈 Reporting & Export APIs
|
||||
|
||||
**Base Path:** `/api/v1/reports`
|
||||
|
||||
```typescript
|
||||
GET /api/v1/reports/correspondences?format=csv&project_id=1&from=2025-01-01&to=2025-12-31
|
||||
GET /api/v1/reports/rfas?format=excel&project_id=1
|
||||
GET /api/v1/reports/dashboard # Dashboard KPIs
|
||||
```
|
||||
|
||||
**Supported Formats:**
|
||||
|
||||
- `csv` - CSV file
|
||||
- `excel` - Excel file (.xlsx)
|
||||
- `pdf` - PDF file
|
||||
|
||||
## 🔧 Workflow Engine API
|
||||
|
||||
**Base Path:** `/api/v1/workflows`
|
||||
|
||||
```typescript
|
||||
GET /api/v1/workflows/definitions # List workflow definitions
|
||||
GET /api/v1/workflows/definitions/:id # Definition details
|
||||
POST /api/v1/workflows/instances # Create workflow instance
|
||||
GET /api/v1/workflows/instances/:id # Instance details
|
||||
POST /api/v1/workflows/instances/:id/transition # Execute transition
|
||||
GET /api/v1/workflows/instances/:id/history # View history
|
||||
```
|
||||
|
||||
## ⚡ Performance Optimization
|
||||
|
||||
### 11.1 Caching Strategy
|
||||
|
||||
**Cache Headers:**
|
||||
|
||||
```http
|
||||
Cache-Control: max-age=3600, private
|
||||
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"
|
||||
```
|
||||
|
||||
**Cache TTL:**
|
||||
|
||||
- Master Data: 1 hour
|
||||
- User Sessions: 30 minutes
|
||||
- Search Results: 15 minutes
|
||||
- File Metadata: 1 hour
|
||||
|
||||
### 11.2 Response Compression
|
||||
|
||||
```http
|
||||
Accept-Encoding: gzip, deflate, br
|
||||
Content-Encoding: gzip
|
||||
```
|
||||
|
||||
## 🧪 Testing & Documentation
|
||||
|
||||
### 12.1 API Documentation
|
||||
|
||||
- **Swagger/OpenAPI:** Auto-generated จาก NestJS Decorators
|
||||
- **URL:** `https://backend.np-dms.work/api/docs`
|
||||
|
||||
### 12.2 Testing Strategy
|
||||
|
||||
- **Unit Tests:** Test individual controllers & services
|
||||
- **Integration Tests:** Test API endpoints with database
|
||||
- **E2E Tests:** Test complete user flows
|
||||
- **Contract Tests:** Verify API contracts
|
||||
|
||||
## 🚦 Health Check & Monitoring
|
||||
|
||||
```typescript
|
||||
GET /health # Health check endpoint
|
||||
GET /health/ready # Readiness probe
|
||||
GET /health/live # Liveness probe
|
||||
GET /metrics # Prometheus metrics
|
||||
```
|
||||
|
||||
**Response:**
|
||||
|
||||
```typescript
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 86400,
|
||||
"checks": {
|
||||
"database": "ok",
|
||||
"redis": "ok",
|
||||
"elasticsearch": "ok"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 📝 API Versioning Strategy
|
||||
|
||||
### 14.1 Versioning Approach
|
||||
|
||||
- **URL-Based Versioning:** `/api/v1/...`, `/api/v2/...`
|
||||
- **Backward Compatibility:** รองรับ API เวอร์ชันเก่าอย่างน้อย 1 เวอร์ชัน
|
||||
- **Deprecation Headers:**
|
||||
|
||||
```http
|
||||
X-API-Deprecation-Warning: This endpoint will be deprecated on 2026-01-01
|
||||
X-API-Deprecation-Info: https://docs.np-dms.work/migration/v2
|
||||
```
|
||||
|
||||
## 🎯 Best Practices Summary
|
||||
|
||||
1. **ใช้ DTOs สำหรับ Validation ทุก Request**
|
||||
2. **ส่ง Idempotency-Key สำหรับ Critical Operations**
|
||||
3. **ใช้ Proper HTTP Status Codes**
|
||||
4. **Implement Rate Limiting บน Client Side**
|
||||
5. **Handle Errors Gracefully**
|
||||
6. **Cache Frequently-Accessed Data**
|
||||
7. **Use Pagination สำหรับ Large Datasets**
|
||||
8. **Document ทุก Endpoint ด้วย Swagger**
|
||||
|
||||
---
|
||||
|
||||
**Document Control:**
|
||||
|
||||
- **Version:** 1.5.0
|
||||
- **Status:** First Draft
|
||||
- **Last Updated:** 2025-11-30
|
||||
- **Owner:** Nattanin Peancharoen
|
||||
0
specs/02-architecture/data-model.md
Normal file
0
specs/02-architecture/data-model.md
Normal file
953
specs/02-architecture/system-architecture.md
Normal file
953
specs/02-architecture/system-architecture.md
Normal file
@@ -0,0 +1,953 @@
|
||||
# 🏗️ System Architecture Specification
|
||||
|
||||
---
|
||||
|
||||
**title:** 'System Architecture'
|
||||
**version:** 1.5.0
|
||||
**status:** first-draft
|
||||
**owner:** Nattanin Peancharoen
|
||||
**last_updated:** 2025-11-30
|
||||
**related:**
|
||||
|
||||
- specs/01-requirements/02-architecture.md
|
||||
- specs/01-requirements/06-non-functional.md
|
||||
- specs/03-implementation/fullftack-js-v1.5.0.md
|
||||
|
||||
---
|
||||
|
||||
## 📋 ภาพรวม (Overview)
|
||||
|
||||
เอกสารนี้อธิบายสถาปัตยกรรมระบบ LCBP3-DMS (Laem Chabang Port Phase 3 - Document Management System) ที่ใช้แนวทาง **Headless/API-First Architecture** พร้อมการ Deploy บน QNAP Server ผ่าน Container Station
|
||||
|
||||
## 🎯 Architecture Principles
|
||||
|
||||
### 1.1 Core Principles
|
||||
|
||||
1. **Data Integrity First:** ความถูกต้องของข้อมูลต้องมาก่อนทุกอย่าง
|
||||
2. **Security by Design:** รักษาความปลอดภัยที่ทุกชั้น
|
||||
3. **Scalability:** รองรับการเติบโตในอนาคต
|
||||
4. **Resilience:** ทนทานต่อ Failure และ Recovery ได้รวดเร็ว
|
||||
5. **Observability:** ติดตามและวิเคราะห์สถานะระบบได้ง่าย
|
||||
|
||||
### 1.2 Architecture Style
|
||||
|
||||
- **Headless CMS Architecture:** แยก Frontend และ Backend เป็นอิสระ
|
||||
- **API-First:** Backend เป็น API Server ที่ Frontend หรือ Third-party สามารถเรียกใช้ได้
|
||||
- **Microservices-Ready:** ออกแบบเป็น Modular Architecture พร้อมแยกเป็น Microservices ในอนาคต
|
||||
|
||||
## 🏢 Infrastructure & Deployment
|
||||
|
||||
### 2.1 Server Infrastructure
|
||||
|
||||
- **Server:** QNAP TS-473A
|
||||
- CPU: AMD Ryzen V1500B
|
||||
- RAM: 32GB
|
||||
- Storage: /share/dms-data
|
||||
- **IP Address:** 159.192.126.103
|
||||
- **Domain:** np-dms.work, www.np-dms.work
|
||||
- **Containerization:** Docker & Docker Compose via Container Station
|
||||
- **Development Environment:** VS Code/Cursor on Windows 11
|
||||
|
||||
### 2.2 Network Architecture
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
Internet[Internet] --> NPM[Nginx Proxy Manager<br/>npm.np-dms.work]
|
||||
NPM --> Frontend[Next.js Frontend<br/>lcbp3.np-dms.work]
|
||||
NPM --> Backend[NestJS Backend<br/>backend.np-dms.work]
|
||||
NPM --> PMA[phpMyAdmin<br/>pma.np-dms.work]
|
||||
NPM --> N8N[n8n Workflow<br/>n8n.np-dms.work]
|
||||
NPM --> Gitea[Gitea Git<br/>git.np-dms.work]
|
||||
|
||||
Backend --> MariaDB[(MariaDB 10.11<br/>db.np-dms.work)]
|
||||
Backend --> Redis[(Redis Cache)]
|
||||
Backend --> Elastic[Elasticsearch]
|
||||
Backend --> Storage[File Storage<br/>/share/dms-data]
|
||||
|
||||
N8N --> Line[LINE Notify]
|
||||
Backend --> Email[Email Server]
|
||||
```
|
||||
|
||||
**Docker Network:**
|
||||
|
||||
- Network Name: `lcbp3`
|
||||
- ทุก Service เชื่อมต่อผ่าน Internal Docker Network เพื่อความปลอดภัย
|
||||
|
||||
### 2.3 Configuration Management
|
||||
|
||||
> [!WARNING] > **ข้อจำกัดสำคัญ:** QNAP Container Station ไม่รองรับการใช้ `.env` files ในการกำหนด Environment Variables
|
||||
|
||||
**Configuration Strategy:**
|
||||
|
||||
1. **Production/Staging:**
|
||||
|
||||
- ใช้ `docker-compose.yml` สำหรับกำหนด Environment Variables
|
||||
- ห้ามระบุ Sensitive Secrets (Password, Keys) ใน `docker-compose.yml` หลัก
|
||||
- ใช้ `docker-compose.override.yml` (gitignored) สำหรับ Secrets
|
||||
- พิจารณาใช้ Docker Secrets หรือ Hashicorp Vault
|
||||
|
||||
2. **Development:**
|
||||
|
||||
- ใช้ `docker-compose.override.yml` สำหรับ Local Secrets
|
||||
- ไฟล์หลักใส่ค่า Dummy/Placeholder
|
||||
|
||||
3. **Validation:**
|
||||
- ใช้ Joi/Zod validate Environment Variables ตอน App Start
|
||||
- Throw Error ทันทีหากขาด Variable สำคัญ
|
||||
|
||||
## 🔧 Core Services
|
||||
|
||||
### 3.1 Service Overview
|
||||
|
||||
| Service | Application Name | Domain | Technology | Purpose |
|
||||
| :---------------- | :--------------- | :------------------ | :----------------------- | :-------------------------- |
|
||||
| **Frontend** | lcbp3-frontend | lcbp3.np-dms.work | Next.js 14+ (App Router) | Web Application UI |
|
||||
| **Backend** | lcbp3-backend | backend.np-dms.work | NestJS (TypeScript) | API Server & Business Logic |
|
||||
| **Database** | lcbp3-db | db.np-dms.work | MariaDB 10.11 | Primary Database |
|
||||
| **DB Management** | lcbp3-db | pma.np-dms.work | phpMyAdmin | Database Admin UI |
|
||||
| **Reverse Proxy** | lcbp3-npm | npm.np-dms.work | Nginx Proxy Manager | Reverse Proxy & SSL |
|
||||
| **Workflow** | lcbp3-n8n | n8n.np-dms.work | n8n | Workflow Automation |
|
||||
| **Git** | git | git.np-dms.work | Gitea | Self-hosted Git |
|
||||
| **Cache** | - | - | Redis | Caching & Locking |
|
||||
| **Search** | - | - | Elasticsearch | Full-text Search |
|
||||
|
||||
### 3.2 Frontend (Next.js)
|
||||
|
||||
**Stack:**
|
||||
|
||||
- **Framework:** Next.js 14+ with App Router
|
||||
- **Language:** TypeScript (ESM)
|
||||
- **Styling:** Tailwind CSS + PostCSS
|
||||
- **Components:** shadcn/ui
|
||||
- **State Management:**
|
||||
- Server State: TanStack Query (React Query)
|
||||
- Form State: React Hook Form + Zod
|
||||
- UI State: useState/useReducer
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- Render Web UI สำหรับผู้ใช้
|
||||
- จัดการ User Interactions
|
||||
- เรียก Backend API
|
||||
- Client-side Validation
|
||||
- Responsive Design (Desktop + Mobile)
|
||||
|
||||
### 3.3 Backend (NestJS)
|
||||
|
||||
**Stack:**
|
||||
|
||||
- **Framework:** NestJS (Node.js + TypeScript)
|
||||
- **ORM:** TypeORM
|
||||
- **Authentication:** JWT + Passport
|
||||
- **Authorization:** CASL (RBAC)
|
||||
- **Validation:** class-validator + class-transformer
|
||||
- **Documentation:** Swagger/OpenAPI
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- ให้บริการ RESTful API
|
||||
- Business Logic Processing
|
||||
- Authentication & Authorization
|
||||
- Data Validation
|
||||
- Database Operations
|
||||
- File Upload Handling (Two-Phase Storage)
|
||||
- Workflow Engine
|
||||
- Background Jobs (Notifications, Cleanup)
|
||||
|
||||
### 3.4 Database (MariaDB 10.11)
|
||||
|
||||
**Features:**
|
||||
|
||||
- **JSON Support:** จัดเก็บ `details` fields (Dynamic Schema)
|
||||
- **Virtual Columns:** Index JSON fields สำหรับ Performance
|
||||
- **Partitioning:** สำหรับ `audit_logs` และ `notifications`
|
||||
- **Optimistic Locking:** ใช้ `@VersionColumn()` ป้องกัน Race Condition
|
||||
|
||||
**Key Tables:**
|
||||
|
||||
- Users & Permissions: `users`, `roles`, `permissions`, `user_roles`
|
||||
- Projects: `projects`, `organizations`, `contracts`, `project_parties`
|
||||
- Documents: `correspondences`, `rfas`, `shop_drawings`, `contract_drawings`
|
||||
- Workflow: `workflow_definitions`, `workflow_instances`, `workflow_history`
|
||||
- Files: `attachments`, `correspondence_attachments`, etc.
|
||||
- Audit: `audit_logs`
|
||||
|
||||
### 3.5 Redis
|
||||
|
||||
**Use Cases:**
|
||||
|
||||
1. **Distributed Locking:** Document Numbering, Critical Operations
|
||||
2. **Session Caching:** User Permissions, Profile Data
|
||||
3. **Master Data Cache:** Roles, Permissions, Organizations (TTL: 1 hour)
|
||||
4. **Queue Management:** BullMQ for Background Jobs
|
||||
5. **Rate Limiting:** Track API Request Counts
|
||||
|
||||
### 3.6 Elasticsearch
|
||||
|
||||
**Use Cases:**
|
||||
|
||||
- **Full-text Search:** Search across Correspondence, RFA, Drawings
|
||||
- **Advanced Filtering:** Multi-criteria Search
|
||||
- **Aggregations:** Statistics และ Dashboard Data
|
||||
|
||||
**Indexing Strategy:**
|
||||
|
||||
- Index อัตโนมัติเมื่อ Create/Update เอกสาร
|
||||
- Async Indexing ผ่าน Queue (ไม่ Block Main Request)
|
||||
|
||||
## 🧱 Backend Module Architecture
|
||||
|
||||
### 4.1 Modular Design
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Core Modules"
|
||||
Common[CommonModule<br/>Shared Services]
|
||||
Auth[AuthModule<br/>JWT & Guards]
|
||||
User[UserModule<br/>User Management]
|
||||
end
|
||||
|
||||
subgraph "Business Modules"
|
||||
Project[ProjectModule<br/>Projects & Contracts]
|
||||
Corr[CorrespondenceModule<br/>Correspondences]
|
||||
RFA[RfaModule<br/>RFA Management]
|
||||
Drawing[DrawingModule<br/>Shop & Contract Drawings]
|
||||
Circ[CirculationModule<br/>Circulation Sheets]
|
||||
Trans[TransmittalModule<br/>Transmittals]
|
||||
end
|
||||
|
||||
subgraph "Supporting Modules"
|
||||
Workflow[WorkflowEngineModule<br/>Unified Workflow]
|
||||
Numbering[DocumentNumberingModule<br/>Auto Numbering]
|
||||
Search[SearchModule<br/>Elasticsearch]
|
||||
Master[MasterModule<br/>Master Data]
|
||||
JSON[JsonSchemaModule<br/>JSON Validation]
|
||||
end
|
||||
|
||||
Corr --> Workflow
|
||||
RFA --> Workflow
|
||||
Circ --> Workflow
|
||||
|
||||
Corr --> Numbering
|
||||
RFA --> Numbering
|
||||
|
||||
Search --> Corr
|
||||
Search --> RFA
|
||||
Search --> Drawing
|
||||
```
|
||||
|
||||
### 4.2 Module Descriptions
|
||||
|
||||
#### 4.2.1 CommonModule
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- Database Configuration
|
||||
- FileStorageService (Two-Phase Upload)
|
||||
- AuditLogService
|
||||
- NotificationService
|
||||
- Shared DTOs, Guards, Interceptors
|
||||
|
||||
#### 4.2.2 AuthModule
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- JWT Token Management
|
||||
- Authentication Guards
|
||||
- 4-Level Permission Checking:
|
||||
- Global (Superadmin)
|
||||
- Organization
|
||||
- Project
|
||||
- Contract
|
||||
- Token Refresh & Revocation
|
||||
|
||||
#### 4.2.3 UserModule
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- User CRUD Operations
|
||||
- Role Assignment
|
||||
- Permission Management
|
||||
- User Profile Management
|
||||
|
||||
#### 4.2.4 ProjectModule
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- Project Management
|
||||
- Contract Management
|
||||
- Organization Management
|
||||
- Project Parties & Contract Parties
|
||||
|
||||
#### 4.2.5 CorrespondenceModule
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- Correspondence CRUD
|
||||
- Revision Management
|
||||
- Attachment Handling
|
||||
- Workflow Integration (Routing)
|
||||
|
||||
#### 4.2.6 RfaModule
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- RFA CRUD
|
||||
- RFA Item Management
|
||||
- Workflow Integration (Approval Process)
|
||||
- Respond/Approve Actions
|
||||
|
||||
#### 4.2.7 DrawingModule
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- Shop Drawing Management
|
||||
- Contract Drawing Management
|
||||
- Drawing Categories
|
||||
- Revision Tracking
|
||||
- Drawing References
|
||||
|
||||
#### 4.2.8 CirculationModule
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- Circulation Sheet Management
|
||||
- Circulation Templates
|
||||
- Assignees Management
|
||||
- Workflow Integration (Internal Circulation)
|
||||
|
||||
#### 4.2.9 WorkflowEngineModule (Core)
|
||||
|
||||
> [!IMPORTANT] > **Unified Workflow Engine** - ระบบกลางสำหรับจัดการ Workflow ทั้งหมด
|
||||
|
||||
**Features:**
|
||||
|
||||
- DSL-Based Workflow Definitions (JSON Configuration)
|
||||
- State Machine Management
|
||||
- Workflow Instance Tracking
|
||||
- History & Audit Trail
|
||||
- Workflow Versioning
|
||||
|
||||
**Entities:**
|
||||
|
||||
- `WorkflowDefinition`: กำหนด Workflow Template
|
||||
- `WorkflowInstance`: Instance ที่กำลังรัน
|
||||
- `WorkflowHistory`: ประวัติการเปลี่ยน State
|
||||
|
||||
**Integration:**
|
||||
|
||||
- CorrespondenceModule → Routing Workflow
|
||||
- RfaModule → Approval Workflow
|
||||
- CirculationModule → Internal Circulation Workflow
|
||||
|
||||
#### 4.2.10 DocumentNumberingModule (Internal)
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- Auto-generate Document Numbers
|
||||
- Token-Based Generator: `{CONTRACT}-{TYPE}-{DISCIPLINE}-{SEQ:4}`
|
||||
- **Double-Lock Mechanism:**
|
||||
- Layer 1: Redis Distributed Lock
|
||||
- Layer 2: Optimistic Database Lock (`@VersionColumn()`)
|
||||
|
||||
**Algorithm:**
|
||||
|
||||
1. Parse Template → Identify Required Tokens
|
||||
2. Acquire Redis Lock (Key: `project_id:type_id:discipline_id:year`)
|
||||
3. Query `document_number_counters` Table
|
||||
4. Increment Counter (Check Version)
|
||||
5. Generate Final Number
|
||||
6. Release Lock
|
||||
7. Retry on Conflict (Exponential Backoff)
|
||||
|
||||
#### 4.2.11 SearchModule
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- Elasticsearch Integration
|
||||
- Full-text Search across Documents
|
||||
- Advanced Filtering
|
||||
- Search Result Aggregation
|
||||
|
||||
#### 4.2.12 JsonSchemaModule (Internal)
|
||||
|
||||
**Responsibilities:**
|
||||
|
||||
- JSON Schema Validation (AJV)
|
||||
- Schema Versioning & Migration
|
||||
- Dynamic Schema Generation
|
||||
- Data Transformation
|
||||
|
||||
## 📊 Data Flow Architecture
|
||||
|
||||
### 5.1 Main Request Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as Client (Browser)
|
||||
participant NPM as Nginx Proxy
|
||||
participant BE as Backend (NestJS)
|
||||
participant Redis as Redis Cache
|
||||
participant DB as MariaDB
|
||||
participant ES as Elasticsearch
|
||||
|
||||
Client->>NPM: HTTP Request + JWT
|
||||
NPM->>BE: Forward Request
|
||||
|
||||
BE->>BE: Rate Limit Check
|
||||
BE->>BE: Validate Input (DTO)
|
||||
BE->>BE: JWT Auth Guard
|
||||
BE->>Redis: Get User Permissions
|
||||
Redis-->>BE: Permission Data
|
||||
BE->>BE: RBAC Guard (Check Permission)
|
||||
|
||||
BE->>DB: Query Data
|
||||
DB-->>BE: Return Data
|
||||
|
||||
BE->>BE: Business Logic Processing
|
||||
BE->>DB: Save Changes (Transaction)
|
||||
BE->>ES: Index for Search
|
||||
BE->>Redis: Invalidate Cache
|
||||
|
||||
BE->>DB: Audit Log
|
||||
BE-->>Client: JSON Response
|
||||
```
|
||||
|
||||
### 5.2 File Upload Flow (Two-Phase Storage)
|
||||
|
||||
> [!IMPORTANT] > **Two-Phase Storage** ป้องกัน Orphan Files และรักษา Data Integrity
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client
|
||||
participant Backend
|
||||
participant ClamAV as Virus Scanner
|
||||
participant TempStorage as Temp Storage
|
||||
participant PermStorage as Permanent Storage
|
||||
participant DB as Database
|
||||
|
||||
Client->>Backend: Upload File
|
||||
Backend->>ClamAV: Scan Virus
|
||||
ClamAV-->>Backend: Scan Result (CLEAN/INFECTED)
|
||||
|
||||
alt File is CLEAN
|
||||
Backend->>TempStorage: Save to temp/
|
||||
Backend-->>Client: Return temp_id
|
||||
|
||||
Client->>Backend: POST Create Document (include temp_id)
|
||||
Backend->>DB: BEGIN Transaction
|
||||
Backend->>DB: Create Document Record
|
||||
Backend->>PermStorage: Move temp/ → permanent/{YYYY}/{MM}/
|
||||
Backend->>DB: Create Attachment Record
|
||||
Backend->>DB: COMMIT Transaction
|
||||
Backend-->>Client: Success Response
|
||||
else File is INFECTED
|
||||
Backend-->>Client: Error: Virus Detected
|
||||
end
|
||||
|
||||
Note over Backend,TempStorage: Cron Job: Delete temp files > 24h
|
||||
```
|
||||
|
||||
### 5.3 Document Numbering Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Service as Correspondence Service
|
||||
participant Numbering as Numbering Service
|
||||
participant Redis
|
||||
participant DB as MariaDB
|
||||
|
||||
Service->>Numbering: generateNextNumber(context)
|
||||
Numbering->>Numbering: Parse Template
|
||||
Numbering->>Redis: ACQUIRE Lock (project:type:year)
|
||||
|
||||
alt Lock Acquired
|
||||
Redis-->>Numbering: Lock Success
|
||||
Numbering->>DB: SELECT counter (with version)
|
||||
DB-->>Numbering: current_number, version
|
||||
Numbering->>DB: UPDATE counter SET last_number = X, version = version + 1 WHERE version = old_version
|
||||
|
||||
alt Update Success
|
||||
DB-->>Numbering: Success
|
||||
Numbering->>Numbering: Generate Final Number
|
||||
Numbering->>Redis: RELEASE Lock
|
||||
Numbering-->>Service: Document Number
|
||||
else Version Conflict (Race Condition)
|
||||
DB-->>Numbering: Update Failed
|
||||
Numbering->>Redis: RELEASE Lock
|
||||
Numbering->>Numbering: Retry (Exponential Backoff)
|
||||
end
|
||||
else Lock Failed
|
||||
Redis-->>Numbering: Lock Timeout
|
||||
Numbering->>Numbering: Retry or Fail
|
||||
end
|
||||
```
|
||||
|
||||
### 5.4 Workflow Execution Flow
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User
|
||||
participant Module as Correspondence Module
|
||||
participant Engine as Workflow Engine
|
||||
participant DB
|
||||
participant Notify as Notification Service
|
||||
|
||||
User->>Module: Create Correspondence
|
||||
Module->>Engine: createWorkflowInstance(definition_id, entity_id)
|
||||
Engine->>DB: Create workflow_instance
|
||||
Engine->>DB: Set initial state
|
||||
Engine-->>Module: Instance Created
|
||||
Module-->>User: Success
|
||||
|
||||
User->>Module: Execute Action (e.g., "Send")
|
||||
Module->>Engine: executeTransition(instance_id, action)
|
||||
Engine->>DB: Check current state
|
||||
Engine->>Engine: Validate transition (DSL)
|
||||
|
||||
alt Transition Valid
|
||||
Engine->>DB: Update state
|
||||
Engine->>DB: Create workflow_history
|
||||
Engine->>Notify: Trigger Notification
|
||||
Notify->>Notify: Queue Email/Line
|
||||
Engine-->>Module: Transition Success
|
||||
Module-->>User: Action Completed
|
||||
else Invalid Transition
|
||||
Engine-->>Module: Error: Invalid State Transition
|
||||
Module-->>User: Error Response
|
||||
end
|
||||
```
|
||||
|
||||
## 🛡️ Security Architecture
|
||||
|
||||
### 6.1 Security Layers
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Layer 1: Network Security"
|
||||
SSL[SSL/TLS<br/>Nginx Proxy Manager]
|
||||
Firewall[Firewall Rules<br/>QNAP]
|
||||
end
|
||||
|
||||
subgraph "Layer 2: Application Security"
|
||||
RateLimit[Rate Limiting]
|
||||
CSRF[CSRF Protection]
|
||||
XSS[XSS Prevention]
|
||||
Input[Input Validation]
|
||||
end
|
||||
|
||||
subgraph "Layer 3: Authentication"
|
||||
JWT[JWT Tokens]
|
||||
Refresh[Token Refresh]
|
||||
Revoke[Token Revocation]
|
||||
end
|
||||
|
||||
subgraph "Layer 4: Authorization"
|
||||
RBAC[4-Level RBAC]
|
||||
Guards[Permission Guards]
|
||||
CASL[CASL Rules]
|
||||
end
|
||||
|
||||
subgraph "Layer 5: Data Security"
|
||||
Encrypt[Data Encryption]
|
||||
Audit[Audit Logs]
|
||||
Backup[Backups]
|
||||
end
|
||||
|
||||
subgraph "Layer 6: File Security"
|
||||
Virus[Virus Scanning]
|
||||
FileType[Type Validation]
|
||||
FileAccess[Access Control]
|
||||
end
|
||||
```
|
||||
|
||||
### 6.2 Authentication & Authorization Details
|
||||
|
||||
**JWT Token Structure:**
|
||||
|
||||
```json
|
||||
{
|
||||
"sub": "user_id",
|
||||
"scope": "organization_id|project_id|contract_id",
|
||||
"iat": 1638360000,
|
||||
"exp": 1638388800
|
||||
}
|
||||
```
|
||||
|
||||
**Permission Checking Logic:**
|
||||
|
||||
1. Extract JWT from `Authorization: Bearer <token>`
|
||||
2. Validate Token (Signature, Expiration)
|
||||
3. Get User Permissions from Redis Cache (Key: `user:{user_id}:permissions`)
|
||||
4. Check Permission based on Context:
|
||||
- Global Permission (Superadmin)
|
||||
- Organization Permission
|
||||
- Project Permission (if in project context)
|
||||
- Contract Permission (if in contract context)
|
||||
5. Allow if **any level** grants permission (Most Permissive)
|
||||
|
||||
### 6.3 Rate Limiting
|
||||
|
||||
| Endpoint Category | Limit | Tracking |
|
||||
| :---------------- | :------------ | :--------- |
|
||||
| Anonymous | 100 req/hour | IP Address |
|
||||
| Authentication | 10 req/min | IP Address |
|
||||
| File Upload | 50 req/hour | User ID |
|
||||
| Search | 500 req/hour | User ID |
|
||||
| Viewer | 500 req/hour | User ID |
|
||||
| Editor | 1000 req/hour | User ID |
|
||||
| Document Control | 2000 req/hour | User ID |
|
||||
| Admin | 5000 req/hour | User ID |
|
||||
|
||||
**Implementation:** `rate-limiter-flexible` library with Redis backend
|
||||
|
||||
### 6.4 Input Validation
|
||||
|
||||
**Frontend (Client-Side):**
|
||||
|
||||
- React Hook Form + Zod Schema Validation
|
||||
- Sanitize User Inputs before Display
|
||||
|
||||
**Backend (Server-Side):**
|
||||
|
||||
- class-validator DTOs
|
||||
- Whitelist Validation (`@ValidateIf`, `@IsEnum`, etc.)
|
||||
- Transform Pipes
|
||||
|
||||
**File Upload Validation:**
|
||||
|
||||
1. **File Type Validation:**
|
||||
|
||||
- White-list: PDF, DWG, DOCX, XLSX, ZIP
|
||||
- Magic Number Verification (ไม่ใช่แค่ extension)
|
||||
|
||||
2. **File Size Validation:**
|
||||
|
||||
- Maximum: 50MB per file
|
||||
|
||||
3. **Virus Scanning:**
|
||||
- ClamAV Integration
|
||||
- Scan before saving to temp storage
|
||||
|
||||
### 6.5 OWASP Top 10 Protection
|
||||
|
||||
| Vulnerability | Protection Measure |
|
||||
| :-------------------------------- | :----------------------------------- |
|
||||
| SQL Injection | Parameterized Queries (TypeORM) |
|
||||
| XSS | Input Sanitization + Output Encoding |
|
||||
| CSRF | CSRF Tokens (State-changing ops) |
|
||||
| Broken Auth | JWT + Secure Token Management |
|
||||
| Security Misconfiguration | Security Headers (Helmet.js) |
|
||||
| Sensitive Data Exposure | Encryption + Secure Storage |
|
||||
| Insufficient Logging | Comprehensive Audit Logs |
|
||||
| Insecure Deserialization | Input Validation |
|
||||
| Using Known Vulnerable Components | Regular Dependency Updates |
|
||||
|
||||
## 📈 Performance & Scalability
|
||||
|
||||
### 7.1 Caching Strategy
|
||||
|
||||
| Data Type | Cache Location | TTL | Invalidation |
|
||||
| :--------------- | :------------- | :------ | :------------------------ |
|
||||
| User Permissions | Redis | 30 min | On role/permission change |
|
||||
| Master Data | Redis | 1 hour | On update |
|
||||
| Search Results | Redis | 15 min | Time-based |
|
||||
| File Metadata | Redis | 1 hour | On file update |
|
||||
| Session Data | Redis | 8 hours | On logout |
|
||||
|
||||
### 7.2 Database Optimization
|
||||
|
||||
**Indexes:**
|
||||
|
||||
- Foreign Keys (Auto-indexed)
|
||||
- Search Columns (`idx_cor_project`, `idx_rfa_status`, etc.)
|
||||
- JSON Virtual Columns (for frequently queried JSON fields)
|
||||
|
||||
**Partitioning:**
|
||||
|
||||
- `audit_logs`: Partitioned by Year
|
||||
- `notifications`: Partitioned by Month
|
||||
- Automated Partition Creation (Cron Job)
|
||||
|
||||
**Query Optimization:**
|
||||
|
||||
- Use Views for Complex Queries (`v_current_correspondences`, `v_user_tasks`)
|
||||
- Pagination for Large Datasets
|
||||
- Eager/Lazy Loading Strategy
|
||||
|
||||
### 7.3 Performance Targets
|
||||
|
||||
| Metric | Target | Measurement |
|
||||
| :---------------------------------- | :------ | :------------- |
|
||||
| API Response Time (90th percentile) | < 200ms | Simple CRUD |
|
||||
| Search Query Performance | < 500ms | Complex Search |
|
||||
| File Upload Processing | < 30s | 50MB file |
|
||||
| Concurrent Users | 100+ | Simultaneous |
|
||||
| Cache Hit Ratio | > 80% | Master Data |
|
||||
| Application Startup | < 30s | Cold Start |
|
||||
|
||||
## 🔄 Resilience & Error Handling
|
||||
|
||||
### 8.1 Resilience Patterns
|
||||
|
||||
**Circuit Breaker:**
|
||||
|
||||
- Applied to: Elasticsearch, Email Service, LINE Notify
|
||||
- Threshold: 5 failures in 1 minute
|
||||
- Timeout: 30 seconds
|
||||
- Recovery: Half-open after 1 minute
|
||||
|
||||
**Retry Mechanism:**
|
||||
|
||||
- Strategy: Exponential Backoff
|
||||
- Max Retries: 3
|
||||
- Applied to: External API Calls, Document Numbering
|
||||
|
||||
**Graceful Degradation:**
|
||||
|
||||
- Search Service Down → Return cached results or basic search
|
||||
- Email Service Down → Queue for later retry
|
||||
- LINE Notify Down → Log error, continue operation
|
||||
|
||||
### 8.2 Error Handling
|
||||
|
||||
**Backend:**
|
||||
|
||||
- Global Exception Filter
|
||||
- Structured Error Response Format
|
||||
- Error Logging with Context (Winston)
|
||||
- Don't Expose Internal Details in Error Messages
|
||||
|
||||
**Frontend:**
|
||||
|
||||
- Error Boundaries (React)
|
||||
- Toast Notifications
|
||||
- Fallback UI Components
|
||||
- Retry Mechanisms for Failed Requests
|
||||
|
||||
## 📊 Monitoring & Observability
|
||||
|
||||
### 9.1 Health Checks
|
||||
|
||||
**Endpoints:**
|
||||
|
||||
```
|
||||
GET /health # Overall health
|
||||
GET /health/ready # Readiness probe
|
||||
GET /health/live # Liveness probe
|
||||
```
|
||||
|
||||
**Checks:**
|
||||
|
||||
- Database Connection
|
||||
- Redis Connection
|
||||
- Elasticsearch Connection
|
||||
- Disk Space
|
||||
- Memory Usage
|
||||
|
||||
### 9.2 Metrics Collection
|
||||
|
||||
**Application Metrics:**
|
||||
|
||||
- Request Rate (req/sec)
|
||||
- Response Time (p50, p90, p99)
|
||||
- Error Rate
|
||||
- Active Connections
|
||||
|
||||
**Business Metrics:**
|
||||
|
||||
- Documents Created per Day
|
||||
- Workflow Completion Rate
|
||||
- User Activity
|
||||
- Search Query Performance
|
||||
|
||||
**Infrastructure Metrics:**
|
||||
|
||||
- CPU Usage
|
||||
- Memory Usage
|
||||
- Disk I/O
|
||||
- Network Throughput
|
||||
|
||||
### 9.3 Logging Strategy
|
||||
|
||||
> [!WARNING] > **QNAP Storage Constraints:** ต้องจำกัดปริมาณ Logs
|
||||
|
||||
**Log Levels:**
|
||||
|
||||
- **Production:** WARN and ERROR only
|
||||
- **Staging:** INFO for critical business flows
|
||||
- **Development:** DEBUG allowed
|
||||
|
||||
**Structured Logging:**
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp": "2025-11-30T13:48:20Z",
|
||||
"level": "INFO",
|
||||
"service": "backend",
|
||||
"module": "CorrespondenceModule",
|
||||
"action": "create",
|
||||
"user_id": 1,
|
||||
"ip_address": "192.168.1.100",
|
||||
"duration_ms": 45,
|
||||
"message": "Correspondence created successfully"
|
||||
}
|
||||
```
|
||||
|
||||
**Log Rotation:**
|
||||
|
||||
- Rotate Daily
|
||||
- Keep 7 days
|
||||
- Compress Old Logs
|
||||
|
||||
### 9.4 Audit Logging
|
||||
|
||||
**Scope:**
|
||||
|
||||
- All CRUD Operations on Critical Data
|
||||
- Permission Changes
|
||||
- Login Attempts (Success/Failure)
|
||||
- File Downloads
|
||||
- Workflow State Changes
|
||||
|
||||
**Audit Log Fields:**
|
||||
|
||||
- `user_id`
|
||||
- `action` (e.g., `correspondence.create`)
|
||||
- `entity_type`, `entity_id`
|
||||
- `old_values`, `new_values` (for updates)
|
||||
- `ip_address`, `user_agent`
|
||||
- `timestamp`
|
||||
|
||||
## 💾 Backup & Disaster Recovery
|
||||
|
||||
### 10.1 Backup Strategy
|
||||
|
||||
**Database Backup:**
|
||||
|
||||
- **Frequency:** Daily (Automated)
|
||||
- **Method:** Full Backup + Transaction Logs
|
||||
- **Retention:** 30 days
|
||||
- **Tool:** QNAP HBS 3 or mysqldump
|
||||
|
||||
**File Storage Backup:**
|
||||
|
||||
- **Frequency:** Daily
|
||||
- **Path:** `/share/dms-data`
|
||||
- **Method:** Incremental Backup
|
||||
- **Retention:** 30 days
|
||||
- **Tool:** QNAP Snapshot or rsync
|
||||
|
||||
### 10.2 Disaster Recovery
|
||||
|
||||
**Recovery Objectives:**
|
||||
|
||||
- **RTO (Recovery Time Objective):** < 4 hours
|
||||
- **RPO (Recovery Point Objective):** < 1 hour
|
||||
|
||||
**Recovery Procedures:**
|
||||
|
||||
1. **Database Restoration:**
|
||||
|
||||
- Restore latest full backup
|
||||
- Apply transaction logs to point-in-time
|
||||
- Verify data integrity
|
||||
|
||||
2. **File Storage Restoration:**
|
||||
|
||||
- Restore from QNAP snapshot
|
||||
- Verify file permissions
|
||||
|
||||
3. **Application Redeployment:**
|
||||
|
||||
- Deploy from known-good Docker images
|
||||
- Verify health checks
|
||||
|
||||
4. **Data Integrity Verification:**
|
||||
- Run consistency checks
|
||||
- Verify critical business data
|
||||
|
||||
## 🏗️ Deployment Architecture
|
||||
|
||||
### 11.1 Container Deployment
|
||||
|
||||
**Docker Compose Services:**
|
||||
|
||||
```yaml
|
||||
services:
|
||||
frontend:
|
||||
image: lcbp3-frontend:latest
|
||||
networks: [lcbp3]
|
||||
depends_on: [backend]
|
||||
|
||||
backend:
|
||||
image: lcbp3-backend:latest
|
||||
networks: [lcbp3]
|
||||
depends_on: [mariadb, redis, elasticsearch]
|
||||
|
||||
mariadb:
|
||||
image: mariadb:10.11
|
||||
networks: [lcbp3]
|
||||
volumes: [/share/dms-data/mysql:/var/lib/mysql]
|
||||
|
||||
redis:
|
||||
image: redis:7-alpine
|
||||
networks: [lcbp3]
|
||||
|
||||
elasticsearch:
|
||||
image: elasticsearch:8.x
|
||||
networks: [lcbp3]
|
||||
|
||||
nginx-proxy-manager:
|
||||
image: jc21/nginx-proxy-manager:latest
|
||||
networks: [lcbp3]
|
||||
ports: [80:80, 443:443]
|
||||
```
|
||||
|
||||
### 11.2 CI/CD Pipeline (Future)
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Git[Gitea Repository] --> Build[Build & Test]
|
||||
Build --> StagingDeploy[Deploy to Staging]
|
||||
StagingDeploy --> Test[Run E2E Tests]
|
||||
Test --> Manual[Manual Approval]
|
||||
Manual --> ProdDeploy[Deploy to Production]
|
||||
ProdDeploy --> Monitor[Monitor & Alert]
|
||||
```
|
||||
|
||||
## 🎯 Future Enhancements
|
||||
|
||||
### 12.1 Scalability Improvements
|
||||
|
||||
- [ ] Separate into Microservices (when needed)
|
||||
- [ ] Add Load Balancer (HAProxy/Nginx)
|
||||
- [ ] Database Replication (Master-Slave)
|
||||
- [ ] Message Queue (RabbitMQ/Kafka) for async processing
|
||||
|
||||
### 12.2 Advanced Features
|
||||
|
||||
- [ ] AI-Powered Document Classification
|
||||
- [ ] Advanced Analytics & Reporting
|
||||
- [ ] Mobile Native Apps
|
||||
- [ ] Blockchain Integration for Document Integrity
|
||||
|
||||
### 12.3 Infrastructure
|
||||
|
||||
- [ ] Multi-Region Deployment
|
||||
- [ ] CDN for Static Assets
|
||||
- [ ] Automated Failover
|
||||
- [ ] Blue-Green Deployment
|
||||
|
||||
---
|
||||
|
||||
**Document Control:**
|
||||
|
||||
- **Version:** 1.5.0
|
||||
- **Status:** First Draft
|
||||
- **Last Updated:** 2025-11-30
|
||||
- **Owner:** Nattanin Peancharoen
|
||||
|
||||
```
|
||||
|
||||
```
|
||||
456
specs/03-implementation/backend-guidelines.md
Normal file
456
specs/03-implementation/backend-guidelines.md
Normal file
@@ -0,0 +1,456 @@
|
||||
# Backend Development Guidelines
|
||||
|
||||
**สำหรับ:** NAP-DMS LCBP3 Backend (NestJS + TypeScript)
|
||||
**เวอร์ชัน:** 1.4.5
|
||||
**อัปเดต:** 2025-11-30
|
||||
|
||||
---
|
||||
|
||||
## 🎯 หลักการพื้นฐาน
|
||||
|
||||
ระบบ Backend ของเรามุ่งเน้น **"Data Integrity First"** - ความถูกต้องของข้อมูลต้องมาก่อน ตามด้วย Security และ UX
|
||||
|
||||
### หลักการหลัก
|
||||
|
||||
1. **Strict Typing:** ใช้ TypeScript เต็มรูปแบบ ห้ามใช้ `any`
|
||||
2. **Data Integrity:** ป้องกัน Race Condition ด้วย Optimistic Locking + Redis Lock
|
||||
3. **Security First:** ทุก Endpoint ต้องผ่าน Authentication, Authorization, และ Input Validation
|
||||
4. **Idempotency:** Request สำคัญต้องทำซ้ำได้โดยไม่เกิดผลกระทบซ้ำซ้อน
|
||||
5. **Resilience:** รองรับ Network Failure และ External Service Downtime
|
||||
|
||||
---
|
||||
|
||||
## 📁 โครงสร้างโปรเจกต์
|
||||
|
||||
```
|
||||
backend/
|
||||
├── src/
|
||||
│ ├── common/ # Shared utilities, decorators, guards
|
||||
│ │ ├── auth/ # Authentication module
|
||||
│ │ ├── config/ # Configuration management
|
||||
│ │ ├── decorators/ # Custom decorators
|
||||
│ │ ├── guards/ # Auth guards, RBAC
|
||||
│ │ ├── interceptors/ # Logging, transform, idempotency
|
||||
│ │ └── file-storage/ # Two-phase file storage
|
||||
│ ├── modules/ # Business modules (domain-driven)
|
||||
│ │ ├── user/
|
||||
│ │ ├── project/
|
||||
│ │ ├── correspondence/
|
||||
│ │ ├── rfa/
|
||||
│ │ ├── workflow-engine/
|
||||
│ │ └── ...
|
||||
│ └── database/
|
||||
│ ├── migrations/
|
||||
│ └── seeds/
|
||||
├── test/ # E2E tests
|
||||
└── scripts/ # Utility scripts
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔐 Security Guidelines
|
||||
|
||||
### 1. Authentication & Authorization
|
||||
|
||||
**JWT Authentication:**
|
||||
|
||||
```typescript
|
||||
// ใช้ @UseGuards(JwtAuthGuard) สำหรับ Protected Routes
|
||||
@Controller('projects')
|
||||
@UseGuards(JwtAuthGuard)
|
||||
export class ProjectController {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
**RBAC (4 ระดับ):**
|
||||
|
||||
```typescript
|
||||
// ใช้ @RequirePermission() Decorator
|
||||
@Post(':id/contracts')
|
||||
@RequirePermission('contract.create', { scope: 'project' })
|
||||
async createContract() {
|
||||
// Level 1: Global Permission
|
||||
// Level 2: Organization Permission
|
||||
// Level 3: Project Permission
|
||||
// Level 4: Contract Permission
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Input Validation
|
||||
|
||||
**ใช้ DTOs พร้อม class-validator:**
|
||||
|
||||
```typescript
|
||||
import { IsNotEmpty, IsUUID, MaxLength } from 'class-validator';
|
||||
|
||||
export class CreateCorrespondenceDto {
|
||||
@IsNotEmpty({ message: 'ต้องระบุโปรเจกต์' })
|
||||
@IsUUID('4', { message: 'รูปแบบ Project ID ไม่ถูกต้อง' })
|
||||
project_id: string;
|
||||
|
||||
@IsNotEmpty()
|
||||
@MaxLength(500)
|
||||
title: string;
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Rate Limiting
|
||||
|
||||
```typescript
|
||||
// กำหนด Rate Limit ตาม User Type
|
||||
@UseGuards(RateLimitGuard)
|
||||
@RateLimit({ points: 100, duration: 3600 }) // 100 requests/hour
|
||||
@Post('upload')
|
||||
async uploadFile() { }
|
||||
```
|
||||
|
||||
### 4. Secrets Management
|
||||
|
||||
- **Production:** ใช้ Docker Environment Variables (ไม่ใส่ใน docker-compose.yml)
|
||||
- **Development:** ใช้ `docker-compose.override.yml` (gitignored)
|
||||
- **Validation:** Validate Environment Variables ตอน Start App
|
||||
|
||||
```typescript
|
||||
// src/common/config/env.validation.ts
|
||||
import * as Joi from 'joi';
|
||||
|
||||
export const envValidationSchema = Joi.object({
|
||||
DATABASE_URL: Joi.string().required(),
|
||||
JWT_SECRET: Joi.string().min(32).required(),
|
||||
REDIS_URL: Joi.string().required(),
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ Database Best Practices
|
||||
|
||||
### 1. Optimistic Locking
|
||||
|
||||
**ใช้ @VersionColumn() ป้องกัน Race Condition:**
|
||||
|
||||
```typescript
|
||||
@Entity()
|
||||
export class DocumentNumberCounter {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@Column()
|
||||
last_number: number;
|
||||
|
||||
@VersionColumn() // Auto-increment on update
|
||||
version: number;
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Virtual Columns สำหรับ JSON
|
||||
|
||||
**สร้าง Index สำหรับ JSON field ที่ใช้ Search บ่อย:**
|
||||
|
||||
```sql
|
||||
-- Migration Script
|
||||
ALTER TABLE correspondence_revisions
|
||||
ADD COLUMN ref_project_id INT GENERATED ALWAYS AS
|
||||
(JSON_UNQUOTE(JSON_EXTRACT(details, '$.projectId'))) VIRTUAL;
|
||||
|
||||
CREATE INDEX idx_ref_project_id ON correspondence_revisions(ref_project_id);
|
||||
```
|
||||
|
||||
### 3. Soft Delete
|
||||
|
||||
```typescript
|
||||
// Base Entity
|
||||
@Entity()
|
||||
export abstract class BaseEntity {
|
||||
@PrimaryGeneratedColumn('uuid')
|
||||
id: string;
|
||||
|
||||
@CreateDateColumn()
|
||||
created_at: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updated_at: Date;
|
||||
|
||||
@DeleteDateColumn()
|
||||
deleted_at: Date; // NULL = Active, NOT NULL = Soft Deleted
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📦 Core Modules
|
||||
|
||||
### 1. DocumentNumberingModule
|
||||
|
||||
**Double-Lock Mechanism:**
|
||||
|
||||
```typescript
|
||||
@Injectable()
|
||||
export class DocumentNumberingService {
|
||||
async generateNextNumber(context: NumberingContext): Promise<string> {
|
||||
const lockKey = `doc_num:${context.projectId}:${context.typeId}`;
|
||||
|
||||
// Layer 1: Redis Lock (2-5 seconds TTL)
|
||||
const lock = await this.redisLock.acquire(lockKey, 3000);
|
||||
|
||||
try {
|
||||
// Layer 2: Optimistic DB Lock
|
||||
const counter = await this.counterRepo.findOne({
|
||||
where: context,
|
||||
lock: { mode: 'optimistic' },
|
||||
});
|
||||
|
||||
counter.last_number++;
|
||||
await this.counterRepo.save(counter); // Throws if version changed
|
||||
|
||||
return this.formatNumber(counter);
|
||||
} finally {
|
||||
await lock.release();
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 2. FileStorageService (Two-Phase)
|
||||
|
||||
**Phase 1: Upload to Temp**
|
||||
|
||||
```typescript
|
||||
@Post('upload')
|
||||
async uploadFile(@UploadedFile() file: Express.Multer.File) {
|
||||
// 1. Virus Scan
|
||||
await this.virusScan(file);
|
||||
|
||||
// 2. Save to temp/
|
||||
const tempId = await this.fileStorage.saveToTemp(file);
|
||||
|
||||
// 3. Return temp_id
|
||||
return { temp_id: tempId, expires_at: addHours(new Date(), 24) };
|
||||
}
|
||||
```
|
||||
|
||||
**Phase 2: Commit to Permanent**
|
||||
|
||||
```typescript
|
||||
async createCorrespondence(dto: CreateDto, tempFileIds: string[]) {
|
||||
return this.dataSource.transaction(async (manager) => {
|
||||
// 1. Create Correspondence
|
||||
const correspondence = await manager.save(Correspondence, dto);
|
||||
|
||||
// 2. Commit Files (ภายใน Transaction)
|
||||
await this.fileStorage.commitFiles(tempFileIds, correspondence.id, manager);
|
||||
|
||||
return correspondence;
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**Cleanup Job:**
|
||||
|
||||
```typescript
|
||||
@Cron('0 */6 * * *') // ทุก 6 ชั่วโมง
|
||||
async cleanupOrphanFiles() {
|
||||
const expiredFiles = await this.attachmentRepo.find({
|
||||
where: {
|
||||
is_temporary: true,
|
||||
expires_at: LessThan(new Date()),
|
||||
},
|
||||
});
|
||||
|
||||
for (const file of expiredFiles) {
|
||||
await this.deleteFile(file.file_path);
|
||||
await this.attachmentRepo.remove(file);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Idempotency Interceptor
|
||||
|
||||
```typescript
|
||||
@Injectable()
|
||||
export class IdempotencyInterceptor implements NestInterceptor {
|
||||
async intercept(context: ExecutionContext, next: CallHandler) {
|
||||
const request = context.switchToHttp().getRequest();
|
||||
const idempotencyKey = request.headers['idempotency-key'];
|
||||
|
||||
if (!idempotencyKey) {
|
||||
throw new BadRequestException('Idempotency-Key required');
|
||||
}
|
||||
|
||||
// ตรวจสอบ Cache
|
||||
const cached = await this.redis.get(`idempotency:${idempotencyKey}`);
|
||||
if (cached) {
|
||||
return of(JSON.parse(cached)); // Return ผลลัพธ์เดิม
|
||||
}
|
||||
|
||||
// Execute & Cache Result
|
||||
return next.handle().pipe(
|
||||
tap(async (response) => {
|
||||
await this.redis.set(
|
||||
`idempotency:${idempotencyKey}`,
|
||||
JSON.stringify(response),
|
||||
'EX',
|
||||
86400 // 24 hours
|
||||
);
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Workflow Engine Integration
|
||||
|
||||
**ห้ามสร้างตาราง Routing แยก** - ใช้ Unified Workflow Engine
|
||||
|
||||
```typescript
|
||||
@Injectable()
|
||||
export class CorrespondenceWorkflowService {
|
||||
constructor(private workflowEngine: WorkflowEngineService) {}
|
||||
|
||||
async submitCorrespondence(corrId: string, templateId: string) {
|
||||
// สร้าง Workflow Instance
|
||||
const instance = await this.workflowEngine.createInstance({
|
||||
definition_name: 'CORRESPONDENCE_ROUTING',
|
||||
entity_type: 'correspondence',
|
||||
entity_id: corrId,
|
||||
template_id: templateId,
|
||||
});
|
||||
|
||||
// Execute Initial Transition
|
||||
await this.workflowEngine.executeTransition(instance.id, 'SUBMIT');
|
||||
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Testing Standards
|
||||
|
||||
### 1. Unit Tests
|
||||
|
||||
```typescript
|
||||
describe('DocumentNumberingService', () => {
|
||||
let service: DocumentNumberingService;
|
||||
let mockRedisLock: jest.Mocked<RedisLock>;
|
||||
|
||||
beforeEach(async () => {
|
||||
const module = await Test.createTestingModule({
|
||||
providers: [
|
||||
DocumentNumberingService,
|
||||
{ provide: RedisLock, useValue: mockRedisLock },
|
||||
],
|
||||
}).compile();
|
||||
|
||||
service = module.get(DocumentNumberingService);
|
||||
});
|
||||
|
||||
it('should generate unique numbers concurrently', async () => {
|
||||
// Test concurrent number generation
|
||||
const promises = Array(10)
|
||||
.fill(null)
|
||||
.map(() => service.generateNextNumber(context));
|
||||
|
||||
const results = await Promise.all(promises);
|
||||
const unique = new Set(results);
|
||||
|
||||
expect(unique.size).toBe(10); // ไม่มีเลขซ้ำ
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 2. E2E Tests
|
||||
|
||||
```typescript
|
||||
describe('Correspondence API (e2e)', () => {
|
||||
it('should create correspondence with idempotency', async () => {
|
||||
const idempotencyKey = uuidv4();
|
||||
|
||||
// Request 1
|
||||
const response1 = await request(app.getHttpServer())
|
||||
.post('/correspondences')
|
||||
.set('Idempotency-Key', idempotencyKey)
|
||||
.send(createDto);
|
||||
|
||||
expect(response1.status).toBe(201);
|
||||
|
||||
// Request 2 (Same Key)
|
||||
const response2 = await request(app.getHttpServer())
|
||||
.post('/correspondences')
|
||||
.set('Idempotency-Key', idempotencyKey)
|
||||
.send(createDto);
|
||||
|
||||
expect(response2.status).toBe(201);
|
||||
expect(response2.body.id).toBe(response1.body.id); // Same entity
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📊 Logging & Monitoring
|
||||
|
||||
### 1. Winston Logger
|
||||
|
||||
```typescript
|
||||
// src/modules/monitoring/logger/winston.config.ts
|
||||
export const winstonConfig = {
|
||||
level: process.env.NODE_ENV === 'production' ? 'warn' : 'debug',
|
||||
format: winston.format.combine(
|
||||
winston.format.timestamp(),
|
||||
winston.format.json()
|
||||
),
|
||||
transports: [
|
||||
new winston.transports.Console(),
|
||||
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
|
||||
],
|
||||
};
|
||||
```
|
||||
|
||||
### 2. Audit Logging
|
||||
|
||||
```typescript
|
||||
@Post(':id/approve')
|
||||
@UseInterceptors(AuditLogInterceptor)
|
||||
async approve(@Param('id') id: string, @CurrentUser() user: User) {
|
||||
// AuditLogInterceptor จะบันทึก:
|
||||
// - user_id
|
||||
// - action: 'correspondence.approve'
|
||||
// - entity_type: 'correspondence'
|
||||
// - entity_id: id
|
||||
// - ip_address
|
||||
// - timestamp
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚫 Anti-Patterns (สิ่งที่ห้ามทำ)
|
||||
|
||||
1. ❌ **ห้ามใช้ SQL Triggers** สำหรับ Business Logic
|
||||
2. ❌ **ห้ามใช้ .env** ใน Production (ใช้ Docker ENV)
|
||||
3. ❌ **ห้ามใช้ `any` Type**
|
||||
4. ❌ **ห้าม Hardcode Secrets**
|
||||
5. ❌ **ห้ามสร้างตาราง Routing แยก** (ใช้ Workflow Engine)
|
||||
6. ❌ **ห้ามใช้ console.log** (ใช้ Logger)
|
||||
|
||||
---
|
||||
|
||||
## 📚 เอกสารอ้างอิง
|
||||
|
||||
- [FullStack Guidelines](./fullftack-js-V1.5.0.md)
|
||||
- [Backend Plan v1.4.5](../../docs/2_Backend_Plan_V1_4_5.md)
|
||||
- [Data Dictionary](../../docs/4_Data_Dictionary_V1_4_5.md)
|
||||
- [Workflow Engine Plan](../../docs/2_Backend_Plan_V1_4_4.Phase6A.md)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Update History
|
||||
|
||||
| Version | Date | Changes |
|
||||
| ------- | ---------- | ---------------------------------- |
|
||||
| 1.0.0 | 2025-11-30 | Initial backend guidelines created |
|
||||
653
specs/03-implementation/frontend-guidelines.md
Normal file
653
specs/03-implementation/frontend-guidelines.md
Normal file
@@ -0,0 +1,653 @@
|
||||
# Frontend Development Guidelines
|
||||
|
||||
**สำหรับ:** NAP-DMS LCBP3 Frontend (Next.js + TypeScript)
|
||||
**เวอร์ชัน:** 1.4.5
|
||||
**อัปเดต:** 2025-11-30
|
||||
|
||||
---
|
||||
|
||||
## 🎯 หลักการพื้นฐาน
|
||||
|
||||
ระบบ Frontend ของเรามุ่งเน้น **User Experience First** - ประสบการณ์ผู้ใช้ที่ราบรื่น รวดเร็ว และใช้งานง่าย
|
||||
|
||||
### หลักการหลัก
|
||||
|
||||
1. **Type Safety:** ใช้ TypeScript Strict Mode ตลอดทั้งโปรเจกต์
|
||||
2. **Responsive Design:** รองรับทุกขนาดหน้าจอ (Mobile-first approach)
|
||||
3. **Performance:** Optimize การโหลดข้อมูล ใช้ Caching อย่างชาญฉลาด
|
||||
4. **Accessibility:** ทุก Component ต้องรองรับ Screen Reader และ Keyboard Navigation
|
||||
5. **Offline Support:** Auto-save Drafts และ Silent Token Refresh
|
||||
|
||||
---
|
||||
|
||||
## 📁 โครงสร้างโปรเจกต์
|
||||
|
||||
```
|
||||
frontend/
|
||||
├── app/ # Next.js App Router
|
||||
│ ├── (auth)/ # Auth routes (login, register)
|
||||
│ ├── (dashboard)/ # Protected dashboard routes
|
||||
│ ├── api/ # API routes (NextAuth)
|
||||
│ └── layout.tsx
|
||||
├── components/
|
||||
│ ├── ui/ # shadcn/ui components
|
||||
│ ├── custom/ # Custom components
|
||||
│ ├── forms/ # Form components
|
||||
│ ├── layout/ # Layout components (Navbar, Sidebar)
|
||||
│ └── tables/ # Data table components
|
||||
├── lib/
|
||||
│ ├── api/ # API client (Axios)
|
||||
│ ├── hooks/ # Custom React hooks
|
||||
│ ├── services/ # API service functions
|
||||
│ └── stores/ # Zustand stores
|
||||
├── types/ # TypeScript types & DTOs
|
||||
└── providers/ # Context providers
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🎨 UI/UX Guidelines
|
||||
|
||||
### 1. Design System - Tailwind CSS
|
||||
|
||||
**ใช้ Tailwind Utilities เท่านั้น:**
|
||||
|
||||
```tsx
|
||||
// ✅ Good
|
||||
<div className="flex items-center gap-4 rounded-lg border p-4">
|
||||
<Button variant="outline">Cancel</Button>
|
||||
</div>
|
||||
|
||||
// ❌ Bad - Inline styles
|
||||
<div style={{ display: 'flex', padding: '16px' }}>
|
||||
```
|
||||
|
||||
**Responsive Design:**
|
||||
|
||||
```tsx
|
||||
<div
|
||||
className="
|
||||
grid
|
||||
grid-cols-1 /* Mobile: 1 column */
|
||||
md:grid-cols-2 /* Tablet: 2 columns */
|
||||
lg:grid-cols-3 /* Desktop: 3 columns */
|
||||
gap-4
|
||||
"
|
||||
>
|
||||
{items.map((item) => (
|
||||
<Card key={item.id} />
|
||||
))}
|
||||
</div>
|
||||
```
|
||||
|
||||
### 2. shadcn/ui Components
|
||||
|
||||
**ใช้ shadcn/ui สำหรับ UI Components:**
|
||||
|
||||
```tsx
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||||
|
||||
export function Dashboard() {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>งานของฉัน</CardTitle>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Button>สร้างเอกสารใหม่</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. Responsive Data Tables
|
||||
|
||||
**Mobile: Card View, Desktop: Table View**
|
||||
|
||||
```tsx
|
||||
export function ResponsiveTable({ data }: { data: Correspondence[] }) {
|
||||
return (
|
||||
<>
|
||||
{/* Desktop Table */}
|
||||
<div className="hidden md:block">
|
||||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>เลขที่เอกสาร</TableHead>
|
||||
<TableHead>เรื่อง</TableHead>
|
||||
<TableHead>สถานะ</TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{data.map((item) => (
|
||||
<TableRow key={item.id}>
|
||||
<TableCell>{item.doc_number}</TableCell>
|
||||
<TableCell>{item.title}</TableCell>
|
||||
<TableCell>
|
||||
<Badge>{item.status}</Badge>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</div>
|
||||
|
||||
{/* Mobile Card View */}
|
||||
<div className="md:hidden space-y-4">
|
||||
{data.map((item) => (
|
||||
<Card key={item.id}>
|
||||
<CardContent className="pt-6">
|
||||
<div className="space-y-2">
|
||||
<div className="text-sm text-muted-foreground">
|
||||
เลขที่เอกสาร
|
||||
</div>
|
||||
<div className="font-medium">{item.doc_number}</div>
|
||||
<div className="text-sm text-muted-foreground">เรื่อง</div>
|
||||
<div>{item.title}</div>
|
||||
<Badge>{item.status}</Badge>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🗄️ State Management
|
||||
|
||||
### 1. Server State - TanStack Query
|
||||
|
||||
**ใช้สำหรับข้อมูลจาก API:**
|
||||
|
||||
```tsx
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
|
||||
|
||||
// Fetch data
|
||||
export function useCorrespondences(projectId: string) {
|
||||
return useQuery({
|
||||
queryKey: ['correspondences', projectId],
|
||||
queryFn: () => correspondenceService.getAll(projectId),
|
||||
staleTime: 5 * 60 * 1000, // 5 minutes
|
||||
});
|
||||
}
|
||||
|
||||
// Mutation with optimistic update
|
||||
export function useCreateCorrespondence() {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation({
|
||||
mutationFn: correspondenceService.create,
|
||||
onMutate: async (newCorrespondence) => {
|
||||
// Optimistic update
|
||||
await queryClient.cancelQueries({ queryKey: ['correspondences'] });
|
||||
const previous = queryClient.getQueryData(['correspondences']);
|
||||
|
||||
queryClient.setQueryData(['correspondences'], (old: any) => [
|
||||
...old,
|
||||
newCorrespondence,
|
||||
]);
|
||||
|
||||
return { previous };
|
||||
},
|
||||
onError: (err, newCorrespondence, context) => {
|
||||
// Rollback on error
|
||||
queryClient.setQueryData(['correspondences'], context?.previous);
|
||||
},
|
||||
onSuccess: () => {
|
||||
queryClient.invalidateQueries({ queryKey: ['correspondences'] });
|
||||
},
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 2. Form State - React Hook Form + Zod
|
||||
|
||||
```tsx
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import * as z from 'zod';
|
||||
|
||||
// Schema Definition
|
||||
const formSchema = z.object({
|
||||
title: z.string().min(1, 'กรุณาระบุหัวเรื่อง').max(500),
|
||||
project_id: z.string().uuid('กรุณาเลือกโปรเจกต์'),
|
||||
type_id: z.string().uuid('กรุณาเลือกประเภทเอกสาร'),
|
||||
});
|
||||
|
||||
type FormData = z.infer<typeof formSchema>;
|
||||
|
||||
// Form Component
|
||||
export function CorrespondenceForm() {
|
||||
const form = useForm<FormData>({
|
||||
resolver: zodResolver(formSchema),
|
||||
defaultValues: {
|
||||
title: '',
|
||||
project_id: '',
|
||||
type_id: '',
|
||||
},
|
||||
});
|
||||
|
||||
const onSubmit = async (data: FormData) => {
|
||||
await createCorrespondence(data);
|
||||
};
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||
<FormField
|
||||
control={form.control}
|
||||
name="title"
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>หัวเรื่อง</FormLabel>
|
||||
<FormControl>
|
||||
<Input {...field} />
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
<Button type="submit">บันทึก</Button>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
### 3. UI State - Zustand
|
||||
|
||||
```tsx
|
||||
import { create } from 'zustand';
|
||||
import { persist } from 'zustand/middleware';
|
||||
|
||||
// Draft Store (with localStorage persistence)
|
||||
interface DraftStore {
|
||||
drafts: Record<string, any>;
|
||||
saveDraft: (formKey: string, data: any) => void;
|
||||
loadDraft: (formKey: string) => any;
|
||||
clearDraft: (formKey: string) => void;
|
||||
}
|
||||
|
||||
export const useDraftStore = create<DraftStore>()(
|
||||
persist(
|
||||
(set, get) => ({
|
||||
drafts: {},
|
||||
saveDraft: (formKey, data) =>
|
||||
set((state) => ({
|
||||
drafts: { ...state.drafts, [formKey]: data },
|
||||
})),
|
||||
loadDraft: (formKey) => get().drafts[formKey],
|
||||
clearDraft: (formKey) =>
|
||||
set((state) => {
|
||||
const { [formKey]: _, ...rest } = state.drafts;
|
||||
return { drafts: rest };
|
||||
}),
|
||||
}),
|
||||
{ name: 'correspondence-drafts' }
|
||||
)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🔌 API Integration
|
||||
|
||||
### 1. Axios Client Setup
|
||||
|
||||
```typescript
|
||||
// lib/api/client.ts
|
||||
import axios from 'axios';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
const apiClient = axios.create({
|
||||
baseURL: process.env.NEXT_PUBLIC_API_URL,
|
||||
timeout: 30000,
|
||||
});
|
||||
|
||||
// Request Interceptor - Add Auth & Idempotency
|
||||
apiClient.interceptors.request.use((config) => {
|
||||
// Add JWT Token
|
||||
const token = localStorage.getItem('access_token');
|
||||
if (token) {
|
||||
config.headers.Authorization = `Bearer ${token}`;
|
||||
}
|
||||
|
||||
// Add Idempotency-Key for mutation requests
|
||||
if (['post', 'put', 'delete'].includes(config.method?.toLowerCase() || '')) {
|
||||
config.headers['Idempotency-Key'] = uuidv4();
|
||||
}
|
||||
|
||||
return config;
|
||||
});
|
||||
|
||||
// Response Interceptor - Handle Errors & Token Refresh
|
||||
apiClient.interceptors.response.use(
|
||||
(response) => response,
|
||||
async (error) => {
|
||||
const originalRequest = error.config;
|
||||
|
||||
// Auto refresh token on 401
|
||||
if (error.response?.status === 401 && !originalRequest._retry) {
|
||||
originalRequest._retry = true;
|
||||
|
||||
try {
|
||||
const refreshToken = localStorage.getItem('refresh_token');
|
||||
const { data } = await axios.post('/auth/refresh', { refreshToken });
|
||||
|
||||
localStorage.setItem('access_token', data.access_token);
|
||||
originalRequest.headers.Authorization = `Bearer ${data.access_token}`;
|
||||
|
||||
return apiClient(originalRequest);
|
||||
} catch (refreshError) {
|
||||
// Redirect to login
|
||||
window.location.href = '/login';
|
||||
return Promise.reject(refreshError);
|
||||
}
|
||||
}
|
||||
|
||||
return Promise.reject(error);
|
||||
}
|
||||
);
|
||||
|
||||
export default apiClient;
|
||||
```
|
||||
|
||||
### 2. Service Layer
|
||||
|
||||
```typescript
|
||||
// lib/services/correspondence.service.ts
|
||||
import apiClient from '@/lib/api/client';
|
||||
import type {
|
||||
Correspondence,
|
||||
CreateCorrespondenceDto,
|
||||
SearchCorrespondenceDto,
|
||||
} from '@/types/dto/correspondence';
|
||||
|
||||
export const correspondenceService = {
|
||||
async getAll(params: SearchCorrespondenceDto): Promise<Correspondence[]> {
|
||||
const { data } = await apiClient.get('/correspondences', { params });
|
||||
return data;
|
||||
},
|
||||
|
||||
async getById(id: string): Promise<Correspondence> {
|
||||
const { data } = await apiClient.get(`/correspondences/${id}`);
|
||||
return data;
|
||||
},
|
||||
|
||||
async create(dto: CreateCorrespondenceDto): Promise<Correspondence> {
|
||||
const { data } = await apiClient.post('/correspondences', dto);
|
||||
return data;
|
||||
},
|
||||
|
||||
async update(
|
||||
id: string,
|
||||
dto: Partial<CreateCorrespondenceDto>
|
||||
): Promise<Correspondence> {
|
||||
const { data } = await apiClient.put(`/correspondences/${id}`, dto);
|
||||
return data;
|
||||
},
|
||||
|
||||
async delete(id: string): Promise<void> {
|
||||
await apiClient.delete(`/correspondences/${id}`);
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📝 Dynamic Forms (JSON Schema)
|
||||
|
||||
### Dynamic Form Generator
|
||||
|
||||
```tsx
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { zodResolver } from '@hookform/resolvers/zod';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
|
||||
interface DynamicFormProps {
|
||||
schemaName: string;
|
||||
onSubmit: (data: any) => void;
|
||||
}
|
||||
|
||||
export function DynamicForm({ schemaName, onSubmit }: DynamicFormProps) {
|
||||
// Fetch JSON Schema from Backend
|
||||
const { data: schema } = useQuery({
|
||||
queryKey: ['json-schema', schemaName],
|
||||
queryFn: () => jsonSchemaService.getByName(schemaName),
|
||||
});
|
||||
|
||||
// Generate Zod schema from JSON Schema
|
||||
const zodSchema = useMemo(() => {
|
||||
if (!schema) return null;
|
||||
return generateZodSchemaFromJsonSchema(schema.schema_definition);
|
||||
}, [schema]);
|
||||
|
||||
const form = useForm({
|
||||
resolver: zodResolver(zodSchema!),
|
||||
});
|
||||
|
||||
if (!schema) return <Skeleton />;
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
|
||||
{Object.entries(schema.schema_definition.properties).map(
|
||||
([key, prop]: [string, any]) => (
|
||||
<FormField
|
||||
key={key}
|
||||
control={form.control}
|
||||
name={key}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel>{prop.title || key}</FormLabel>
|
||||
<FormControl>
|
||||
{renderFieldByType(prop.type, field)}
|
||||
</FormControl>
|
||||
<FormMessage />
|
||||
</FormItem>
|
||||
)}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
<Button type="submit">บันทึก</Button>
|
||||
</form>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
// Helper function to render different field types
|
||||
function renderFieldByType(type: string, field: any) {
|
||||
switch (type) {
|
||||
case 'string':
|
||||
return <Input {...field} />;
|
||||
case 'number':
|
||||
return <Input type="number" {...field} />;
|
||||
case 'boolean':
|
||||
return <Switch {...field} />;
|
||||
// Add more types as needed
|
||||
default:
|
||||
return <Input {...field} />;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 📤 File Upload
|
||||
|
||||
### Drag & Drop File Upload
|
||||
|
||||
```tsx
|
||||
import { useCallback } from 'react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
import { Upload, X } from 'lucide-react';
|
||||
|
||||
interface FileUploadZoneProps {
|
||||
onUpload: (files: File[]) => void;
|
||||
maxFiles?: number;
|
||||
maxSize?: number;
|
||||
acceptedTypes?: string[];
|
||||
}
|
||||
|
||||
export function FileUploadZone({
|
||||
onUpload,
|
||||
maxFiles = 10,
|
||||
maxSize = 50 * 1024 * 1024, // 50MB
|
||||
acceptedTypes = ['.pdf', '.dwg', '.docx', '.xlsx', '.zip'],
|
||||
}: FileUploadZoneProps) {
|
||||
const onDrop = useCallback(
|
||||
(acceptedFiles: File[]) => {
|
||||
onUpload(acceptedFiles);
|
||||
},
|
||||
[onUpload]
|
||||
);
|
||||
|
||||
const { getRootProps, getInputProps, isDragActive } = useDropzone({
|
||||
onDrop,
|
||||
maxFiles,
|
||||
maxSize,
|
||||
accept: acceptedTypes.reduce((acc, type) => ({ ...acc, [type]: [] }), {}),
|
||||
});
|
||||
|
||||
return (
|
||||
<div
|
||||
{...getRootProps()}
|
||||
className={`
|
||||
border-2 border-dashed rounded-lg p-8 text-center cursor-pointer
|
||||
transition-colors
|
||||
${
|
||||
isDragActive
|
||||
? 'border-primary bg-primary/5'
|
||||
: 'border-muted-foreground/25'
|
||||
}
|
||||
hover:border-primary hover:bg-primary/5
|
||||
`}
|
||||
>
|
||||
<input {...getInputProps()} />
|
||||
<Upload className="mx-auto h-12 w-12 text-muted-foreground" />
|
||||
<p className="mt-2 text-sm text-muted-foreground">
|
||||
{isDragActive
|
||||
? 'วางไฟล์ที่นี่...'
|
||||
: 'ลากไฟล์มาวางที่นี่ หรือคลิกเพื่อเลือกไฟล์'}
|
||||
</p>
|
||||
<p className="mt-1 text-xs text-muted-foreground">
|
||||
รองรับ: {acceptedTypes.join(', ')} (สูงสุด {maxFiles} ไฟล์,{' '}
|
||||
{maxSize / 1024 / 1024}MB/ไฟล์)
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## ✅ Testing Standards
|
||||
|
||||
### 1. Component Testing (Vitest + React Testing Library)
|
||||
|
||||
```tsx
|
||||
import { render, screen, fireEvent } from '@testing-library/react';
|
||||
import { describe, it, expect, vi } from 'vitest';
|
||||
import { CorrespondenceForm } from './correspondence-form';
|
||||
|
||||
describe('CorrespondenceForm', () => {
|
||||
it('should validate required fields', async () => {
|
||||
const onSubmit = vi.fn();
|
||||
render(<CorrespondenceForm onSubmit={onSubmit} />);
|
||||
|
||||
const submitButton = screen.getByRole('button', { name: /บันทึก/i });
|
||||
fireEvent.click(submitButton);
|
||||
|
||||
expect(await screen.findByText('กรุณาระบุหัวเรื่อง')).toBeInTheDocument();
|
||||
expect(onSubmit).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should submit form with valid data', async () => {
|
||||
const onSubmit = vi.fn();
|
||||
render(<CorrespondenceForm onSubmit={onSubmit} />);
|
||||
|
||||
const titleInput = screen.getByLabelText('หัวเรื่อง');
|
||||
fireEvent.change(titleInput, { target: { value: 'Test Correspondence' } });
|
||||
|
||||
const submitButton = screen.getByRole('button', { name: /บันทึก/i });
|
||||
fireEvent.click(submitButton);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(onSubmit).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ title: 'Test Correspondence' })
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
### 2. E2E Testing (Playwright)
|
||||
|
||||
```typescript
|
||||
import { test, expect } from '@playwright/test';
|
||||
|
||||
test.describe('Correspondence Workflow', () => {
|
||||
test.beforeEach(async ({ page }) => {
|
||||
// Login
|
||||
await page.goto('/login');
|
||||
await page.fill('input[name="username"]', 'testuser');
|
||||
await page.fill('input[name="password"]', 'password123');
|
||||
await page.click('button[type="submit"]');
|
||||
await page.waitForURL('/dashboard');
|
||||
});
|
||||
|
||||
test('should create new correspondence', async ({ page }) => {
|
||||
// Navigate to create page
|
||||
await page.click('text=สร้างเอกสาร');
|
||||
await page.waitForURL('/correspondences/new');
|
||||
|
||||
// Fill form
|
||||
await page.fill('input[name="title"]', 'E2E Test Correspondence');
|
||||
await page.selectOption('select[name="project_id"]', { index: 1 });
|
||||
await page.selectOption('select[name="type_id"]', { index: 1 });
|
||||
|
||||
// Submit
|
||||
await page.click('button[type="submit"]');
|
||||
|
||||
// Verify success
|
||||
await expect(page.locator('text=สร้างเอกสารสำเร็จ')).toBeVisible();
|
||||
await expect(page).toHaveURL(/\/correspondences\/[a-f0-9-]+/);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 🚫 Anti-Patterns (สิ่งที่ห้ามทำ)
|
||||
|
||||
1. ❌ **ห้ามใช้ Inline Styles** - ใช้ Tailwind เท่านั้น
|
||||
2. ❌ **ห้าม Fetch Data ใน useEffect** - ใช้ TanStack Query
|
||||
3. ❌ **ห้าม Props Drilling** - ใช้ Context หรือ Zustand
|
||||
4. ❌ **ห้าม Any Type**
|
||||
5. ❌ **ห้าม console.log** ใน Production
|
||||
6. ❌ **ห้ามใช้ Index เป็น Key** ใน List
|
||||
7. ❌ **ห้าม Mutation โดยตรง** - ใช้ TanStack Query Mutation
|
||||
|
||||
---
|
||||
|
||||
## 📚 เอกสารอ้างอิง
|
||||
|
||||
- [FullStack Guidelines](./fullftack-js-V1.5.0.md)
|
||||
- [Frontend Plan v1.4.5](../../docs/3_Frontend_Plan_V1_4_5.md)
|
||||
- [Next.js Documentation](https://nextjs.org/docs)
|
||||
- [TanStack Query](https://tanstack.com/query)
|
||||
- [shadcn/ui](https://ui.shadcn.com)
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Update History
|
||||
|
||||
| Version | Date | Changes |
|
||||
| ------- | ---------- | ----------------------------------- |
|
||||
| 1.0.0 | 2025-11-30 | Initial frontend guidelines created |
|
||||
1095
specs/03-implementation/fullftack-js-v1.5.0.md
Normal file
1095
specs/03-implementation/fullftack-js-v1.5.0.md
Normal file
File diff suppressed because it is too large
Load Diff
0
specs/03-implementation/testing-strategy.md
Normal file
0
specs/03-implementation/testing-strategy.md
Normal file
Reference in New Issue
Block a user