Prepare to version 1.5 use spec-kit

This commit is contained in:
admin
2025-11-30 13:58:46 +07:00
parent eff0169c21
commit 241022ada6
169 changed files with 34584 additions and 26464 deletions

View File

@@ -0,0 +1 @@
# Project overview

View File

@@ -0,0 +1 @@
# คำศัพท์เทคนิค

View 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 ที่ครอบคลุม

View 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

View 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)

View 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 โครงการเท่านั้น

View 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 ทุกครั้งที่มีการดาวน์โหลดไฟล์สำคัญ

View 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

View 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 ได้โดยไม่ต้องแก้โค้ด

View 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

View 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

View 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

View 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 ฉบับ

View 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 ใหม่ หรือมีการเปลี่ยนสถานะ
- สามารถข้ามขั้นตอนได้ในกรณีพิเศษ (โดยผู้มีสิทธิ์)
- สามารถส่งกลับขั้นตอนก่อนหน้าได้

View 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

View 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)

View 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 สามารถดูประวัติการแก้ไขของเอกสารทั้งหมด พร้อม จัดทำรายงายตามข้อกำหนดที่ ต้องการได้

View 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)

View 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+) ได้รวดเร็วโดยไม่ต้องรอโหลดเสร็จทั้งไฟล์

View 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

View 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 ให้ตรงกัน

View 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)

View 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)

View 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

View File

View 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
```
```

View 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 |

View 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 |

File diff suppressed because it is too large Load Diff