diff --git a/docs/superpowers/specs/2026-06-17-disbursement-plan-research-design.md b/docs/superpowers/specs/2026-06-17-disbursement-plan-research-design.md new file mode 100644 index 0000000..b7ac382 --- /dev/null +++ b/docs/superpowers/specs/2026-06-17-disbursement-plan-research-design.md @@ -0,0 +1,132 @@ +# Design: แผนการเบิกจ่ายเป็นงวด (Research Disbursement Plan) + +**Date:** 2026-06-17 +**Page:** `http://localhost:4200/app/agency-report-research` (typeUrl=27) +**Approved by:** User + +--- + +## 1. Summary + +เพิ่มฟีเจอร์ "แผนการเบิกจ่ายเป็นงวด" ให้กับหน้า `agency-report-research` โดยมีปุ่มไอคอนต่อแต่ละโครงการในตาราง list20-research เมื่อกดจะเปิด MatDialog popup สำหรับกรอก/แก้ไขแผนการเบิกจ่าย 3 งวด พร้อมบันทึกลง DB ผ่าน API เดิม + +--- + +## 2. Data Model + +### 2.1 Backend — เพิ่ม 6 field ใน `change_project_research_detail` + +| Field | Type | Description | +|-------|------|-------------| +| `disbursement_1_amount` | `decimal?` | จำนวนเงิน งวดที่ 1 | +| `disbursement_1_date` | `DateTime?` | ว/ด/ป งวดที่ 1 | +| `disbursement_2_amount` | `decimal?` | จำนวนเงิน งวดที่ 2 | +| `disbursement_2_date` | `DateTime?` | ว/ด/ป งวดที่ 2 | +| `disbursement_last_amount` | `decimal?` | จำนวนเงิน งวดสุดท้าย | +| `disbursement_last_date` | `DateTime?` | ว/ด/ป งวดสุดท้าย | + +**ทำไม:** เก็บข้อมูลบน record เดิม ไม่ต้องสร้างตารางใหม่ ข้อมูลต่อโครงการมีเพียง 1 ชุด (3 งวด) +**หมายเหตุ:** `รวมเบิกจ่ายทั้งสิ้น` คำนวณใน frontend (sum ของ 3 amount) ไม่เก็บใน DB + +### 2.2 Migration + +ไฟล์: `Migrations/YYYYMMDDHHMMSS_disbursement_plan_research.cs` +- `AddColumn` ทั้ง 6 field ใน table `change_project_research_detail` schema `BUDGET` + +--- + +## 3. Architecture + +### 3.1 Backend (ASP.NET Core) + +- **ไม่ต้องสร้าง controller ใหม่** — `t_change_project_research_detail` มี `[GeneratedUidController]` อยู่แล้ว +- เพิ่ม field ในโมเดล → migration → deploy +- PUT endpoint เดิม `/api/request_budget/change_project_research_detail/{uid}` รองรับ field ใหม่โดยอัตโนมัติ + +### 3.2 Frontend (Angular) + +``` +list20-research component + └─ เพิ่ม Output: onDisbursementPlan (EventEmitter) + └─ เพิ่มคอลัมน์ "แผนเบิกจ่าย" + ปุ่มไอคอน + +request-budget-statistics.container + └─ handle onDisbursementPlan → เปิด MatDialog + +DisbursementPlanResearchDialogComponent (ใหม่) + ├─ Input: data (change_project_research_detail row) + ├─ Form: disbursement_1_amount, disbursement_1_date, disbursement_2_amount, disbursement_2_date, disbursement_last_amount, disbursement_last_date + ├─ Computed: total = sum(amounts) + └─ Save: PUT via ChangeProjectResearchDetailService +``` + +--- + +## 4. UI Design + +### 4.1 ตาราง list20-research — คอลัมน์เพิ่มใหม่ + +| คอลัมน์ | เนื้อหา | +|---------|---------| +| แผนเบิกจ่าย | badge "✓ กรอกแล้ว" (สีเขียว) ถ้า disbursement_1_amount ไม่ null, badge "ยังไม่กรอก" (สีเทา) ถ้ายังไม่มีข้อมูล | +| เครื่องมือ | เพิ่มปุ่มไอคอนเงิน (💰) ก่อนปุ่ม edit — สีเขียวเข้มถ้ากรอกแล้ว, สีเขียวอ่อนถ้ายังไม่กรอก | + +### 4.2 Dialog — ตาราง + +``` +┌─────────────────────────────────────────────┬──────────────────┐ +│ แผนการเบิกจ่ายเงิน │ รวมเบิกจ่าย │ +├──────────────┬──────────────┬───────────────┤ ทั้งสิ้น (บาท) │ +│ งวดที่ 1 │ งวดที่ 2 │ งวดสุดท้าย │ │ +├──────┬───────┼──────┬───────┼──────┬────────┤ │ +│ จำนวน│ ว/ด/ป │ จำนวน│ ว/ด/ป │ จำนวน│ ว/ด/ป │ [คำนวณอัตโนมัติ] │ +│ เงิน │ │ เงิน │ │ เงิน │ │ │ +├──────┼───────┼──────┼───────┼──────┼────────┼──────────────────┤ +│ input│ date │ input│ date │ input│ date │ readonly computed │ +└──────┴───────┴──────┴───────┴──────┴────────┴──────────────────┘ +``` + +- Input จำนวนเงิน: ใช้ `appCurrencyInputMask` (pattern เดิมในโปรเจกต์) +- Input วันที่: `mat-datepicker` +- รวม: คำนวณ real-time ด้วย getter + +### 4.3 Actions + +- **บันทึก**: confirmSave → PUT detail → updateSuccess → close dialog → reload list +- **ยกเลิก**: ปิด dialog ไม่บันทึก + +--- + +## 5. Files to Create/Modify + +### Backend +| File | Action | +|------|--------| +| `Modules/RequestBudgets/Databases/Models/change_project_research_detail.cs` | เพิ่ม 6 field | +| `Migrations/YYYYMMDDHHMMSS_disbursement_plan_research.cs` | สร้างใหม่ | + +### Frontend +| File | Action | +|------|--------| +| `presenter/popup/disbursement-plan-research-dialog/disbursement-plan-research-dialog.component.ts` | สร้างใหม่ | +| `presenter/popup/disbursement-plan-research-dialog/disbursement-plan-research-dialog.component.html` | สร้างใหม่ | +| `presenter/popup/disbursement-plan-research-dialog/disbursement-plan-research-dialog.component.scss` | สร้างใหม่ | +| `presenter/list/.../list20-research/list20-research.component.html` | เพิ่มคอลัมน์ + ปุ่ม | +| `presenter/list/.../list20-research/list20-research.component.ts` | เพิ่ม Output onDisbursementPlan | +| `container/.../request-budget-statistics.container.ts` | handle event + เปิด dialog | +| `request-budget-statistics.module.ts` | ลงทะเบียน component ใหม่ | + +--- + +## 6. Error Handling + +- ถ้า save ล้มเหลว: แสดง `swSV.errText(err?.error?.description)` +- Dialog ใช้ `ChangeDetectionStrategy.OnPush` + `cdRef.detectChanges()` ตาม pattern เดิม + +--- + +## 7. Out of Scope + +- ไม่สร้างหน้าแยก (ใช้ dialog แทน) +- ไม่รองรับหลายชุดแผนต่อโครงการ (1 โครงการ = 1 แผน) +- ไม่เพิ่ม column ใน list view (แสดงเฉพาะใน dialog)