253 lines
22 KiB
Markdown
253 lines
22 KiB
Markdown
# ADR-021: Integrated Workflow Context & Step-specific Attachments
|
|
|
|
## 1. ข้อมูลทั่วไป (General Information)
|
|
- **Status:** Proposed
|
|
- **Version:** 1.8.6
|
|
- **Date:** 2026-04-12
|
|
- **Author:** Senior Full Stack Developer (Windsurf AI)
|
|
- **Reference:** ADR-001 (Workflow Engine), ADR-002 (Redlock), ADR-016 (Security)
|
|
|
|
---
|
|
|
|
## Clarifications
|
|
|
|
### Session 2026-04-12
|
|
- **Q:** What are the file size and attachment count limits per workflow step? → **A:** No explicit limit (controlled by infrastructure only)
|
|
- **Q:** What are the specific values and storage format for the "Priority" field in the Integrated Banner? → **A:** Enum "URGENT", "HIGH", "MEDIUM", "LOW" — 4-tier system with visual indicators
|
|
- **Q:** How should the system handle virus/malware detection during step-specific file upload? → **A:** Block upload immediately, delete temp file, show error "File rejected" to user
|
|
- **Q:** What is the cache TTL for Workflow History data to reduce join query overhead? → **A:** 1 hour — balanced cache duration for workflow history data
|
|
- **Q:** Who is authorized to upload step-specific attachments during a workflow transition? → **A:** Only assigned handler can upload; superadmin and organization admin can upload on behalf (impersonation)
|
|
|
|
### Session 2026-04-19
|
|
- **Q:** สถานะ Workflow ใดบ้างที่อนุญาตให้อัปโหลด Step-specific Attachment ได้? → **A:** เฉพาะสถานะ Active-decision เท่านั้น (`PENDING_REVIEW`, `PENDING_APPROVAL`) — ห้ามอัปโหลดในสถานะ Terminal (`APPROVED`, `REJECTED`, `CLOSED`)
|
|
- **Q:** หาก Redis Redlock ล้มเหลวระหว่าง Transition ระบบควรทำอย่างไร? → **A:** Fail-closed — Retry 3 ครั้ง (500ms exponential backoff) แล้ว throw HTTP 503 "Service temporarily unavailable" เพื่อรักษาความถูกต้องของข้อมูล
|
|
- **Q:** Module ใดบ้างที่ต้องรองรับ Step-specific Attachments ใน v1.8.6? → **A:** ~~เฉพาะ Module ที่ผ่าน Workflow Engine: **RFA, Transmittal, Circulation** — ไม่รวม Correspondence~~ **[REVERSED ในรอบ refinement — ดูด้านล่าง]**
|
|
- **Q (Revised 2026-04-19 v2):** Module scope สุดท้ายคืออะไร? → **A:** **RFA, Transmittal, Circulation, Correspondence ทั้ง 4 module** — เหตุผล: Correspondence detail page มีการ integrate แล้วในการ implement รอบก่อน (T014/T020/T035) การ revert จะสร้าง regression โดยไม่จำเป็น + Correspondence มี workflow instance ของตัวเองผ่าน `CORRESPONDENCE_FLOW` DSL ไม่ได้ routing ผ่าน Circulation 100%
|
|
- **Q:** Performance target ของ Upload + Transition API คืออะไร? → **A:** P95 ≤ 5 วินาที สำหรับ file ≤ 10MB (ClamAV scan + Redlock + DB transaction included)
|
|
- **Q:** Definition of Done สำหรับ REQ-01 ถึง REQ-06 คืออะไร? → **A:** กำหนด Observable Outcome 1 ประโยคต่อ REQ ที่ตรวจสอบได้โดย QA/Product Owner โดยไม่ต้องอ่าน code
|
|
|
|
---
|
|
|
|
## 2. บริบทและความสำคัญ (Context & Problem Statement)
|
|
ในเวอร์ชันปัจจุบัน (v1.8.5) ระบบ DMS ประสบปัญหาด้าน User Experience และ Data Traceability ใน 2 จุดหลัก:
|
|
1. **Context Fragmentation:** ข้อมูลเอกสารและหน้าจอควบคุม Workflow แยกออกจากกัน ทำให้ Reviewer/Approver ต้องสลับหน้าจอไปมาเพื่อตรวจสอบข้อมูลก่อนตัดสินใจ
|
|
2. **Generic Attachments:** ไฟล์แนบถูกเก็บรวมไว้ที่ระดับตัวเอกสารหลัก (Root Document) ทำให้ไม่สามารถระบุได้ว่าไฟล์ใดถูกเพิ่มเข้ามาเพื่อประกอบการตัดสินใจในขั้นตอน (Step) ใดเป็นพิเศษ
|
|
|
|
---
|
|
|
|
## 3. การตัดสินใจเชิงสถาปัตยกรรม (Architecture Decision)
|
|
|
|
เราจะเปลี่ยนไปใช้แนวทาง **Integrated Contextual Workflow** โดยมีรายละเอียดดังนี้:
|
|
|
|
### 3.1 Status Banner Integration
|
|
- ยุบรวม Metadata ที่สำคัญของเอกสาร (Doc No, Subject, Initiator, Priority) ไว้ใน Header เดียวกันกับส่วนแสดงสถานะ (Status) และปุ่มดำเนินการ (Actions)
|
|
- เพื่อให้ผู้ใช้งานเห็น "บริบททั้งหมด" ในแถวสายตาเดียว (Single Row Visibility)
|
|
|
|
### 3.2 Workflow Lifecycle Visualization
|
|
- แสดงขั้นตอนทั้งหมด (Full Path) ในรูปแบบ Vertical Timeline ภายใน Tab
|
|
- **Active Highlighting:** ขั้นตอนปัจจุบันต้องใช้สีเด่น (Indigo) และ Animation (Pulse) เพื่อระบุตำแหน่งงาน
|
|
- **Completed/Pending States:** ขั้นตอนที่ผ่านมาแล้วและในอนาคตต้องมี Visual State ที่แตกต่างกันอย่างชัดเจน
|
|
|
|
### 3.3 Step-specific Attachments & Preview
|
|
- **Linked Data:** ปรับปรุง Schema ให้ไฟล์แนบสามารถเชื่อมโยงกับ `workflow_history` ได้
|
|
- **Contextual Upload:** อนุญาตให้อัปโหลดไฟล์ได้ "เฉพาะ" ในขั้นตอนที่กำลังดำเนินการอยู่ (Active Step) เท่านั้น
|
|
- **Unified Preview:** สร้างระบบ Preview Modal กลางที่เรียกดูไฟล์ได้จากทุกจุดโดยไม่ต้องเปลี่ยนหน้า
|
|
|
|
---
|
|
|
|
## 4. รายละเอียดความต้องการ (Functional Requirements)
|
|
|
|
| ID | Feature | Description |
|
|
| :--- | :--- | :--- |
|
|
| REQ-01 | **Integrated Banner** | แสดง ID, Status, Priority (`URGENT`/`HIGH`/`MEDIUM`/`LOW` พร้อม visual indicators) และปุ่ม Approve/Reject ไว้ในแถบด้านบนสุด |
|
|
| REQ-02 | **Step Detail View** | ใน Tab Workflow Engine ต้องแสดงรายละเอียด Role, Handler และ Description ของทุกขั้นตอน |
|
|
| REQ-03 | **Active Step Color** | ขั้นตอนปัจจุบันใช้สี Indigo (#6366f1) พร้อม Pulse effect |
|
|
| REQ-04 | **Step-safe Upload** | รองรับการลากวางไฟล์ (Drag & Drop) เพื่อแนบหลักฐานประจำขั้นตอนนั้นๆ — **อนุญาตเฉพาะสถานะ `PENDING_REVIEW` และ `PENDING_APPROVAL` เท่านั้น** สถานะ Terminal (`APPROVED`, `REJECTED`, `CLOSED`) ไม่อนุญาต |
|
|
| REQ-05 | **Internal Preview** | คลิกดูไฟล์ PDF/Images ได้ทันทีผ่าน Modal ภายในระบบ |
|
|
| REQ-06 | **i18n Support** | ทุก UI text ต้องใช้ i18n keys ตาม `05-08-i18n-guidelines.md` |
|
|
|
|
---
|
|
|
|
## 5. ข้อกำหนดทางเทคนิค (Technical Requirements - Tier 1 Critical)
|
|
|
|
1. **Database Consistency:** ต้องเพิ่ม `workflow_history_id` ในตาราง `attachments` โดยรักษาค่าเป็น Nullable สำหรับไฟล์หลัก (Main Docs)
|
|
2. **Concurrency Control:**
|
|
- **Transition Lock:** ใช้ Redis Redlock เมื่อมีการเปลี่ยนสถานะพร้อมอัปโหลดไฟล์ (Two-Phase: Lock → Upload + Transition → Unlock) — หาก Lock ไม่สำเร็จ: Retry 3 ครั้ง (500ms exponential backoff) แล้ว Fail-closed (HTTP 503)
|
|
- **File Upload:** ใช้ Temp Storage ก่อน (ADR-016 Two-Phase Upload) แล้วย้ายไป Permanent หลัง Transition สำเร็จ
|
|
3. **Security Audit:** ทุกไฟล์แนบราย Step ต้องผ่านการสแกน **ClamAV** และบันทึกข้อมูล Who/When ลงใน Audit Log (ADR-016)
|
|
4. **Identifier Strategy:** อ้างอิงไฟล์ผ่าน **UUIDv7** (publicId) เท่านั้น ห้ามใช้ ID ที่เป็น Integer ใน API (ADR-019)
|
|
5. **Database Indexing:** ต้องสร้าง Index บน `(workflow_history_id, created_at)` สำหรับตาราง `attachments` เพื่อ optimize การดึงไฟล์แนบตาม Step
|
|
6. **i18n Support:** ทุก UI text ต้องใช้ i18n keys ตาม `05-08-i18n-guidelines.md`
|
|
7. **File Size Limits:** ไม่กำหนด Limit ที่ Application Layer — ควบคุมโดย Infrastructure (Reverse Proxy / Storage Config) เท่านั้น
|
|
8. **Idempotency Control:** ทุกการอัปโหลดไฟล์พร้อม Transition ต้องมีการตรวจสอบ `Idempotency-Key` header (per .windsurfrules Security Rule #1)
|
|
9. **Async Event Processing:** Notifications และ Events จาก workflow transitions ต้องใช้ **BullMQ** queue (ADR-008) — ห้าม inline ใน Service
|
|
10. **Performance SLA:** `POST /workflow/:uuid/transition` (พร้อม file) ต้องตอบสนองภายใน **P95 ≤ 5 วินาที** สำหรับไฟล์ขนาด ≤ 10MB (รวม ClamAV scan + Redlock + DB transaction)
|
|
|
|
---
|
|
|
|
## 5.1 Idempotency & Duplicate Prevention
|
|
|
|
| Mechanism | Implementation |
|
|
|-----------|----------------|
|
|
| **Idempotency-Key** | ทุก `POST/PUT` สำหรับ upload + transition ต้องส่ง header `Idempotency-Key` (UUID) |
|
|
| **Redis Store** | เก็บ key mapping `(idempotency_key, user_id)` → response (TTL: 24 ชั่วโมง) |
|
|
| **Duplicate Detection** | หาก key ซ้ำ → return cached response (201/200) ไม่ทำซ้ำ |
|
|
|
|
---
|
|
|
|
## 5.2 กรณีขอบเขตและการจัดการข้อผิดพลาด (Edge Cases & Error Handling)
|
|
|
|
| Scenario | Behavior |
|
|
|----------|----------|
|
|
| **ClamAV ตรวจพบไวรัส/มัลแวร์** | Block upload ทันที, ลบ temp file, แสดง error "File rejected" แก่ user |
|
|
| **Upload ไฟล์ระหว่าง Transition ล้มเหลว** | Rollback transaction ทั้งหมด, ลบ temp files, คงสถานะ workflow เดิม |
|
|
| **ไฟล์ถูกลบจาก Storage หลัง Attach** | แสดง "File unavailable" ใน UI, บันทึก metadata ไว้ตามเดิม |
|
|
| **Concurrent Transition พร้อม Upload** | Redis Redlock จัดการ queue, อนุญาตเพียง 1 transition พร้อมกัน |
|
|
| **Redis Redlock ล้มเหลว / Redis ล่ม** | Retry 3 ครั้ง (500ms exponential backoff) — หากยังล้มเหลว throw HTTP 503 "Service temporarily unavailable" (Fail-closed, ห้าม Fail-open) |
|
|
| **Invalid File Type** | Reject ตั้งแต่ client-side (whitelist: PDF, DOCX, XLSX, DWG, ZIP) |
|
|
| **Unauthorized Upload Attempt** | ตรวจสอบสิทธิ์: เฉพาะ assigned handler, superadmin, หรือ org admin เท่านั้น |
|
|
| **Upload ในสถานะ Terminal** | Reject ทันทีด้วย HTTP 409 — ไม่อนุญาตอัปโหลดเมื่อสถานะเป็น `APPROVED`, `REJECTED`, หรือ `CLOSED` |
|
|
| **Duplicate Upload (Network Retry)** | ตรวจสอบ `Idempotency-Key` — reject duplicate พร้อม return existing result |
|
|
| **Cache Stale Data** | Invalidate Redis Cache ทันทีเมื่อ workflow state เปลี่ยน (TTL override)
|
|
|
|
---
|
|
|
|
## 6. รายการไฟล์ที่ต้องอัพเดท (Impacted Files)
|
|
|
|
### 🔴 Backend Layer (Data & Logic)
|
|
- `specs/03-Data-and-Storage/lcbp3-v1.8.0-schema-02-tables.sql`
|
|
- *Action:* เพิ่ม FK `workflow_history_id` ในตาราง `attachments`
|
|
- `backend/src/common/file-storage/entities/attachment.entity.ts`
|
|
- *Action:* เพิ่ม Relation `@ManyToOne(() => WorkflowHistory)`
|
|
- `backend/src/modules/workflow-engine/entities/workflow-history.entity.ts`
|
|
- *Action:* เพิ่ม Relation `@OneToMany(() => Attachment)`
|
|
- `backend/src/modules/workflow-engine/workflow-engine.service.ts`
|
|
- *Action:* ปรับปรุง Method `transition()` ให้รองรับการรับไฟล์แนบ (Array of Files)
|
|
- `backend/src/modules/workflow-engine/dto/workflow-transition.dto.ts`
|
|
- *Action:* เพิ่ม Field สำหรับรับ Metadata ของไฟล์ที่อัปโหลด และ `Idempotency-Key` header
|
|
- `backend/src/modules/workflow-engine/guards/workflow-transition.guard.ts` (สร้างใหม่)
|
|
- *Action:* Implement **CASL Guard** สำหรับ 4-Level RBAC: Superadmin > Org Admin > Assigned Handler > Read-only
|
|
|
|
### 🟡 Frontend Layer (UI & Interaction)
|
|
- `frontend/app/(dashboard)/rfas/[uuid]/page.tsx`
|
|
- *Action:* Refactor Header เป็น Integrated Banner และเพิ่ม Tab Workflow Lifecycle
|
|
- `frontend/app/(dashboard)/transmittals/[uuid]/page.tsx`
|
|
- *Action:* Refactor Header เป็น Integrated Banner และเพิ่ม Tab Workflow Lifecycle
|
|
- `frontend/app/(dashboard)/circulation/[uuid]/page.tsx`
|
|
- *Action:* Refactor Header เป็น Integrated Banner และเพิ่ม Tab Workflow Lifecycle
|
|
- `frontend/app/(dashboard)/correspondences/[uuid]/page.tsx`
|
|
- *Action:* Refactor Header เป็น Integrated Banner และเพิ่ม Tab Workflow Lifecycle (Re-included via Clarify v2 2026-04-19)
|
|
- `frontend/components/workflow/workflow-visualizer.tsx` (สร้างใหม่)
|
|
- *Action:* พัฒนาการแสดงผล Vertical Timeline พร้อมระบบสี Active/Inactive
|
|
- `frontend/components/common/file-preview-modal.tsx` (สร้างใหม่)
|
|
- *Action:* พัฒนาคอมโพเนนต์ Modal สำหรับจำลอง PDF Viewer
|
|
- `frontend/hooks/use-workflow-action.ts` (สร้างใหม่)
|
|
- *Action:* จัดการ State การอัปโหลดไฟล์และการยิง API Transition พร้อมกัน
|
|
- `frontend/types/workflow.ts`
|
|
- *Action:* อัปเดต Interface ให้รองรับ `attachments` ภายในแต่ละ `WorkflowStep`
|
|
|
|
---
|
|
|
|
## 7. 🔍 Impact Analysis
|
|
|
|
| Component | Level | Impact Description | Required Action |
|
|
|-----------|-------|-------------------|-----------------|
|
|
| **Backend** | 🔴 High | เพิ่ม FK `workflow_history_id` และ Entity Relations ใหม่ | Update `attachment.entity.ts`, `workflow-history.entity.ts`, Schema SQL |
|
|
| **Database** | 🔴 High | Schema migration เพิ่ม column และ index | Run SQL delta, สร้าง Index |
|
|
| **Frontend** | 🟡 Medium | Refactor Detail Pages, สร้าง Workflow Visualizer | Update Page Components, สร้างใหม่ 3 ไฟล์ |
|
|
| **API** | 🟡 Medium | DTO changes รองรับ file metadata | Update `workflow-transition.dto.ts` |
|
|
| **Workflow Engine** | 🟡 Medium | ปรับปรุง `processTransition()` รองรับ attachments | Update `workflow-engine.service.ts` |
|
|
|
|
---
|
|
|
|
## 8. Migration Strategy
|
|
|
|
- **Existing Attachments:** ไฟล์แนบที่มีอยู่แล้วจะมี `workflow_history_id = NULL` (ถือเป็น Main Document attachments)
|
|
- **New Attachments:** ไฟล์แนบใหม่ที่อัปโหลดพร้อม Transition จะถูกเชื่อมโยงกับ `workflow_history` ของ Step นั้น
|
|
- **Rollback Plan:** หากการ migrate มีปัญหา สามารถตั้ง `workflow_history_id = NULL` กลับได้ทั้งหมด (Nullable FK)
|
|
|
|
---
|
|
|
|
## 9. ผลกระทบ (Consequences)
|
|
- **Positive:** เพิ่มความน่าเชื่อถือของข้อมูล (Data Integrity) และลดระยะเวลาในการอนุมัติเอกสาร
|
|
- **Negative:** เพิ่มความซับซ้อนในการ Join ตารางระหว่างการดึงข้อมูลประวัติและไฟล์แนบ — **Mitigation:** ใช้ Redis Cache สำหรับ Workflow History (TTL: 1 ชั่วโมง) พร้อม **Cache Invalidation** เมื่อ state เปลี่ยน
|
|
|
|
---
|
|
|
|
## 9.1 Testing Requirements (Tier 2 - Important)
|
|
|
|
ตาม .windsurfrules Tier 2 ต้องมี:
|
|
- **Business Logic Coverage:** 80%+ (Workflow transition logic, RBAC checks, file upload validation)
|
|
- **Backend Overall Coverage:** 70%+
|
|
- **Frontend Component Tests:** สำหรับ Integrated Banner, Workflow Visualizer, File Preview Modal
|
|
- **E2E Tests:** สำหรับ complete workflow พร้อม file upload
|
|
|
|
### Definition of Done (Observable Outcomes)
|
|
|
|
| REQ | Done When |
|
|
|-----|-----------|
|
|
| **REQ-01** | Banner แสดง Doc No, Status, Priority badge และปุ่ม Approve/Reject ก่อนเนื้อหาเอกสารในทุก Module (RFA, Transmittal, Circulation) |
|
|
| **REQ-02** | Tab "Workflow Engine" แสดง Role + Handler + Description ครบทุก Step โดยไม่ต้อง reload หน้า |
|
|
| **REQ-03** | Step ปัจจุบันใช้สี Indigo (#6366f1) พร้อม CSS Pulse animation ที่มองเห็นได้ชัดเจน; Step อื่นๆ ไม่มี animation |
|
|
| **REQ-04** | Drag & Drop ทำงานเฉพาะเมื่อ Status = `PENDING_REVIEW`/`PENDING_APPROVAL`; ปุ่มถูก disable เมื่อ Status = `APPROVED`/`REJECTED`/`CLOSED` |
|
|
| **REQ-05** | คลิกไฟล์ PDF/Image ใดก็ตามเปิด Preview Modal แบบ In-browser โดยไม่ navigate ออกจากหน้าปัจจุบัน |
|
|
| **REQ-06** | ไม่มี Hardcoded text ใน Component ใหม่; ทุก label ต้องเปลี่ยนภาษาได้เมื่อ switch EN/TH |
|
|
|
|
---
|
|
|
|
## 10. Compliance
|
|
|
|
เป็นไปตาม:
|
|
- [Backend Guidelines](../05-Engineering-Guidelines/05-02-backend-guidelines.md) - NestJS patterns, TypeORM relations
|
|
- [Frontend Guidelines](../05-Engineering-Guidelines/05-03-frontend-guidelines.md) - React/Next.js patterns
|
|
- [i18n Guidelines](../05-Engineering-Guidelines/05-08-i18n-guidelines.md) - การรองรับหลายภาษา
|
|
- [Testing Strategy](../05-Engineering-Guidelines/05-04-testing-strategy.md) - Coverage goals
|
|
|
|
---
|
|
|
|
## 11. Related ADRs
|
|
|
|
- [ADR-001: Unified Workflow Engine](./ADR-001-unified-workflow-engine.md) - พื้นฐาน Workflow Engine ที่ ADR-021 ขยายต่อ
|
|
- [ADR-002: Document Numbering Strategy](./ADR-002-document-numbering-strategy.md) - Redis Redlock สำหรับ Concurrency Control
|
|
- [ADR-016: Security and Authentication](./ADR-016-security-authentication.md) - ClamAV, Audit Log, Two-Phase Upload
|
|
- [ADR-019: Hybrid Identifier Strategy](./ADR-019-hybrid-identifier-strategy.md) - UUIDv7 / publicId ใช้ใน API
|
|
|
|
---
|
|
|
|
## 12. 📋 Version Dependency Matrix
|
|
|
|
| ADR | Version | Dependency Type | Affected Version(s) | Implementation Status |
|
|
|-----|---------|-----------------|---------------------|----------------------|
|
|
| **ADR-021** | 1.8.6 | Core | v1.8.6+ | 🔄 Proposed |
|
|
| **ADR-001** | 1.0 | Required By | v1.8.6+ | ✅ Active |
|
|
| **ADR-002** | 1.0 | Uses | v1.8.6+ | ✅ Active |
|
|
| **ADR-016** | 1.0 | Security | v1.8.6+ | ✅ Active |
|
|
| **ADR-019** | 1.0 | Identifier | v1.8.6+ | ✅ Active |
|
|
|
|
### Version Compatibility Rules
|
|
|
|
- **Minimum Version:** v1.8.6 (ADR-021 มีผลบังคับใช้)
|
|
- **Breaking Changes:** มี (Schema changes, API DTO changes)
|
|
- **Deprecation Timeline:** ไม่มี (Feature addition)
|
|
|
|
---
|
|
|
|
## 13. 🔄 Review Cycle & Maintenance
|
|
|
|
### Review Schedule
|
|
- **Next Review:** 2026-10-12 (6 months from creation)
|
|
- **Review Type:** Scheduled (Architecture Decision Review)
|
|
- **Reviewers:** System Architect, Development Team Lead, Product Owner
|
|
|
|
### Review Checklist
|
|
- [ ] การ implement ครบถ้วนตาม requirements (REQ-01 ถึง REQ-06)
|
|
- [ ] Database migration สำเร็จและ performance อยู่ในเกณฑ์ที่ยอมรับได้
|
|
- [ ] Frontend components ผ่าน UI/UX review
|
|
- [ ] มีปัญหา Integration กับ Module อื่นหรือไม่
|
|
- [ ] ต้องการ Update DSL structure หรือไม่
|
|
|
|
### Version History
|
|
| Version | Date | Changes | Status |
|
|
|---------|------|---------|--------|
|
|
| 1.8.6 | 2026-04-12 | Initial version - Integrated Workflow Context & Step-specific Attachments | 🔄 Proposed |
|