From 5f634c1bf81f0e6382c7adbbf894b6dae769d0d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nut=2E=E0=B9=84=E0=B8=9B=E0=B9=80=E0=B8=A3=E0=B8=B7?= =?UTF-8?q?=E0=B9=88=E0=B8=AD=E0=B8=A2?= Date: Mon, 7 Sep 2026 17:29:39 +0700 Subject: [PATCH] docs: add design spec for post-approval central review stage MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Design for auto-forwarding a fully-approved income-report request_expense into a new lightweight review stage surfaced at income-budget-plan-01 (faculty status view) and income-budget-plan-02 (central reviewer actions: ส่งแก้ไข/ตรวจสอบแล้ว + dashboard + correction history table). Deliberately introduces a new income_budget_review table rather than extending the existing approve_state round_no/resubmit mechanism, since that's hardcoded to request_approve_type "03" (admin-preconfigured queue per faculty/location) which conflicts with the confirmed requirement that the central reviewer is a single role covering every faculty/location, not a named per-unit approver. Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs --- ...09-07-income-budget-review-stage-design.md | 114 ++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 docs/superpowers/specs/2026-09-07-income-budget-review-stage-design.md diff --git a/docs/superpowers/specs/2026-09-07-income-budget-review-stage-design.md b/docs/superpowers/specs/2026-09-07-income-budget-review-stage-design.md new file mode 100644 index 0000000..8d63856 --- /dev/null +++ b/docs/superpowers/specs/2026-09-07-income-budget-review-stage-design.md @@ -0,0 +1,114 @@ +# ขั้นตอน "ตรวจสอบส่วนกลาง" หลังเชนอนุมัติคำขอเงินรายได้เสร็จสิ้น + +**วันที่:** 2026-09-07 +**อ้างอิง:** [[2026-09-07-approve-state-workflow-reference]] (โครงสร้าง `request_expense`/`approve_state` เดิม) + +## 1. ปัญหา / เป้าหมาย + +หน้า "ส่งอนุมัติคำขอเงินรายได้" (`/app/income-report`) มีเชนอนุมัติภายในคณะ/พื้นที่ตัวเอง (ผู้ส่ง → +ผู้อนุมัติ 1 → ผู้อนุมัติ 2 ...) ที่ทำงานอยู่แล้ว (ดูเอกสารอ้างอิงด้านบน) เมื่อผู้อนุมัติ**คนสุดท้าย**ของเชนนั้น +กด "อนุมัติ" (`request_expense.is_approve` เปลี่ยนเป็น `true`) ต้องการให้ระบบ: + +1. ส่งข้อมูลนั้นเข้าสู่ขั้นตอน**ตรวจสอบส่วนกลาง**โดยอัตโนมัติ — ปรากฏที่เมนู + `/app/income-budget-plan-02` ("ตรวจสรุปคำของบประมาณเงินรายได้") +2. ฝั่งคณะเห็นสถานะของตัวเองที่เมนู `/app/income-budget-plan-01` ("สรุปคำของบประมาณเงินรายได้") + +**ผู้ตรวจสอบ:** คนกลาง/ส่วนกลาง (เช่น กองนโยบายและแผน) คนเดียวตรวจได้ทุกคณะ/ทุกพื้นที่ — ไม่ได้ผูกกับ +รายชื่อเฉพาะเจาะจงแบบผู้อนุมัติในเชนเดิม สิทธิ์เข้าถึงอิงจากสิทธิ์เข้าเมนูตามระบบเดิม ไม่ใช่รายชื่อต่อเรื่อง + +**การค้นหา/กรอง:** ที่ `income-budget-plan-02` ต้องกรองตาม **ปีงบประมาณ + หน่วยงาน/คณะ + พื้นที่** +เหมือนหน้า income-report เดิม (ยืนยันจากผู้ใช้) + +## 2. ทำไมไม่ใช้กลไก `round_no` (resubmit) ที่มีอยู่แล้ว + +ระบบมี "ส่งอนุมัติเพิ่มเติม" (`ResubmitGetEntity`, เพิ่ม `round_no`) อยู่แล้ว แต่ **ผูกตายตัวกับ +`request_approve_type = "03"`** ซึ่งต้องมีแอดมินตั้งคิวผู้อนุมัติล่วงหน้าเป็นรายคณะ/พื้นที่ในเมนู +"จัดการเมนูการอนุมัติ" ก่อน — ขัดกับข้อกำหนดว่าผู้ตรวจสอบเป็น "คนกลางคนเดียว ไม่ผูกคณะ/พื้นที่" และ +จะเพิ่มภาระแอดมินที่ code `"04"` เคยถูกสร้างมาเพื่อเลิกพึ่งพาอยู่แล้ว จึง **ไม่ต่อยอด `round_no` เดิม** +แต่สร้างชั้นสถานะใหม่แยกต่างหาก ผูกกับ `request_expense_uid` โดยตรง + +## 3. โมเดลข้อมูลใหม่ + +ตารางใหม่ `income_budget_review` (1 แถวต่อ "รอบการตรวจสอบ" — มีได้หลายแถวถ้าโดนส่งแก้ไขแล้วส่งใหม่หลายรอบ +เพื่อเก็บประวัติ): + +```csharp +public class income_budget_review : base_table +{ + [Key] public Guid? income_budget_review_uid { get; set; } + public Guid? request_expense_uid { get; set; } // FK -> request_expense (เชนเดิมจาก income-report) + public short status_id { get; set; } // 1=รอตรวจสอบ, 2=ส่งแก้ไข, 3=ตรวจสอบแล้ว + public string remark { get; set; } // เหตุผล/รายละเอียดตอนกด "ส่งแก้ไข" + public string reviewed_by { get; set; } // login_name ผู้ตรวจ (ตอนกด ส่งแก้ไข/ตรวจสอบแล้ว) + public DateTime? reviewed_datetime { get; set; } +} +``` + +**Trigger สร้างแถวใหม่ (status_id=1, รอตรวจสอบ):** +ในจุดเดียวกับที่ `ApproveGetEntity` (ApproveState.cs) ตั้ง `request_expense.is_approve = true` (เคสที่ไม่มี +ลำดับถัดไปแล้ว — ดู [[2026-09-07-approve-state-workflow-reference]] ข้อ 5) ให้เพิ่ม insert +`income_budget_review` แถวใหม่ `status_id=1` **เฉพาะตอน `request_approve_type == "04"`** (ไม่กระทบ +`invest_asset`/`invest_construct`/`request_expense` code อื่นๆ ที่ใช้ engine เดียวกัน) + +**สถานะปัจจุบันของเรื่องหนึ่งๆ** = แถว `income_budget_review` ที่มี `created_datetime` ล่าสุดของ +`request_expense_uid` นั้น (query `OrderByDescending(created_datetime).First()`) + +## 4. Flow + +``` +income-report เชนอนุมัติผ่านครบ (is_approve=true) + │ (auto insert income_budget_review status_id=1) + ▼ +income-budget-plan-01 (ฝั่งคณะ) income-budget-plan-02 (ฝั่งส่วนกลาง) + เห็นสถานะ "รอตรวจสอบ" เห็นเรื่องนี้ใน dashboard "รอตรวจสอบ" + │ │ + │ ผู้ตรวจสอบกด "ส่งแก้ไข" + พิมพ์ remark + │◄───────────────────────────────────────┘ + เห็นสถานะ "ถูกส่งแก้ไข" + remark + กด "ส่งตรวจสอบใหม่" (แก้ไขข้อมูลผ่าน income-report/plan-01 ตามปกติ) + │ (insert income_budget_review row ใหม่ status_id=1) + ▼ +income-budget-plan-02 เห็นเรื่องนี้กลับมาที่ "รอตรวจสอบ" อีกครั้ง + │ + ผู้ตรวจสอบกด "ตรวจสอบแล้ว" (status_id=3, จบกระบวนการ) +``` + +## 5. Backend API (ใหม่) + +โมดูล `Modules/IncomeBudgetReview/` (ตามแพทเทิร์นโฟลเดอร์เดิมของโปรเจกต์): + +| Endpoint | Method | หน้าที่ | +|---|---|---| +| `/api/income_budget_review/search` | GET | query `budget_year_uid`, `faculty_uid`, `budget_location_uid` → คืน `request_expense` 1 เรื่อง (ถ้ามี) + สถานะรีวิวล่าสุด + ประวัติ remark ทั้งหมด | +| `/api/income_budget_review/dashboard` | GET | นับจำนวนตามสถานะทั่วทั้งระบบ (ไม่กรองคณะ — ผู้ตรวจสอบเป็นส่วนกลาง): รอตรวจสอบ, ส่งแก้ไข(ที่ยังไม่ถูกแก้), ตรวจสอบแล้ว — พร้อม list รายละเอียด (คณะ/พื้นที่/ปีงบ) ต่อหมวด เหมือน `request_expense/type_2/my_dashboard` | +| `/api/income_budget_review/return_for_edit/{request_expense_uid}` | POST | body `{ remark }` → insert แถวใหม่ `status_id=2` | +| `/api/income_budget_review/mark_reviewed/{request_expense_uid}` | POST | insert แถวใหม่ `status_id=3` — เงื่อนไข: แถวล่าสุดต้องเป็น `status_id=1` เท่านั้น (กันกดซ้ำ/กดข้ามสถานะ) | +| `/api/income_budget_review/resubmit/{request_expense_uid}` | POST | ใช้ที่ฝั่งคณะ (plan-01) กด "ส่งตรวจสอบใหม่" หลังแก้ไข — เงื่อนไข: แถวล่าสุดต้องเป็น `status_id=2` → insert แถวใหม่ `status_id=1` | + +ทุก endpoint ตรวจสอบเงื่อนไข "แถวล่าสุดของเรื่องนี้ต้องเป็นสถานะอะไร" ก่อน insert เสมอ กัน race condition/ +กดปุ่มผิดจังหวะ (เช่น กด "ตรวจสอบแล้ว" ซ้ำ หรือกด "ส่งตรวจสอบใหม่" ทั้งที่ยังไม่เคยถูกส่งแก้ไข) + +## 6. Frontend + +**`income-budget-plan-02`** (เพิ่มเข้าไปในหน้าเดิม เหนือฟอร์มค้นหา — โครงเดียวกับ dashboard ที่ทำให้ +income-report): +- การ์ด dashboard: chip กดได้ 3 อัน — "รอตรวจสอบ N", "ส่งแก้ไขไปแล้ว N" (ที่ยังไม่ถูกแก้กลับมา), + "ตรวจสอบแล้ว N" — กด chip กางลิสต์ (คณะ/พื้นที่/ปีงบ), กดแถวในลิสต์ = pre-fill ช่องค้นหาแล้วค้นหาทันที + (รูปแบบเดียวกับ `income-report-approve-dashboard.component.ts` ที่มีอยู่แล้ว — reuse โครงสร้างเดิม) +- หลังค้นหาแล้วเจอเรื่อง: แสดง **สถานะปัจจุบันชัดเจน** (badge: "รอตรวจสอบ" / "ส่งแก้ไขแล้ว รอคณะแก้ไข" / + "ตรวจสอบแล้ว") + ตาราง**ประวัติการส่งแก้ไข**ทั้งหมดของเรื่องนี้ (วันที่, remark, ผู้ตรวจ) — โครงตาราง + เดียวกับ "รายละเอียดสำหรับการส่งแก้ไข" ที่มีอยู่แล้วในหน้า income-report (`remark_history`) +- ปุ่ม "ส่งแก้ไข" (เปิด dialog ให้พิมพ์ remark ก่อนยืนยัน) และ "ตรวจสอบแล้ว" — โชว์เฉพาะตอนสถานะปัจจุบัน + เป็น "รอตรวจสอบ" เท่านั้น + +**`income-budget-plan-01`** (เพิ่มเข้าไปในหน้าเดิม): +- Badge สถานะเดียวกัน ("รอตรวจสอบ" / "ถูกส่งแก้ไข" + remark ล่าสุด / "ตรวจสอบแล้ว") ต่อเรื่องที่ค้นหาอยู่ +- ปุ่ม "ส่งตรวจสอบใหม่" — โชว์เฉพาะตอนสถานะเป็น "ถูกส่งแก้ไข" เท่านั้น + +## 7. นอกขอบเขตรอบนี้ (YAGNI) + +- แจ้งเตือนแบบ real-time/อีเมล/LINE — dashboard โหลดตอนเข้าเมนูเหมือนเดิมพอ +- สิทธิ์ผู้ตรวจสอบละเอียดกว่า "เข้าเมนูนี้ได้ = ตรวจได้" (เช่น แบ่งสิทธิ์ตามประเภทงบ) — ยังไม่มีความต้องการ + ตอนนี้ ถ้าจะเพิ่มทีหลังค่อยทำเป็นรอบใหม่ +- แก้ไขข้อมูลตัวเลขจริงๆ ที่หน้า plan-01/02 — สมมติว่าคณะยังกลับไปแก้ที่ income-report/ฟอร์มเดิมตามปกติ + plan-01/02 รอบนี้ทำแค่ "แสดงสถานะ + ปุ่มเปลี่ยนสถานะ" ไม่ใช่หน้าแก้ไขตัวเลข