50 KiB
✅ Acceptance Criteria — LCBP3-DMS MVP (UAT) v1.8.1
title: 'Acceptance Criteria & UAT Test Scenarios' version: 1.8.1 status: updated owner: Nattanin Peancharoen (Product Owner) last_updated: 2026-03-24 related:
- specs/01-Requirements/01-01-objectives.md
- specs/01-Requirements/01-04-user-stories.md
- specs/01-Requirements/01-06-edge-cases-and-rules.md
- specs/01-Requirements/01-02-business-rules/01-02-01-rbac-matrix.md
- specs/01-Requirements/01-02-business-rules/01-02-04-non-functional-rules.md
- specs/06-Decision-Records/ADR-001-unified-workflow-engine.md
- specs/06-Decision-Records/ADR-016-security-authentication.md
📖 วิธีอ่านเอกสารนี้
แต่ละ Scenario ใช้รูปแบบ Given / When / Then พร้อม:
- ID: รหัส Scenario ใช้อ้างอิง (AC-XXX-YYY)
- Priority: 🔴 Blocker | 🟠 Critical | 🟡 Major | 🟢 Minor
- Role: ผู้ใช้ที่ทดสอบ Scenario นี้
🏗️ Module 1: Authentication & Session Management
AC-AUTH-001 — Login Success
Priority: 🔴 Blocker | Role: ทุก Role
| Description | |
|---|---|
| Given | User มีบัญชีในระบบ และ Password ถูกต้อง |
| When | กรอก Username + Password แล้วกด Login |
| Then | ✅ ได้รับ JWT Access Token (15 min TTL) + Refresh Token (7 days) |
| ✅ ถูก Redirect ไปที่ Dashboard | |
✅ Audit Log บันทึก LOGIN_SUCCESS พร้อม IP Address |
AC-AUTH-002 — Login Failed (Wrong Password)
Priority: 🔴 Blocker | Role: ทุก Role
| Description | |
|---|---|
| Given | User มีบัญชีในระบบ |
| When | กรอก Password ผิด |
| Then | ✅ แสดง Error "ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง" (ไม่บอกว่าอันไหนผิด) |
✅ Audit Log บันทึก LOGIN_FAILED |
|
| ✅ หลัง 5 ครั้งใน 1 นาที → Rate Limit 429 Too Many Requests |
AC-AUTH-003 — First Login Force Password Change
Priority: 🔴 Blocker | Role: ทุก Role (new user)
| Description | |
|---|---|
| Given | User เพิ่งถูกสร้างโดย Admin (password_must_change = true) |
| When | Login สำเร็จครั้งแรก |
| Then | ✅ ถูก Redirect ไปยังหน้า "เปลี่ยนรหัสผ่าน" ทันที |
| ✅ ไม่สามารถเข้าถึงหน้าอื่นได้ จนกว่าจะเปลี่ยนรหัสผ่าน | |
| ✅ Password ใหม่ต้องผ่าน Policy (ตัวใหญ่ + ตัวเล็ก + ตัวเลข + 8+ ตัวอักษร) |
AC-AUTH-004 — Token Refresh
Priority: 🟠 Critical | Role: ทุก Role
| Description | |
|---|---|
| Given | Access Token หมดอายุ (15 min) แต่ Refresh Token ยังใช้งานได้ |
| When | Frontend ตรวจพบ 401 Response ระหว่างการใช้งาน |
| Then | ✅ Frontend auto-refresh token โดยผู้ใช้ไม่รู้สึก |
| ✅ Request เดิม Retry สำเร็จหลัง Token Refresh |
AC-AUTH-005 — Logout
Priority: 🟠 Critical | Role: ทุก Role
| Description | |
|---|---|
| Given | User กำลัง Login อยู่ |
| When | กด Logout |
| Then | ✅ Refresh Token ถูก Revoke ใน Database |
| ✅ Redis Permission Cache ถูกลบ | |
| ✅ Redirect ไปหน้า Login | |
✅ Audit Log บันทึก LOGOUT |
🏢 Module 2: User & Organization Management (Admin)
AC-ADMIN-001 — Superadmin สร้าง Organization
Priority: 🔴 Blocker | Role: Superadmin
| Description | |
|---|---|
| Given | Login ด้วย Superadmin Account |
| When | สร้าง Organization ใหม่ กรอกชื่อ + รหัสองค์กร |
| Then | ✅ Organization ถูกสร้างในฐานข้อมูล |
| ✅ สามารถกำหนด Org Admin ได้ทันที | |
✅ Audit Log บันทึก ORGANIZATION_CREATED |
AC-ADMIN-002 — Superadmin สร้าง Project + Contract
Priority: 🔴 Blocker | Role: Superadmin
| Description | |
|---|---|
| Given | มี Organization อย่างน้อย 1 ที่ |
| When | สร้าง Project → สร้าง Contract ภายใน Project |
| Then | ✅ Project ผูกกับ Organization ได้หลายองค์กร |
| ✅ Contract ผูกกับ Project (1 Contract ต่อ Contractor) | |
| ✅ การตั้งค่า Document Number Format สำหรับ Project ทำได้ |
AC-ADMIN-003 — Org Admin เพิ่ม User เข้า Organization
Priority: 🟠 Critical | Role: Org Admin
| Description | |
|---|---|
| Given | Login ด้วย Org Admin |
| When | เพิ่ม User พร้อม Role (Editor/Viewer/Document Control) |
| Then | ✅ User ได้รับ Email แจ้ง Credentials |
| ✅ User Login แล้วเห็น Dashboard ขององค์กรตัวเอง | |
| ✅ Permission ถูก Cache ใน Redis (ภายใน 30 วินาที) |
AC-ADMIN-004 — Permission Isolation ระหว่าง Contractor
Priority: 🔴 Blocker | Role: Document Control (Contractor A)
| Description | |
|---|---|
| Given | มี Contractor A (Contract 1) และ Contractor B (Contract 2) |
| When | Contractor A Login แล้วพยายาม เข้าดู Document ของ Contractor B |
| Then | ✅ ได้รับ 403 Forbidden |
| ✅ Contractor A ไม่เห็น Document ของ Contractor B ในรายการ | |
| ✅ Audit Log บันทึกความพยายาม Unauthorized Access |
AC-ADMIN-005 — Permission Cache Invalidation
Priority: 🟠 Critical | Role: Superadmin
| Description | |
|---|---|
| Given | User กำลัง Login อยู่และมี Permission Cache ใน Redis |
| When | Superadmin เปลี่ยน Role ของ User นั้น |
| Then | ✅ Redis Cache ของ User นั้นถูกล้างทันที |
| ✅ Request ถัดไปของ User ใช้ Permission ใหม่ (ภายใน 1 request cycle) |
📨 Module 3: Correspondence Management
AC-CORR-001 — สร้าง Correspondence (Draft)
Priority: 🔴 Blocker | Role: Document Control
| Description | |
|---|---|
| Given | Login ด้วย Document Control ขององค์กรใด |
| When | สร้าง Correspondence ใหม่ (Letter/RFI) กรอก Subject, To, CC, แนบไฟล์ PDF |
| Then | ✅ เอกสารถูกบันทึกในสถานะ DRAFT |
| ✅ ผู้ใช้ขององค์กรอื่น ไม่เห็น Draft นี้ | |
| ✅ ผู้สร้างเห็นใน "เอกสารฉบับร่างของฉัน" |
AC-CORR-002 — Submit Correspondence + Auto Document Number
Priority: 🔴 Blocker | Role: Document Control
| Description | |
|---|---|
| Given | มี Correspondence ในสถานะ Draft พร้อม Attachment |
| When | กด Submit |
| Then | ✅ ระบบออกเลขเอกสารอัตโนมัติตาม Format Template (เช่น LCBP3-สคฉ-กทท-LETTER-0001-68) |
| ✅ เลขเอกสารไม่ซ้ำกัน แม้ Submit พร้อมกันหลาย Request | |
✅ สถานะเปลี่ยนเป็น SUBMITTED |
|
✅ Workflow Instance ถูกสร้างใน workflow_instances |
|
| ✅ องค์กรผู้รับ (To) ได้รับแจ้งเตือน (Email + In-App) |
AC-CORR-003 — ผู้รับ Correspondence
Priority: 🔴 Blocker | Role: Document Control (Recipient Org)
| Description | |
|---|---|
| Given | Correspondence ถูก Submit มายังองค์กรเรา |
| When | Document Control ขององค์กรผู้รับ เปิดดู |
| Then | ✅ เห็นเอกสารใน Inbox/Received |
| ✅ สามารถสร้าง Circulation Sheet ได้ | |
| ✅ สามารถดาวน์โหลดไฟล์แนบได้ |
AC-CORR-004 — อ้างอิงเอกสารก่อนหน้า (References)
Priority: 🟡 Major | Role: Document Control
| Description | |
|---|---|
| Given | มีเอกสาร Correspondence เก่าในระบบ |
| When | สร้าง Correspondence ใหม่และอ้างอิงเอกสารเก่า |
| Then | ✅ Link เชื่อมระหว่างเอกสารทั้งสอง |
| ✅ สามารถคลิก Navigate ไปดูเอกสารที่อ้างถึงได้ |
AC-CORR-005 — Cancel Correspondence (Admin Only)
Priority: 🟡 Major | Role: Org Admin / Superadmin
| Description | |
|---|---|
| Given | Correspondence ถูก Submit แล้ว (สถานะ SUBMITTED+) |
| When | Admin กด Cancel พร้อมระบุเหตุผล |
| Then | ✅ สถานะเปลี่ยนเป็น CANCELLED |
✅ ต้องระบุ cancel_reason (ไม่ยอม Empty) |
|
| ✅ Audit Log บันทึกพร้อมเหตุผล | |
| ✅ User ระดับ Viewer/Editor ทำ Cancel ไม่ได้ → 403 |
📋 Module 4: RFA Management
AC-RFA-001 — สร้าง RFA + แนบ Shop Drawing
Priority: 🔴 Blocker | Role: Document Control (Contractor)
| Description | |
|---|---|
| Given | Login ด้วย Document Control ของ Contractor |
| When | สร้าง RFA ใหม่ — กรอก RFA Type, Discipline, แนบ Shop Drawing (PDF/DWG/ZIP) |
| Then | ✅ RFA ถูกบันทึกในสถานะ DRAFT |
| ✅ Shop Drawing ผูกกับ RFA (1 Revision = 1 RFA) | |
| ✅ ไฟล์ถูก Scan ด้วย ClamAV — ปฏิเสธไฟล์ที่ติด Virus |
AC-RFA-002 — Submit RFA + Auto Number
Priority: 🔴 Blocker | Role: Document Control (Contractor)
| Description | |
|---|---|
| Given | RFA Draft พร้อม Shop Drawing |
| When | กด Submit |
| Then | ✅ เลขที่ RFA ถูกออกอัตโนมัติตาม Format (LCBP3-RFA-STR-0001) |
| ✅ เลขไม่ reset ตามปี (RFA = No reset policy) | |
✅ สถานะ = SUBMITTED → สร้าง Transmittal อัตโนมัติ |
|
| ✅ Workflow Routing เริ่มทำงาน (ส่งไปยัง Reviewer) |
AC-RFA-003 — Review RFA (Approved)
Priority: 🔴 Blocker | Role: Engineer/Reviewer (Supervisor Org)
| Description | |
|---|---|
| Given | RFA อยู่ในสถานะรอ Review ที่องค์กรเรา |
| When | Engineer คลิก "Approved" |
| Then | ✅ สถานะ RFA เปลี่ยนเป็น APPROVED (1A) |
| ✅ Originator (Contractor) ได้รับแจ้งเตือน | |
| ✅ Workflow History บันทึก Action + Timestamp + User |
AC-RFA-004 — Review RFA (Approved with Comments)
Priority: 🟠 Critical | Role: Engineer/Reviewer
| Description | |
|---|---|
| Given | RFA อยู่ในสถานะรอ Review |
| When | Engineer คลิก "Approved with Comments" + กรอก Comment |
| Then | ✅ สถานะ = APPROVED_WITH_COMMENTS (1B) |
| ✅ Comment ถูกบันทึกใน Workflow History | |
| ✅ Originator เห็น Comment ได้ |
AC-RFA-005 — Review RFA (Rejected)
Priority: 🟠 Critical | Role: Engineer/Reviewer
| Description | |
|---|---|
| Given | RFA อยู่ในสถานะรอ Review |
| When | Engineer คลิก "Rejected" + ระบุเหตุผล |
| Then | ✅ สถานะ = REJECTED (4X) |
| ✅ เหตุผลการ Reject บันทึกครบถ้วน | |
| ✅ Contractor สามารถยื่น RFA Revision ใหม่ได้ |
AC-RFA-006 — Revision RFA
Priority: 🟠 Critical | Role: Document Control (Contractor)
| Description | |
|---|---|
| Given | RFA Rev.A ถูก Rejected แล้ว |
| When | Contractor สร้าง RFA Revision ใหม่ (Rev.B) |
| Then | ✅ Rev.B ผูกกับ shop_drawing revision ใหม่ |
✅ เลขที่เอกสารเดิม — Revision Code เปลี่ยน (เช่น -B) |
|
| ✅ Rev.A ยังอ่านได้ (ไม่ถูกลบ) |
AC-RFA-007 — Edit Draft RFA
Priority: 🔴 Blocker | Role: Document Control (Contractor)
| Description | |
|---|---|
| Given | RFA อยู่ในสถานะ DRAFT (EC-RFA-001 enforced) |
| When | Document Control แก้ไข Subject/Body/Remarks |
| Then | ✅ RFA ถูกอัปเดตในสถานะ DRAFT |
| ✅ หากสถานะไม่ใช่ DFT → 403 Forbidden | |
| ✅ Audit Log บันทึก UPDATE + user + timestamp | |
| ✅ 1 Shop Drawing Revision = 1 RFA เท่านั้น |
AC-RFA-008 — Cancel Draft RFA
Priority: 🟠 Critical | Role: Document Control (Contractor)
| Description | |
|---|---|
| Given | RFA อยู่ในสถานะ DRAFT |
| When | กด Cancel |
| Then | ✅ สถานะเปลี่ยนเป็น CANCELLED |
| ✅ Shop Drawing Revision ถูกปลดผูก (available) | |
| ✅ Audit Log บันทึก CANCELLED + reason | |
| ✅ ไม่สามารถกด Cancel ได้ถ้าสถานะไม่ใช่ DFT |
AC-RFA-009 — Search/Filter RFA
Priority: 🔴 Blocker | Role: Document Control/Engineer
| Description | |
|---|---|
| Given | มี RFA ในระบบหลายฉบับ |
| When | Filter ด้วย Project/Status หรือค้นหา Keyword |
| Then | ✅ ผลลัพธ์ถูกต้องตาม Filter |
| ✅ DFT → เห็นเฉพาะ originator org (RBAC) | |
| ✅ Pagination ทำงาน (20 items/page) | |
| ✅ ค้นหาจากเลขเอกสาร/Subject ได้ |
📐 Module 5: Drawing Management
AC-DRW-001 — Upload Contract Drawing
Priority: 🟠 Critical | Role: Document Control (Design Consultant)
| Description | |
|---|---|
| Given | Login ด้วย Document Control ที่มีสิทธิ์ Contract Drawing |
| When | Upload แบบคู่สัญญา (PDF) พร้อมระบุ หมวดหมู่ / Drawing Number |
| Then | ✅ Drawing ถูกบันทึกในระบบ |
| ✅ สามารถอ้างอิงจาก Shop Drawing ได้ | |
| ✅ ไม่สามารถแก้ไขได้โดยไม่มีสิทธิ์ |
AC-DRW-002 — Upload Shop Drawing + Link to Contract Drawing
Priority: 🟠 Critical | Role: Document Control (Contractor)
| Description | |
|---|---|
| Given | มี Contract Drawing ในระบบแล้ว |
| When | Upload Shop Drawing พร้อมระบุ Referenced Contract Drawing |
| Then | ✅ Shop Drawing ผูก Reference กับ Contract Drawing |
| ✅ สามารถ Navigate ไปดู Contract Drawing ที่อ้างถึงได้ |
AC-DRW-003 — Shop Drawing Revision Control
Priority: 🟠 Critical | Role: Document Control
| Description | |
|---|---|
| Given | Shop Drawing Rev.A มีอยู่แล้ว |
| When | Upload Shop Drawing Rev.B |
| Then | ✅ Rev.B ถือเป็น Current Revision |
| ✅ Rev.A ยังสามารถดูได้ (ไม่ถูกลบ) | |
| ✅ 1 Shop Drawing Revision ผูกกับ RFA ได้ 1 ฉบับเท่านั้น |
⚙️ Module 6: Unified Workflow Engine
AC-WF-001 — Workflow Instance Creation
Priority: 🔴 Blocker | Role: ระบบ (Auto)
| Description | |
|---|---|
| Given | Document ถูก Submit |
| When | ระบบสร้าง Workflow Instance |
| Then | ✅ workflow_instances record ถูกสร้าง |
✅ current_state = Initial State ตาม DSL |
|
✅ entity_type และ entity_id ถูกต้อง |
AC-WF-002 — Workflow State Transition (Happy Path)
Priority: 🔴 Blocker | Role: ตาม Workflow Role
| Description | |
|---|---|
| Given | Workflow อยู่ใน State A |
| When | User ที่มีสิทธิ์ทำ Action ที่กำหนดใน DSL |
| Then | ✅ State เปลี่ยนเป็น State B ตาม Transition Rules |
✅ workflow_histories บันทึก from_state, to_state, action, user_id, timestamp |
|
| ✅ Event Notifications ถูก Dispatch (ถ้า DSL กำหนด) |
AC-WF-003 — Workflow Unauthorized Transition
Priority: 🔴 Blocker | Role: User ไม่ถูก Role
| Description | |
|---|---|
| Given | Workflow รอ Approve โดย Role X |
| When | User ที่เป็น Role Y (ไม่ใช่ X) พยายาม Approve |
| Then | ✅ ได้รับ 403 Forbidden |
| ✅ State ไม่เปลี่ยน |
AC-WF-004 — Workflow Visualization (UI)
Priority: 🟡 Major | Role: ทุก Role ที่มีสิทธิ์ดูเอกสาร
| Description | |
|---|---|
| Given | Workflow กำลังดำเนินการอยู่ |
| When | เปิดดูหน้ารายละเอียดเอกสาร |
| Then | ✅ แสดง Workflow Diagram พร้อม State ปัจจุบัน |
| ✅ State ที่ผ่านมาแล้วแสดง History (คลิกดูรายละเอียดได้) | |
| ✅ State ที่ยังไม่ถึง Disabled |
AC-WF-005 — Force Proceed (Document Control Override)
Priority: 🟡 Major | Role: Document Control
| Description | |
|---|---|
| Given | Workflow ติดอยู่ที่ State ใด State หนึ่ง |
| When | Document Control กด "Force Proceed" พร้อมระบุเหตุผล |
| Then | ✅ Workflow ข้ามไป State ถัดไป |
✅ Audit Log บันทึก FORCE_PROCEED + reason + user |
AC-WF-006 — Workflow Deadline & Notification
Priority: 🟡 Major | Role: Document Control
| Description | |
|---|---|
| Given | Workflow ถูกกำหนด Deadline สำหรับ Organization |
| When | เวลาผ่าน Deadline ไปแล้ว |
| Then | ✅ ระบบส่ง Reminder Notification ให้ผู้รับผิดชอบ |
| ✅ Dashboard แสดง "Overdue" indicator |
📧 Module 7: Transmittals Management
AC-TRM-001 — สร้าง Transmittal (ส่ง RFA หลายฉบับพร้อมกัน)
Priority: 🟠 Critical | Role: Document Control
| Description | |
|---|---|
| Given | มี RFA Draft หลายฉบับต้องส่งให้ที่ปรึกษา |
| When | สร้าง Transmittal แนบ RFA หลายฉบับ |
| Then | ✅ Transmittal ผูกกับ RFA ทุกฉบับ |
| ✅ Transmittal เป็นส่วนหนึ่งใน Correspondence (มีเลขเอกสาร) | |
| ✅ ผู้รับเห็น Transmittal พร้อม RFA ที่แนบ |
📄 Module 8: Circulation Sheet Management
AC-CIRC-001 — สร้าง Circulation Sheet
Priority: 🟠 Critical | Role: Document Control (ภายในองค์กร)
| Description | |
|---|---|
| Given | Correspondence เข้ามาในองค์กร |
| When | Document Control สร้าง Circulation Sheet กำหนด Main/Action/Info Assignees |
| Then | ✅ Circulation ถูกสร้าง ผูกกับ Correspondence |
| ✅ Assignees ได้รับแจ้งเตือน (In-App + Email) | |
| ✅ ผู้ใช้นอกองค์กรไม่เห็น Circulation Sheet นี้ |
AC-CIRC-002 — กำหนด Deadline + แจ้งเตือนล่วงหน้า
Priority: 🟡 Major | Role: Document Control
| Description | |
|---|---|
| Given | Circulation ถูกกำหนด Deadline ให้ Main Assignee |
| When | เหลืออีก 2 วันก่อน Deadline |
| Then | ✅ ระบบส่งแจ้งเตือน Reminder |
| ✅ Dashboard แสดง "ใกล้ Deadline" badge |
AC-CIRC-003 — ปิด Circulation
Priority: 🟠 Critical | Role: Document Control
| Description | |
|---|---|
| Given | ดำเนินการตอบกลับ Originator แล้ว |
| When | กด "ปิด Circulation" |
| Then | ✅ Circulation สถานะ = CLOSED |
| ✅ Audit Log บันทึก closed_by + timestamp |
🔢 Module 9: Document Numbering System
AC-DN-001 — Auto Number Generation (Concurrent Safe)
Priority: 🔴 Blocker | Role: ระบบ (Auto)
| Description | |
|---|---|
| Given | User 2 คนกด Submit พร้อมกัน ใน Project/Type เดียวกัน |
| When | ทั้งสองส่ง Request พร้อมกัน |
| Then | ✅ เลขเอกสารไม่ซ้ำกัน (Redis Redlock + DB Optimistic Lock) |
| ✅ Response Time < 100ms สำหรับ Generation | |
| ✅ ทั้งสอง Request สำเร็จ — ไม่มี Error |
Test Method: Load Test ด้วย 50 concurrent requests ไปที่
POST /document-numbering/reserve— ตรวจสอบว่าเลขไม่ซ้ำ
AC-DN-002 — Cancelled Number ไม่ถูกนำกลับมาใช้
Priority: 🔴 Blocker | Role: ระบบ
| Description | |
|---|---|
| Given | เลขที่ 0012 ถูก Reserved แต่ Document ถูก Cancel ก่อน Confirm |
| When | มีการ Submit Document ถัดไป |
| Then | ✅ เลขที่ถัดไปจะเป็น 0013 (ข้าม 0012) |
✅ เลข 0012 อยู่ใน document_number_reservations สถานะ CANCELLED |
AC-DN-003 — Number Format Template
Priority: 🟡 Major | Role: Superadmin
| Description | |
|---|---|
| Given | กำหนด Format Template: {PROJECT}-{ORIGINATOR}-{RECIPIENT}-{CORR_TYPE}-{SEQ:4}-{YY} |
| When | Submit Document ครั้งแรกของปีสำหรับ Pair นั้น |
| Then | ✅ เลขออกมาถูก Format (เช่น LCBP3-สค.-กทท.-LETTER-0001-68) |
| ✅ Preview ตัวอย่างเลขได้ก่อน Save Template |
AC-DN-004 — Yearly Reset
Priority: 🟡 Major | Role: ระบบ (Cron)
| Description | |
|---|---|
| Given | Correspondence ใช้ Yearly Reset Policy |
| When | ปีใหม่เปลี่ยน (Cron Job ทำงาน) |
| Then | ✅ Counter เริ่มนับใหม่จาก 0001 |
| ✅ เลขของปีก่อนยังคงอยู่ในระบบ (ไม่ถูกลบ) |
🔍 Module 10: Search & Discovery
AC-SRCH-001 — Full-text Search
Priority: 🟠 Critical | Role: ทุก Role
| Description | |
|---|---|
| Given | มีเอกสารในระบบ (Indexed ใน Elasticsearch) |
| When | พิมพ์ค้นหา Keyword ในช่อง Search |
| Then | ✅ ผล Search ปรากฏภายใน 500ms |
| ✅ ค้นหาได้จาก: เลขเอกสาร, Subject, Tag | |
| ✅ แสดงเฉพาะเอกสารที่ User มีสิทธิ์เห็น |
AC-SRCH-002 — Advanced Filter
Priority: 🟡 Major | Role: ทุก Role
| Description | |
|---|---|
| Given | อยู่ในหน้า Correspondence List |
| When | Filter ด้วย Document Type + Date Range + Status |
| Then | ✅ รายการ Filter ถูกต้อง |
| ✅ URL อัปเดตให้ Shareable (Query Params) |
📧 Module 11: Notifications
AC-NOTIF-001 — Email Notification (Document Submit)
Priority: 🟠 Critical | Role: ระบบ (Auto)
| Description | |
|---|---|
| Given | Document ถูก Submit มายังองค์กร |
| When | Workflow Transition เกิดขึ้น |
| Then | ✅ Email ถูกส่งไปยัง Recipient ภายใน 5 นาที |
| ✅ Email มี: เลขเอกสาร, Subject, ลิงก์ไปยังเอกสาร | |
| ✅ BullMQ Job อยู่ใน Queue (สามารถ Monitor ได้) |
AC-NOTIF-002 — In-App Notification
Priority: 🟡 Major | Role: ทุก Role
| Description | |
|---|---|
| Given | มี Action เกิดขึ้นที่เกี่ยวข้องกับ User |
| When | User เปิดแอป |
| Then | ✅ Bell Icon แสดง Unread Count |
| ✅ คลิกดูรายการ Notifications ได้ | |
| ✅ คลิกที่ Notification นำทางไปเอกสารที่เกี่ยวข้อง |
AC-NOTIF-003 — Notification Retry on Failure
Priority: 🟡 Major | Role: ระบบ
| Description | |
|---|---|
| Given | Email Server ไม่สามารถส่งได้ชั่วคราว |
| When | BullMQ Job ส่งไม่สำเร็จ |
| Then | ✅ Retry ด้วย Exponential Backoff (3 ครั้ง) |
| ✅ เมื่อ Retry ครบแล้วยังล้มเหลว → Dead Letter Queue | |
| ✅ In-App Notification ยังส่งได้ (Fallback) |
📎 Module 12: File Storage & Security
AC-STOR-001 — File Upload (Two-Phase Storage)
Priority: 🔴 Blocker | Role: Document Control
| Description | |
|---|---|
| Given | User อัปโหลดไฟล์ PDF ขนาด 50MB |
| When | เลือกไฟล์ + อัปโหลด |
| Then | ✅ ไฟล์ถูก Upload ไปยัง Temp Storage ก่อน |
| ✅ ClamAV Scan ในเวลา < 30 วินาที | |
| ✅ หากผ่าน Scan → ย้ายไปยัง Permanent Storage เมื่อ Document Confirmed | |
| ✅ หากไม่ผ่าน Scan → ปฏิเสธพร้อมแสดง Security Warning |
AC-STOR-002 — File Type Restriction
Priority: 🔴 Blocker | Role: Document Control
| Description | |
|---|---|
| Given | User พยายาม Upload ไฟล์ .exe หรือ .js |
| When | เลือกไฟล์นอก Whitelist |
| Then | ✅ Frontend Block ก่อน Upload |
| ✅ Backend ยืนยันซ้ำ (Defense in Depth) — 400 Bad Request |
AC-STOR-003 — Secure PDF Viewer (No Download)
Priority: 🟡 Major | Role: Viewer
| Description | |
|---|---|
| Given | User มีสิทธิ์ดูเอกสารแต่ไม่มีสิทธิ์ Download |
| When | คลิกดูเอกสาร PDF |
| Then | ✅ เปิดใน In-App PDF Viewer (ไม่ต้อง Download) |
| ✅ ปุ่ม Download ถูก Disable | |
| ✅ Range Requests (Streaming) ใช้งานได้ |
📊 Module 13: Dashboard & Audit Log
AC-DASH-001 — Dashboard KPI Cards
Priority: 🟡 Major | Role: ทุก Role
| Description | |
|---|---|
| Given | Login เสร็จ |
| When | เข้าหน้า Dashboard |
| Then | ✅ KPI Cards แสดง: จำนวน Correspondence, RFA Pending, งานของฉัน, Overdue |
| ✅ "My Tasks" แสดง Circulation ที่ตัวเองต้องทำ | |
| ✅ ข้อมูลถูกต้องตามสิทธิ์ของตัวเอง |
AC-AUDIT-001 — Audit Log Coverage
Priority: 🔴 Blocker | Role: Superadmin
| Description | |
|---|---|
| Given | ดำเนินการ Action ต่างๆ ในระบบ (Create, Update, Submit, Approve, Cancel) |
| When | ตรวจสอบ Audit Log |
| Then | ✅ ทุก Action มีบันทึกใน audit_logs (severity INFO/WARN/ERROR/CRITICAL) |
| ✅ บันทึกมี: user_id, action, entity_type, entity_uuid, details_json, ip_address, timestamp | |
| ✅ ไม่สามารถแก้ไขหรือลบ Audit Log ได้ (Read-only) |
🔐 Section 14: Security Acceptance Criteria
AC-SEC-001 — SQL Injection Prevention
Priority: 🔴 Blocker | Role: QA (Security Test)
| Description | |
|---|---|
| Given | ช่อง Input ใดๆ ในระบบ |
| When | ใส่ SQL Injection payload เช่น '; DROP TABLE users; -- |
| Then | ✅ คำขอถูกปฏิเสธหรือ Sanitized โดยไม่ทำงาน |
| ✅ Database ปลอดภัย ไม่เกิด Error จาก Injection |
AC-SEC-002 — XSS Prevention
Priority: 🔴 Blocker | Role: QA (Security Test)
| Description | |
|---|---|
| Given | ช่อง Input เช่น Subject, Comment |
| When | ใส่ <script>alert('XSS')</script> |
| Then | ✅ Script ไม่ถูก Execute ใน Browser |
| ✅ แสดงเป็น Plaintext หรือถูก Escaped |
AC-SEC-003 — Authorization Boundary (IDOR Protection)
Priority: 🔴 Blocker | Role: QA (Security Test)
| Description | |
|---|---|
| Given | User A รู้ Document UUID ของ User B (ADR-019) |
| When | User A เรียก GET /correspondences/:uuid ของ User B โดยตรง |
| Then | ✅ ได้รับ 403 Forbidden (ไม่ใช่ 404) |
| ✅ ข้อมูลของ User B ไม่ถูกเปิดเผย |
AC-SEC-004 — Rate Limiting on Auth Endpoint
Priority: 🔴 Blocker | Role: QA (Security Test)
| Description | |
|---|---|
| Given | ไม่มี Session อยู่ |
| When | เรียก POST /auth/login เกิน 5 ครั้งใน 1 นาที จาก IP เดียว |
| Then | ✅ ครั้งที่ 6+ ได้รับ 429 Too Many Requests |
| ✅ Audit Log บันทึก Rate Limit Event |
AC-SEC-005 — Security Headers
Priority: 🟠 Critical | Role: QA
| Description | |
|---|---|
| Given | ระบบทำงานบน HTTPS |
| When | ตรวจสอบ HTTP Response Headers |
| Then | ✅ X-Content-Type-Options: nosniff |
✅ X-Frame-Options: DENY |
|
✅ Strict-Transport-Security present |
|
✅ Content-Security-Policy defined |
⚡ Section 15: Performance Acceptance Criteria
AC-PERF-001 — API Response Time
Priority: 🟠 Critical
| Description | |
|---|---|
| Test Condition | 50 concurrent users, Normal workload |
| Then | ✅ P90 Response Time < 200ms สำหรับ CRUD operations |
| ✅ P90 Search Query < 500ms | |
| ✅ File Upload 50MB < 30 seconds |
Test Tool: k6 หรือ Apache JMeter Test Script:
specs/05-Engineering-Guidelines/performance-test-script.js(TODO: สร้าง)
AC-PERF-002 — Concurrent Users
Priority: 🟠 Critical
| Description | |
|---|---|
| Test Condition | 100 concurrent active users |
| Then | ✅ ระบบไม่ crash หรือ Error Rate > 1% |
| ✅ Memory ไม่เกิน 80% ของ Container Limit | |
| ✅ CPU ไม่เกิน 80% sustained |
AC-PERF-003 — Document Number Concurrent
Priority: 🔴 Blocker
| Description | |
|---|---|
| Test Condition | 50 concurrent POST /document-numbering/reserve สำหรับ Project/Type เดียวกัน |
| Then | ✅ เลขเอกสารไม่ซ้ำกันทั้ง 50 Request |
| ✅ ทุก Request สำเร็จ (ไม่มี 5xx Error) |
💾 Section 16: Data Integrity & Recovery
AC-DATA-001 — Backup & Restore
Priority: 🔴 Blocker | Role: DevOps
| Description | |
|---|---|
| Given | Production Database มีข้อมูล 1 วันทำการ |
| When | ทดสอบ Restore จาก Backup ล่าสุด |
| Then | ✅ Restore สำเร็จภายใน RTO < 4 ชั่วโมง |
| ✅ ข้อมูลสมบูรณ์ ไม่มี Data Loss เกิน RPO < 1 ชั่วโมง | |
| ✅ ระบบทำงานปกติหลัง Restore |
AC-DATA-002 — Orphan File Prevention
Priority: 🟠 Critical | Role: ระบบ
| Description | |
|---|---|
| Given | User อัปโหลดไฟล์ไปยัง Temp แล้ว Cancel Document ก่อน Confirm |
| When | Cleanup Job ทำงาน |
| Then | ✅ ไฟล์ใน Temp Storage ถูกลบ |
| ✅ Permanent Storage ไม่มี Orphan Files |
✅ UAT Sign-off Checklist
Pre-UAT Conditions
- ระบบ Deploy บน Staging Environment (ใช้ Docker Compose เหมือน Production)
- Seed Data ตาม
lcbp3-v1.8.0-seed-basic.sqlและseed-permissions.sql - Test Users ทุก Role ถูกสร้าง (Superadmin, Org Admin, Document Control, Editor, Viewer)
- Email + LINE Notify Test Mode เปิดใช้งาน
Go-Live Criteria (ต้องผ่านทั้งหมด)
| # | Criteria | Status |
|---|---|---|
| 1 | AC-AUTH-001 ~ AC-AUTH-005 ผ่านทั้งหมด | ⬜ |
| 2 | AC-ADMIN-001 ~ AC-ADMIN-005 ผ่านทั้งหมด | ⬜ |
| 3 | AC-CORR-001 ~ AC-CORR-002 (Happy Path) ผ่าน | ⬜ |
| 4 | AC-RFA-001 ~ AC-RFA-003, AC-RFA-007 ~ AC-RFA-009 (RFA Core) ผ่าน | ⬜ |
| 5 | AC-WF-001 ~ AC-WF-003 (Workflow Engine Core) ผ่าน | ⬜ |
| 6 | AC-DN-001 (Concurrent Number) ผ่าน | ⬜ |
| 7 | AC-STOR-001 (Two-Phase Storage + ClamAV) ผ่าน | ⬜ |
| 8 | AC-SEC-001 ~ AC-SEC-004 (Security) ผ่านทั้งหมด | ⬜ |
| 9 | AC-PERF-001 (Response Time) ผ่าน | ⬜ |
| 10 | AC-DATA-001 (Backup & Restore DR Test) ผ่าน | ⬜ |
| 11 | AC-AUDIT-001 (Audit Log Coverage) ผ่าน | ⬜ |
| 12 | ไม่มี Bug Priority P0/P1 ค้างอยู่ | ⬜ |
UAT Participant Sign-off
| Organization | Representative | Signature | Date |
|---|---|---|---|
| กทท. (Owner) | |||
| สค. (Admin) | |||
| TEAM (Design Consultant) | |||
| คคง. (Supervisor) | |||
| ผรม. (Contractor Rep.) | |||
| NAP (Developer) | Nattanin P. |
📝 Document Control
- Version: 1.8.1
- Status: updated
- Created: 2026-03-11 | Updated: 2026-03-24
- Owner: Nattanin Peancharoen (Product Owner / System Architect)
- Changes: Added AC-RFA-007~009 (Edit/Cancel/Search RFA), Updated status codes, Added UUID references (ADR-019), Linked edge cases
- Next Review: Prior to UAT Start
- Classification: Internal Use Only
Note
เอกสารนี้ต้องได้รับการ Sign-off จาก Stakeholder ทุกฝ่ายก่อนเริ่ม UAT ดู Gap 5 (Stakeholder Sign-off) ใน
po-analysis.mdสำหรับ Process การอนุมัติ