docs: add design spec for post-approval central review stage
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 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs
This commit is contained in:
co-authored by
Claude Sonnet 5
parent
efbc4618c2
commit
5f634c1bf8
@@ -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 รอบนี้ทำแค่ "แสดงสถานะ + ปุ่มเปลี่ยนสถานะ" ไม่ใช่หน้าแก้ไขตัวเลข
|
||||||
Reference in New Issue
Block a user