# คำขอระหว่างปี — ขั้นตอนบันทึกฉบับร่าง / ส่งกองนโยบายและแผน ## บริบท เมนู "คำขอระหว่างปี" (`/budget-web/app/request-budget-between-year`, routing `type: 21`) ปัจจุบันเมื่อกด "บันทึก" (ครั้งแรก) ระบบจะสร้างระเบียน `request_budget` (`is_between_year=true`) ด้วย `status_id = 0` และ `is_examine = true` ทันที แล้วพากลับไปหน้ารายการ — ระเบียนนี้จะไปปรากฏในเมนู "ตรวจสอบคำเสนอขอโครงการ" (`check-project-proposal`, `type: 2`) แท็บ "จัดการคำเสนอขอ" โดยอัตโนมัติ เพราะแท็บนั้น query `request_budget_and_strategic?status_id=1`... แต่ทดสอบจริงพบว่าระเบียนที่ `status_id=0` จากฟอร์มก็ไปโผล่ที่นั่นแล้ว (มีสถานะ "รอตรวจสอบ") กล่าวคือ ปัจจุบัน**ไม่มีขั้นตอนกลาง** — บันทึกปุ๊บ = ส่งงานแผนปั๊บ ผู้ใช้ไม่มีโอกาสร่างทิ้งไว้ก่อน ผู้ใช้ (เจ้าหน้าที่หน่วยงาน/คณะ ผู้กรอกคำขอ) ต้องการขั้นตอนกลาง: ร่างไว้ก่อน แล้วค่อยเลือกส่งเป็นชุดเมื่อพร้อม โค้ดที่มีอยู่แล้วบางส่วนสะท้อนว่าเคยมีความตั้งใจทำ flow นี้มาก่อนแต่ทำไม่เสร็จ: - `list-between-year.component.html` มีคอลัมน์สถานะที่ comment ไว้ ตรงกับความหมาย `status_id==0` → "ร่าง", `status_id==1` (และยังไม่ `is_ok`/`is_modify`) → รอดำเนินการ - `request-budget-statistics.container.ts` → `getAll()` query เริ่มต้นของ `dataSourceBetweenYear$` มี filter `&status_id=1` ค้างอยู่ (ไม่ตรงกับ `onsearch()` ที่ไม่กรอง) — เป็น bug ที่ต้องแก้ไปพร้อมกัน มิฉะนั้นร่าง (`status_id=0`) จะไม่โผล่ในรายการเริ่มต้นเลย `check-project-proposal` แท็บ "จัดการคำเสนอขอ" (query `status_id=1`) เป็นเมนูที่งานแผนใช้ตรวจสอบอยู่แล้ว **ไม่ต้องแก้ไขเมนูนั้น** — งานนี้ทำเฉพาะฝั่ง "คำขอระหว่างปี" ให้ควบคุมได้ว่าจะยังไม่ส่ง (ร่าง) หรือส่งแล้ว (`status_id: 1`) เท่านั้น การไปโผล่ที่ `check-project-proposal` เป็นผลพลอยได้อัตโนมัติจากการเปลี่ยน `status_id` ซึ่งมีอยู่แล้ว ## ขอบเขต เฉพาะเมนู "คำขอระหว่างปี" (list + form ของ between-year เท่านั้น) ไม่แตะเมนู `check-project-proposal` หรือเมนูอื่นที่ใช้ container เดียวกัน (`request-budget-statistics.container.ts`) เกินความจำเป็น (จะเพิ่ม handler ใหม่ 1 ตัวในไฟล์นี้เท่านั้น) ## การไหลของสถานะ | status_id | is_ok / is_modify | ป้ายในรายการ | แก้ไข/ลบได้ไหม | |---|---|---|---| | 0 | - | ร่าง | ได้ปกติ | | 1 | ทั้งคู่ false/null | ส่งงานแผน | ดูได้อย่างเดียว (form disable, ปุ่มลบปิด) | | 1 | is_modify = true | ส่งแก้ไข | (ปรับปรุงจากงานแผนผ่านเมนูอื่นอยู่แล้ว นอกขอบเขตนี้) | | 1 | is_ok = true | ตรวจสอบแล้ว | (นอกขอบเขตนี้) | หมายเหตุ: แถวสถานะ `is_modify`/`is_ok` เกิดจากการทำงานของงานแผนในเมนู `check-project-proposal` ซึ่งมีอยู่แล้วในโค้ดปัจจุบัน งานนี้แค่แสดงป้ายให้ถูกต้องตามข้อมูลจริงในรายการเดียวกัน ไม่ต้องสร้าง logic ใหม่สำหรับสองแถวนี้ ## การเปลี่ยนแปลงที่ต้องทำ ### 1. Bug fix: `request-budget-statistics.container.ts` → `getAll()` ลบ `&status_id=1` ออกจาก query เริ่มต้นของ `dataSourceBetweenYear$` (บรรทัด ~199) ให้เหลือ `?is_between_year=true` เท่านั้น เพื่อให้ทั้งร่างและที่ส่งแล้วแสดงในรายการเดียวกัน (ตรงกับพฤติกรรมของ `onsearch()` ที่มีอยู่แล้ว) ### 2. ฟอร์ม `request-budget-between-year-form.component.ts` - ปุ่ม "บันทึก" (label ในเทมเพลต) เปลี่ยนเป็น **"บันทึกฉบับร่าง"** - ตอน `save()` กรณี `state === 'add'`: คง `status_id = 0` ไว้ (ร่าง) แต่**เอา `is_examine = true` ออก** จาก path นี้ (ย้ายไปตั้งตอนส่งแทน เพราะ "กำลังตรวจสอบ" ควรเป็นจริงก็ต่อเมื่อส่งไปงานแผนแล้วเท่านั้น) - ตอนโหลดข้อมูลกรณี `state === 'edit'` (ใน `ngOnInit`, หลัง `this.form.patchValue(x)`): ถ้า `x.status_id !== 0` (ถูกส่งไปแล้ว) → เรียก `this.form.disable()` และตั้ง flag `isLocked = true` (component property ใหม่) - เทมเพลตฟอร์ม: ถ้า `isLocked` ให้ซ่อนปุ่ม "บันทึกฉบับร่าง" (เหลือแต่ "ยกเลิก"/กลับ) ฟิลด์ทั้งหมด disable อยู่แล้วจากการ `form.disable()` ### 3. List `list-between-year.component.ts` / `.html` - เพิ่ม `selection = new SelectionModel(true, [])` (import จาก `@angular/cdk/collections`) ตามแพทเทิร์นเดียวกับ `list6`/`list24` - เพิ่มคอลัมน์ checkbox หน้าสุด: เช็คได้เฉพาะแถว `status_id === 0` (ร่าง) แถวอื่น disable ล่วงหน้า (ไม่ให้เลือกส่งซ้ำ) - Uncomment คอลัมน์สถานะเดิม เพิ่มเข้า columns array ของ header/row/footer และแก้ข้อความ: - `status_id == 0` → badge "ร่าง" - `is_modify == true` → badge "ส่งแก้ไข" - `is_ok == true` → badge "ตรวจสอบแล้ว" - `status_id == 1` (ไม่เข้าเงื่อนไขบนสองข้อ) → badge **"ส่งงานแผน"** (เดิม comment ไว้ว่า "รอตรวจสอบ" เปลี่ยนข้อความ) - ไอคอน "ลบ" (`delete`): disable เมื่อ `status_id !== 0` - ไอคอน "แก้ไข" (`edit`): ไม่ disable — กดได้เสมอ (เข้าไปดู แต่ฟอร์มจะ read-only เองถ้าไม่ใช่ร่าง ตามข้อ 2) - เพิ่มปุ่ม toolbar ใหม่ **"ส่งกองนโยบายและแผน"** ข้าง "เพิ่มคำขอระหว่างปี": `disabled` เมื่อ `selection.selected.length === 0`, คลิกแล้ว `emit` ผ่าน `@Output() onsend = new EventEmitter()` ส่ง `this.selection.selected` (array ของแถวที่เลือก) ### 4. เดินสาย output ผ่านชั้น presenter กลาง - `request-budget-statistics-list.component.html` ส่วน `*ngIf="typeUrl == 21"`: เพิ่ม `(onsend)="onsend.emit($event)"` (หรือชื่อ output ที่สอดคล้อง) ให้ bubble ต่อไปยัง container - `request-budget-statistics.container.html`: เพิ่ม `(onsend)="sendBetweenYearToPlan($event)"` บน `` ### 5. Handler ใหม่ใน `request-budget-statistics.container.ts` เมธอดใหม่ `sendBetweenYearToPlan(selected: any[])`: - ถ้า `selected.length === 0` return - confirm ด้วย `this.swSV.confirmSave()` (แพทเทิร์นเดียวกับ handler อื่นในไฟล์นี้) - เมื่อ confirm: map `selected` เป็น payload ที่ตั้ง `status_id: 1, is_examine: true` ทับค่าเดิมของแต่ละแถว แล้วเรียก `this.requestBudgetSV.updateMany(payload)` - สำเร็จ: `this.swSV.updateSuccess()` แล้ว `this.getAll()` (หรือเทียบเท่า) เพื่อ refresh `dataSourceBetweenYear$`, `this.cdRef.detectChanges()` - ผิดพลาด: `catchError` → `this.swSV.errText(err?.error?.description || 'ส่งไม่สำเร็จ')` ## Error handling - กดส่งโดยไม่เลือกอะไร: ปุ่มถูก disable ไว้แล้ว ไม่ต้องมี error state เพิ่ม - API update ล้มเหลว: แสดง error ผ่าน `swSV.errText` ตามแพทเทิร์นเดิมของไฟล์ ไม่ rollback selection (ผู้ใช้กดส่งซ้ำได้) - แถวที่ถูกล็อกแล้วไม่มีทางถูกส่งซ้ำ เพราะ checkbox ถูก disable ไว้ตั้งแต่ต้น (client-side guard เท่านั้น ไม่ได้เพิ่ม guard ฝั่ง backend เพราะนอกขอบเขตงานนี้) ## Testing - Manual/browser verification (ตาม superpowers:verify skill ของโปรเจกต์): เพิ่มคำขอระหว่างปีใหม่ → ยืนยันบันทึกเป็น "ร่าง", แก้ไข/ลบได้ - ติ๊ก checkbox 1-2 แถวร่าง กด "ส่งกองนโยบายและแผน" → ยืนยันเปลี่ยนเป็น "ส่งงานแผน", แก้ไข/ลบไม่ได้ (เข้าไปดูฟอร์ม read-only ได้) - ยืนยันรายการที่ส่งแล้วไปปรากฏในเมนู "ตรวจสอบคำเสนอขอโครงการ" แท็บ "จัดการคำเสนอขอ" เหมือนเดิม (ไม่ต้องแก้โค้ดฝั่งนั้น) - ยืนยัน checkbox ของแถวที่ส่งแล้วไม่สามารถติ๊กเลือกซ้ำได้