docs: mark income-budget-review plan tasks complete

All backend (Tasks 1-3) and frontend (Tasks 4-7) code written, deployed to
production, and verified end-to-end (Task 8) via a synthetic test record —
except Task 7's manual browser click-through, which needs the user's own
login to confirm visually.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0153wBt23EjW125ZsADwWVAs
This commit is contained in:
Nut.ไปเรื่อย
2026-09-07 19:56:58 +07:00
co-authored by Claude Sonnet 5
parent f0441b9e96
commit 29f2da97da
@@ -54,7 +54,7 @@ frontend เพิ่ม dashboard component (reuse pattern จาก `income-re
(1=รอตรวจสอบ, 2=ส่งแก้ไข, 3=ตรวจสอบแล้ว), `remark: string`, บวก field จาก `base_table` (1=รอตรวจสอบ, 2=ส่งแก้ไข, 3=ตรวจสอบแล้ว), `remark: string`, บวก field จาก `base_table`
(`created_by`, `created_datetime`, `updated_by`, `updated_datetime`, `owner_agency_uid`, `status_id`) (`created_by`, `created_datetime`, `updated_by`, `updated_datetime`, `owner_agency_uid`, `status_id`)
- [ ] **Step 1: สร้างโมเดล C#** - [x] **Step 1: สร้างโมเดล C#**
```csharp ```csharp
// rmutr-api/Modules/IncomeBudgetReview/Databases/Models/income_budget_review.cs // rmutr-api/Modules/IncomeBudgetReview/Databases/Models/income_budget_review.cs
@@ -80,7 +80,7 @@ namespace rmutr_budget_api.Modules.IncomeBudgetReview.Databases.Models
} }
``` ```
- [ ] **Step 2: สร้าง `Db.cs` ของโมดูลนี้ (DbSet + ToTable)** - [x] **Step 2: สร้าง `Db.cs` ของโมดูลนี้ (DbSet + ToTable)**
```csharp ```csharp
// rmutr-api/Modules/IncomeBudgetReview/Databases/Db.cs // rmutr-api/Modules/IncomeBudgetReview/Databases/Db.cs
@@ -101,7 +101,7 @@ namespace SeventyOneDev.Utilities
} }
``` ```
- [ ] **Step 3: เรียก `OnIncomeBudgetReviewModelCreating` จากจุดกลาง** - [x] **Step 3: เรียก `OnIncomeBudgetReviewModelCreating` จากจุดกลาง**
แก้ `rmutr-api/Databases/Db.cs` — ในเมธอด `OnApplicationModelCreating` เพิ่มบรรทัดสุดท้าย: แก้ `rmutr-api/Databases/Db.cs` — ในเมธอด `OnApplicationModelCreating` เพิ่มบรรทัดสุดท้าย:
@@ -111,7 +111,7 @@ namespace SeventyOneDev.Utilities
} }
``` ```
- [ ] **Step 4: เขียน migration SQL (idempotent เหมือนไฟล์อื่นในโฟลเดอร์เดียวกัน)** - [x] **Step 4: เขียน migration SQL (idempotent เหมือนไฟล์อื่นในโฟลเดอร์เดียวกัน)**
```sql ```sql
-- rmutr-api/Migrations/add_income_budget_review.sql -- rmutr-api/Migrations/add_income_budget_review.sql
@@ -138,7 +138,7 @@ CREATE INDEX IF NOT EXISTS ix_income_budget_review_request_expense_uid
ON "{0}".income_budget_review (request_expense_uid); ON "{0}".income_budget_review (request_expense_uid);
``` ```
- [ ] **Step 5: ลงทะเบียน migration ใน `Startup.cs`** - [x] **Step 5: ลงทะเบียน migration ใน `Startup.cs`**
แก้ `rmutr-api/Startup.cs` — เพิ่มบรรทัดต่อจาก `add_faculty_uid_to_budget_income.sql` (ประมาณบรรทัด 486): แก้ `rmutr-api/Startup.cs` — เพิ่มบรรทัดต่อจาก `add_faculty_uid_to_budget_income.sql` (ประมาณบรรทัด 486):
@@ -147,12 +147,12 @@ CREATE INDEX IF NOT EXISTS ix_income_budget_review_request_expense_uid
ApplyRawSqlMigration(dbContext, setting.Value.default_schema, "add_income_budget_review.sql"); ApplyRawSqlMigration(dbContext, setting.Value.default_schema, "add_income_budget_review.sql");
``` ```
- [ ] **Step 6: Build ตรวจสอบว่าไม่มี compile error** - [x] **Step 6: Build ตรวจสอบว่าไม่มี compile error**
Run: `cd rmutr-api && dotnet build -v q` Run: `cd rmutr-api && dotnet build -v q`
Expected: `0 Error(s)` (มี warning เดิมได้ ไม่เกี่ยวกับ task นี้) Expected: `0 Error(s)` (มี warning เดิมได้ ไม่เกี่ยวกับ task นี้)
- [ ] **Step 7: Commit** - [x] **Step 7: Commit**
```bash ```bash
cd rmutr-api cd rmutr-api
@@ -177,7 +177,7 @@ Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
ส่วนกลางแล้วอนุมัติผ่านใหม่) และ `request_approve_type == "04"` จะมี `t_income_budget_review` แถวใหม่ ส่วนกลางแล้วอนุมัติผ่านใหม่) และ `request_approve_type == "04"` จะมี `t_income_budget_review` แถวใหม่
`review_status_id = 1` เกิดขึ้นเสมอ `review_status_id = 1` เกิดขึ้นเสมอ
- [ ] **Step 1: หาจุด insert ใน `ApproveGetEntity` (branch `request_expense`)** - [x] **Step 1: หาจุด insert ใน `ApproveGetEntity` (branch `request_expense`)**
เปิด `rmutr-api/Modules/Setting/Controllers/ApproveState.cs` หา block นี้ (อยู่ในเมธอด เปิด `rmutr-api/Modules/Setting/Controllers/ApproveState.cs` หา block นี้ (อยู่ในเมธอด
`ApproveGetEntity`, branch `if (request_expense != null)`): `ApproveGetEntity`, branch `if (request_expense != null)`):
@@ -194,7 +194,7 @@ Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
} }
``` ```
- [ ] **Step 2: แก้ไข block นี้ให้ log "รอตรวจสอบ" เมื่อ type เป็น "04"** - [x] **Step 2: แก้ไข block นี้ให้ log "รอตรวจสอบ" เมื่อ type เป็น "04"**
แทนที่ block ด้านบนด้วย: แทนที่ block ด้านบนด้วย:
@@ -225,7 +225,7 @@ Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
} }
``` ```
- [ ] **Step 3: เพิ่ม `using` ที่หัวไฟล์** - [x] **Step 3: เพิ่ม `using` ที่หัวไฟล์**
เปิด `rmutr-api/Modules/Setting/Controllers/ApproveState.cs` เพิ่มบรรทัด using (หลัง using เดิมบรรทัดที่ 18): เปิด `rmutr-api/Modules/Setting/Controllers/ApproveState.cs` เพิ่มบรรทัด using (หลัง using เดิมบรรทัดที่ 18):
@@ -233,12 +233,12 @@ Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
using rmutr_budget_api.Modules.IncomeBudgetReview.Databases.Models; using rmutr_budget_api.Modules.IncomeBudgetReview.Databases.Models;
``` ```
- [ ] **Step 4: Build** - [x] **Step 4: Build**
Run: `cd rmutr-api && dotnet build -v q` Run: `cd rmutr-api && dotnet build -v q`
Expected: `0 Error(s)` Expected: `0 Error(s)`
- [ ] **Step 5: Commit** - [x] **Step 5: Commit**
```bash ```bash
cd rmutr-api cd rmutr-api
@@ -272,7 +272,7 @@ Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
→ `200 OK` หรือ `400 { description }` → `200 OK` หรือ `400 { description }`
- `POST /api/income_budget_review/mark_reviewed/{request_expense_uid}` → `200 OK` หรือ `400 { description }` - `POST /api/income_budget_review/mark_reviewed/{request_expense_uid}` → `200 OK` หรือ `400 { description }`
- [ ] **Step 1: เขียน DTO + Service** - [x] **Step 1: เขียน DTO + Service**
```csharp ```csharp
// rmutr-api/Modules/IncomeBudgetReview/Services/IncomeBudgetReview.cs // rmutr-api/Modules/IncomeBudgetReview/Services/IncomeBudgetReview.cs
@@ -517,7 +517,7 @@ namespace rmutr_budget_api.Modules.IncomeBudgetReview.Services
} }
``` ```
- [ ] **Step 2: เขียน Controller** - [x] **Step 2: เขียน Controller**
```csharp ```csharp
// rmutr-api/Modules/IncomeBudgetReview/Controllers/IncomeBudgetReview.cs // rmutr-api/Modules/IncomeBudgetReview/Controllers/IncomeBudgetReview.cs
@@ -592,7 +592,7 @@ namespace rmutr_budget_api.Modules.IncomeBudgetReview.Controllers
} }
``` ```
- [ ] **Step 3: เขียน Configure (DI registration) แล้วเรียกจาก `Startup.cs`** - [x] **Step 3: เขียน Configure (DI registration) แล้วเรียกจาก `Startup.cs`**
```csharp ```csharp
// rmutr-api/Modules/IncomeBudgetReview/Configures/IncomeBudgetReview.cs // rmutr-api/Modules/IncomeBudgetReview/Configures/IncomeBudgetReview.cs
@@ -620,12 +620,12 @@ namespace rmutr_budget_api.Modules.IncomeBudgetReview.Configures
services.AddIncomeBudgetReviewServices(); services.AddIncomeBudgetReviewServices();
``` ```
- [ ] **Step 4: Build** - [x] **Step 4: Build**
Run: `cd rmutr-api && dotnet build -v q` Run: `cd rmutr-api && dotnet build -v q`
Expected: `0 Error(s)` Expected: `0 Error(s)`
- [ ] **Step 5: Deploy ไปเซิร์ฟเวอร์จริงเพื่อทดสอบ** - [x] **Step 5: Deploy ไปเซิร์ฟเวอร์จริงเพื่อทดสอบ**
```bash ```bash
cd rmutr-api cd rmutr-api
@@ -641,7 +641,7 @@ curl -sS -o /dev/null -w "HTTP %{http_code}\n" https://rmis.rmutr.ac.th/budget-a
Expected: `HTTP 401` (service ขึ้นปกติ, endpoint ต้อง auth) Expected: `HTTP 401` (service ขึ้นปกติ, endpoint ต้อง auth)
- [ ] **Step 6: ทดสอบ endpoint จริงด้วย token ที่ mint เอง (วิธีเดียวกับที่ใช้ทดสอบ my_dashboard ก่อนหน้านี้)** - [x] **Step 6: ทดสอบ endpoint จริงด้วย token ที่ mint เอง (วิธีเดียวกับที่ใช้ทดสอบ my_dashboard ก่อนหน้านี้)**
```bash ```bash
python3 - <<'EOF' > /tmp/token.txt python3 - <<'EOF' > /tmp/token.txt
@@ -663,7 +663,7 @@ curl -sS -H "Authorization: Bearer $TOKEN" \
Expected: `HTTP:200` กับ `{"pending":[],"returned":[],"reviewed":[]}` (ว่างเปล่าเพราะยังไม่มีเรื่องไหนผ่าน Expected: `HTTP:200` กับ `{"pending":[],"returned":[],"reviewed":[]}` (ว่างเปล่าเพราะยังไม่มีเรื่องไหนผ่าน
Task 2's trigger เลยตอนนี้ — ถูกต้องแล้ว จะมีข้อมูลจริงหลัง Task 2 ถูก exercise จากการอนุมัติจริงในระบบ) Task 2's trigger เลยตอนนี้ — ถูกต้องแล้ว จะมีข้อมูลจริงหลัง Task 2 ถูก exercise จากการอนุมัติจริงในระบบ)
- [ ] **Step 7: Commit** - [x] **Step 7: Commit**
```bash ```bash
cd rmutr-api cd rmutr-api
@@ -686,7 +686,7 @@ git push origin master
- Produces: `IncomeBudgetReviewService` with methods `getStatus(uid)`, `getDashboard()`, - Produces: `IncomeBudgetReviewService` with methods `getStatus(uid)`, `getDashboard()`,
`returnForEdit(uid, remark)`, `markReviewed(uid)` — เรียก endpoint จาก Task 3 `returnForEdit(uid, remark)`, `markReviewed(uid)` — เรียก endpoint จาก Task 3
- [ ] **Step 1: เขียน service** - [x] **Step 1: เขียน service**
```typescript ```typescript
// rmutr-web/src/app/core/service/income-budget-review/income-budget-review.service.ts // rmutr-web/src/app/core/service/income-budget-review/income-budget-review.service.ts
@@ -721,12 +721,12 @@ export class IncomeBudgetReviewService {
} }
``` ```
- [ ] **Step 2: Build ตรวจสอบว่า Angular compile ผ่าน** - [x] **Step 2: Build ตรวจสอบว่า Angular compile ผ่าน**
Run: `cd rmutr-web && node --max_old_space_size=14336 node_modules/@angular/cli/bin/ng build --configuration production --base-href /budget-web/ 2>&1 | tail -20` Run: `cd rmutr-web && node --max_old_space_size=14336 node_modules/@angular/cli/bin/ng build --configuration production --base-href /budget-web/ 2>&1 | tail -20`
Expected: build จบโดยไม่มี error (มี warning เดิมได้) Expected: build จบโดยไม่มี error (มี warning เดิมได้)
- [ ] **Step 3: Commit** - [x] **Step 3: Commit**
```bash ```bash
cd rmutr-web cd rmutr-web
@@ -753,7 +753,7 @@ Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
`{ request_expense_uid, budget_year_uid, budget_year_name_th, faculty_uid, faculty_name_th, `{ request_expense_uid, budget_year_uid, budget_year_name_th, faculty_uid, faculty_name_th,
budget_location_uid, budget_location_name_th }` budget_location_uid, budget_location_name_th }`
- [ ] **Step 1: สร้างโฟลเดอร์และ component (โครงเดียวกับ `income-report-approve-dashboard` ที่มีอยู่แล้ว)** - [x] **Step 1: สร้างโฟลเดอร์และ component (โครงเดียวกับ `income-report-approve-dashboard` ที่มีอยู่แล้ว)**
```typescript ```typescript
// income-budget-review-dashboard.component.ts // income-budget-review-dashboard.component.ts
@@ -828,7 +828,7 @@ export class IncomeBudgetReviewDashboardComponent implements OnInit {
} }
``` ```
- [ ] **Step 2: เขียน template** - [x] **Step 2: เขียน template**
```html ```html
<!-- income-budget-review-dashboard.component.html --> <!-- income-budget-review-dashboard.component.html -->
@@ -860,7 +860,7 @@ export class IncomeBudgetReviewDashboardComponent implements OnInit {
</div> </div>
``` ```
- [ ] **Step 3: เขียน style (คัดลอกจาก `income-report-approve-dashboard.component.scss` ทั้งไฟล์)** - [x] **Step 3: เขียน style (คัดลอกจาก `income-report-approve-dashboard.component.scss` ทั้งไฟล์)**
```bash ```bash
cp rmutr-web/src/app/feature/income-report/presenter/dashboard/income-report-approve-dashboard/income-report-approve-dashboard.component.scss \ cp rmutr-web/src/app/feature/income-report/presenter/dashboard/income-report-approve-dashboard/income-report-approve-dashboard.component.scss \
@@ -870,7 +870,7 @@ cp rmutr-web/src/app/feature/income-report/presenter/dashboard/income-report-app
(เนื้อหา scss เดิมใช้ได้เลย — class names `.dashboard-card`, `.chip`, `.chip-warn`, `.chip-success`, (เนื้อหา scss เดิมใช้ได้เลย — class names `.dashboard-card`, `.chip`, `.chip-warn`, `.chip-success`,
`.item-list`, `.item-row`, `.item-empty` ตรงกันกับ template ด้านบนทุกตัว) `.item-list`, `.item-row`, `.item-empty` ตรงกันกับ template ด้านบนทุกตัว)
- [ ] **Step 4: ประกาศ component ใน module** - [x] **Step 4: ประกาศ component ใน module**
แก้ `rmutr-web/src/app/feature/budget-request/request-budget-plan/request-budget-plan.module.ts` แก้ `rmutr-web/src/app/feature/budget-request/request-budget-plan/request-budget-plan.module.ts`
เพิ่ม import และใส่เข้า `declarations`: เพิ่ม import และใส่เข้า `declarations`:
@@ -881,12 +881,12 @@ import { IncomeBudgetReviewDashboardComponent } from './presenter/dashboard/inco
ใน `declarations: [...]` เพิ่ม `IncomeBudgetReviewDashboardComponent,` ต่อจาก `RequestBudgetListComponent,` ใน `declarations: [...]` เพิ่ม `IncomeBudgetReviewDashboardComponent,` ต่อจาก `RequestBudgetListComponent,`
- [ ] **Step 5: Build** - [x] **Step 5: Build**
Run: `cd rmutr-web && node --max_old_space_size=14336 node_modules/@angular/cli/bin/ng build --configuration production --base-href /budget-web/ 2>&1 | tail -20` Run: `cd rmutr-web && node --max_old_space_size=14336 node_modules/@angular/cli/bin/ng build --configuration production --base-href /budget-web/ 2>&1 | tail -20`
Expected: build ผ่าน ไม่มี error Expected: build ผ่าน ไม่มี error
- [ ] **Step 6: Commit** - [x] **Step 6: Commit**
```bash ```bash
cd rmutr-web cd rmutr-web
@@ -913,7 +913,7 @@ Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
— `showActions=true` ที่ plan-02 (โชว์ปุ่ม), `false` ที่ plan-01 (โชว์อย่างเดียว) — `showActions=true` ที่ plan-02 (โชว์ปุ่ม), `false` ที่ plan-01 (โชว์อย่างเดียว)
`(onchanged)` emit เมื่อกดปุ่มสำเร็จ ให้ container โหลดข้อมูลใหม่ `(onchanged)` emit เมื่อกดปุ่มสำเร็จ ให้ container โหลดข้อมูลใหม่
- [ ] **Step 1: เขียน component** - [x] **Step 1: เขียน component**
```typescript ```typescript
// income-budget-review-status.component.ts // income-budget-review-status.component.ts
@@ -1028,7 +1028,7 @@ export class IncomeBudgetReviewStatusComponent implements OnChanges {
} }
``` ```
- [ ] **Step 2: เขียน template** - [x] **Step 2: เขียน template**
```html ```html
<!-- income-budget-review-status.component.html --> <!-- income-budget-review-status.component.html -->
@@ -1066,7 +1066,7 @@ export class IncomeBudgetReviewStatusComponent implements OnChanges {
</div> </div>
``` ```
- [ ] **Step 3: เขียน style** - [x] **Step 3: เขียน style**
```scss ```scss
// income-budget-review-status.component.scss // income-budget-review-status.component.scss
@@ -1138,7 +1138,7 @@ export class IncomeBudgetReviewStatusComponent implements OnChanges {
} }
``` ```
- [ ] **Step 4: ประกาศ component ใน module** - [x] **Step 4: ประกาศ component ใน module**
แก้ `rmutr-web/src/app/feature/budget-request/request-budget-plan/request-budget-plan.module.ts` แก้ `rmutr-web/src/app/feature/budget-request/request-budget-plan/request-budget-plan.module.ts`
เพิ่ม import และใส่เข้า `declarations`: เพิ่ม import และใส่เข้า `declarations`:
@@ -1149,12 +1149,12 @@ import { IncomeBudgetReviewStatusComponent } from './presenter/status/income-bud
ใน `declarations: [...]` เพิ่ม `IncomeBudgetReviewStatusComponent,` ใน `declarations: [...]` เพิ่ม `IncomeBudgetReviewStatusComponent,`
- [ ] **Step 5: Build** - [x] **Step 5: Build**
Run: `cd rmutr-web && node --max_old_space_size=14336 node_modules/@angular/cli/bin/ng build --configuration production --base-href /budget-web/ 2>&1 | tail -20` Run: `cd rmutr-web && node --max_old_space_size=14336 node_modules/@angular/cli/bin/ng build --configuration production --base-href /budget-web/ 2>&1 | tail -20`
Expected: build ผ่าน ไม่มี error Expected: build ผ่าน ไม่มี error
- [ ] **Step 6: Commit** - [x] **Step 6: Commit**
```bash ```bash
cd rmutr-web cd rmutr-web
@@ -1178,7 +1178,7 @@ Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
- Produces: ปุ่ม/สถานะแสดงผลจริงที่ `income-budget-plan-01` (`keyUrl==201`) และ `income-budget-plan-02` - Produces: ปุ่ม/สถานะแสดงผลจริงที่ `income-budget-plan-01` (`keyUrl==201`) และ `income-budget-plan-02`
(`keyUrl==202`) — dashboard บน plan-02 เท่านั้น, status badge ทั้งสองหน้า (`keyUrl==202`) — dashboard บน plan-02 เท่านั้น, status badge ทั้งสองหน้า
- [ ] **Step 1: เพิ่ม dashboard (เฉพาะ plan-02) เหนือฟอร์มค้นหา** - [x] **Step 1: เพิ่ม dashboard (เฉพาะ plan-02) เหนือฟอร์มค้นหา**
แก้ `request-budget.container.html` เพิ่มก่อนบรรทัดแรก (`<div *ngIf="keyUrl == 203"...`): แก้ `request-budget.container.html` เพิ่มก่อนบรรทัดแรก (`<div *ngIf="keyUrl == 203"...`):
@@ -1189,7 +1189,7 @@ Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
></app-income-budget-review-dashboard> ></app-income-budget-review-dashboard>
``` ```
- [ ] **Step 2: เพิ่ม status component (ทั้งสองหน้า) หลังฟอร์มค้นหา ก่อน list** - [x] **Step 2: เพิ่ม status component (ทั้งสองหน้า) หลังฟอร์มค้นหา ก่อน list**
แก้ `request-budget.container.html` เพิ่มหลัง `</app-request-budget-search>` (บรรทัด 14) ก่อน แก้ `request-budget.container.html` เพิ่มหลัง `</app-request-budget-search>` (บรรทัด 14) ก่อน
`<app-request-budget-list` (บรรทัด 15): `<app-request-budget-list` (บรรทัด 15):
@@ -1203,7 +1203,7 @@ Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>"
></app-income-budget-review-status> ></app-income-budget-review-status>
``` ```
- [ ] **Step 3: เพิ่มเมธอด `onSelectReviewDashboardItem` ใน container** - [x] **Step 3: เพิ่มเมธอด `onSelectReviewDashboardItem` ใน container**
`RequestBudgetContainer.onClickSearch(query)` (มีอยู่แล้ว) รับ query object อิสระได้เลยโดยไม่ต้องมาจาก `RequestBudgetContainer.onClickSearch(query)` (มีอยู่แล้ว) รับ query object อิสระได้เลยโดยไม่ต้องมาจาก
`RequestBudgetSearchComponent` เสมอไป (แค่ต้องมี `budget_year_uid`/`faculty_uid`/`budget_location_uid` `RequestBudgetSearchComponent` เสมอไป (แค่ต้องมี `budget_year_uid`/`faculty_uid`/`budget_location_uid`
@@ -1229,12 +1229,12 @@ dashboard ของตัวเอง (`IncomeReportContainer.onSelectDashboardI
} }
``` ```
- [ ] **Step 4: Build** - [x] **Step 4: Build**
Run: `cd rmutr-web && node --max_old_space_size=14336 node_modules/@angular/cli/bin/ng build --configuration production --base-href /budget-web/ 2>&1 | tail -20` Run: `cd rmutr-web && node --max_old_space_size=14336 node_modules/@angular/cli/bin/ng build --configuration production --base-href /budget-web/ 2>&1 | tail -20`
Expected: build ผ่าน ไม่มี error Expected: build ผ่าน ไม่มี error
- [ ] **Step 5: Deploy ไปเซิร์ฟเวอร์จริง** - [x] **Step 5: Deploy ไปเซิร์ฟเวอร์จริง**
```bash ```bash
cd rmutr-web cd rmutr-web
@@ -1252,7 +1252,7 @@ remark ในตาราง "รายละเอียดสำหรับ
`https://rmis.rmutr.ac.th/budget-web/app/income-budget-plan-01` ค้นหาเรื่องเดียวกัน ต้องเห็น badge `https://rmis.rmutr.ac.th/budget-web/app/income-budget-plan-01` ค้นหาเรื่องเดียวกัน ต้องเห็น badge
"ถูกส่งแก้ไข" เช่นกัน (ไม่มีปุ่ม) "ถูกส่งแก้ไข" เช่นกัน (ไม่มีปุ่ม)
- [ ] **Step 7: Commit** - [x] **Step 7: Commit**
```bash ```bash
cd rmutr-web cd rmutr-web
@@ -1269,7 +1269,7 @@ git push origin master
**Files:** ไม่มีไฟล์ใหม่ — task นี้คือ verify ผ่าน SQL + curl ตรงกับ production ตามรูปแบบที่ใช้ตลอด session **Files:** ไม่มีไฟล์ใหม่ — task นี้คือ verify ผ่าน SQL + curl ตรงกับ production ตามรูปแบบที่ใช้ตลอด session
- [ ] **Step 1: หาเรื่องจริงในระบบที่ใกล้จะอนุมัติผ่านครบ (หรือสร้างเคสทดสอบด้วย SQL)** - [x] **Step 1: หาเรื่องจริงในระบบที่ใกล้จะอนุมัติผ่านครบ (หรือสร้างเคสทดสอบด้วย SQL)**
```bash ```bash
python3 - <<'EOF' python3 - <<'EOF'
@@ -1287,7 +1287,7 @@ for r in cur.fetchall(): print(r)
EOF EOF
``` ```
- [ ] **Step 2: ยืนยันว่า trigger (Task 2) ทำงานจริงหลังมีเรื่องอนุมัติผ่านครบในระบบจริง** - [x] **Step 2: ยืนยันว่า trigger (Task 2) ทำงานจริงหลังมีเรื่องอนุมัติผ่านครบในระบบจริง**
```bash ```bash
python3 - <<'EOF' python3 - <<'EOF'
@@ -1302,12 +1302,12 @@ EOF
Expected: มากกว่า 0 หลังมีการอนุมัติจริงผ่านระบบครบอย่างน้อย 1 เรื่องนับจากตอน deploy Task 2 Expected: มากกว่า 0 หลังมีการอนุมัติจริงผ่านระบบครบอย่างน้อย 1 เรื่องนับจากตอน deploy Task 2
- [ ] **Step 3: ยืนยัน dashboard endpoint คืนค่าตรงกับ SQL** - [x] **Step 3: ยืนยัน dashboard endpoint คืนค่าตรงกับ SQL**
เทียบ `GET /api/income_budget_review/dashboard` (ด้วย token จาก Task 3 Step 6) กับผลจาก เทียบ `GET /api/income_budget_review/dashboard` (ด้วย token จาก Task 3 Step 6) กับผลจาก
`SELECT` ตรงในขั้นตอนที่ 1-2 ว่าจำนวนตรงกัน `SELECT` ตรงในขั้นตอนที่ 1-2 ว่าจำนวนตรงกัน
- [ ] **Step 4: สรุปผลให้ผู้ใช้** - [x] **Step 4: สรุปผลให้ผู้ใช้**
รายงานว่าทดสอบผ่านจริงกี่เคส (รอตรวจสอบ → ส่งแก้ไข → กลับไป income-report เห็น remark → อนุมัติใหม่ → รายงานว่าทดสอบผ่านจริงกี่เคส (รอตรวจสอบ → ส่งแก้ไข → กลับไป income-report เห็น remark → อนุมัติใหม่ →
กลับมา "รอตรวจสอบ" อีกครั้ง → กด "ตรวจสอบแล้ว" จบ) ก่อนถือว่าเสร็จงาน กลับมา "รอตรวจสอบ" อีกครั้ง → กด "ตรวจสอบแล้ว" จบ) ก่อนถือว่าเสร็จงาน