# Training Record Submit Workflow Review ## Executive Summary ปัญหาหลักเกิดจาก submit flow ฝั่งฟอร์มเรียกเปลี่ยนสถานะรายการเป็น `pending` ก่อนอัปโหลด certificate เสร็จในบางเส้นทาง โดย backend อนุญาตให้อัปโหลดได้เฉพาะตอนสถานะ `draft` หรือ `needs_revision` เท่านั้น จึงเกิด error ระหว่าง submit ## Current Workflow ก่อนแก้ไข โฟลว์หลักใน `training-record-form.tsx` เป็นดังนี้ - Edit Draft Submit: `PATCH training record (submit)` -> `POST certificates` - Create Submit: `POST training record (submit)` -> `POST certificates` ผลคือเมื่อ record ถูกเปลี่ยนเป็น `pending` แล้ว route upload จะปฏิเสธทันที ## Expected Workflow โฟลว์ที่ต้องการและที่แก้แล้วคือ - Submit: `validate` -> `save editable data as draft` -> `upload certificates` -> `update status to pending` -> `redirect` - Save Draft: `save draft` -> `upload certificates` -> `redirect` ## Execution Timeline ### Edit + Submit 1. validate form 2. `PATCH /api/training-records/[id]` ด้วย `submissionMode=draft` 3. `POST /api/training-records/[id]/certificates` 4. `PATCH /api/training-records/[id]` ด้วย `submissionMode=submit` 5. invalidate query จาก mutations 6. `router.push('/dashboard/training-records')` ### Create + Submit 1. validate form 2. `POST /api/training-records` ด้วย `submissionMode=draft` 3. `POST /api/training-records/[id]/certificates` 4. `PATCH /api/training-records/[id]` ด้วย `submissionMode=submit` 5. invalidate query จาก mutations 6. redirect ## API Call Sequence - `POST /api/training-records` - `PATCH /api/training-records/[id]` - `POST /api/training-records/[id]/certificates` - `DELETE /api/training-records/[id]/certificates/[certificateId]` ลำดับใหม่ยืนยันว่า upload เกิดก่อน status transition ไป `pending` ## React Query Flow - ใช้ `createTrainingRecordMutation` - ใช้ `updateTrainingRecordMutation` - ใช้ `uploadCertificatesMutation` - แต่ละ mutation invalidate query ตาม key เดิมของ feature - ไม่มี `Promise.all` หรือ upload background ## Async Analysis - flow ใช้ `await` แบบลำดับตรง - ไม่มี parallel mutation ที่เสี่ยงชนกัน - submit จะไม่ไปขั้นเปลี่ยนสถานะถ้า upload ล้มเหลว ## Race Condition Analysis ก่อนแก้มี race เชิงลำดับธุรกิจ ไม่ใช่ race จาก concurrency จริง: - route update เปลี่ยน status เป็น `pending` - route upload ถูกเรียกทีหลัง - backend reject เพราะ record ไม่อยู่ในสถานะ editable แล้ว หลังแก้ upload เกิดก่อน status update จึงปิดช่องนี้ ## Upload Component Review - ฟอร์มหลักใช้ `FileUploader` เก็บไฟล์ไว้ใน `pendingFiles` - upload จริงเกิดใน `onSubmit` - `TrainingRecordCertificateManager` ใช้สำหรับจัดการไฟล์ของรายการที่บันทึกแล้ว - ไม่พบ auto-upload บน mount ## Root Cause root cause คือ submit flow ใน [training-record-form.tsx](/D:/WY-2569/HRD/training-system-minimal-refactor/src/features/training-records/components/training-record-form.tsx) ส่ง record ไปสถานะ `pending` ก่อนเรียก route upload ในบางเส้นทาง ขณะที่ business rule ของ route upload ใน [route.ts](/D:/WY-2569/HRD/training-system-minimal-refactor/src/app/api/training-records/[id]/certificates/route.ts) อนุญาตเฉพาะ `draft` หรือ `needs_revision` หลักฐานจาก source: - ฟอร์มเดิมเรียก create/update ด้วย `submissionMode=submit` ก่อน upload - route upload ตรวจ `canEmployeeManageEditableRecord(...)` - helper ฝั่ง server อนุญาตเฉพาะสถานะ editable ## Files Modified - `src/features/training-records/components/training-record-form.tsx` ปรับลำดับ submit ให้ save-as-draft ก่อน upload แล้วค่อย final submit - `src/features/training-records/server/training-record-data.ts` ปรับ shared editable guard ให้เช็กสิทธิ์จาก employee mapping ได้ครบขึ้น - `src/app/api/training-records/[id]/route.ts` ใช้ shared editable guard แบบใหม่และอัปเดตข้อความ error - `src/app/api/training-records/[id]/certificates/route.ts` ใช้ shared editable guard แบบใหม่และอัปเดตข้อความ error - `src/app/api/training-records/[id]/certificates/[certificateId]/route.ts` ใช้ shared editable guard แบบใหม่และอัปเดตข้อความ error - `src/features/training-records/components/training-record-certificate-manager.tsx` ปรับ helper text ให้ตรงกับสถานะ editable จริง ## Risk Assessment - Employee: ผลดีคือ submit draft/revision พร้อม upload ทำงานสอดคล้องกับ backend มากขึ้น - HRD: pending queue จะเห็นเฉพาะรายการที่ผ่าน upload flow แล้ว - Admin: ไม่มีการเปลี่ยน schema หรือ permission model ## Regression Test Result ตรวจเช็กเชิงโค้ดและ lint แล้ว - editable guard ถูกใช้กับ route แก้ไข/อัปโหลด/ลบ - submit flow ในฟอร์มถูกย้ายเป็น upload ก่อน status update - `npx oxlint` ผ่านสำหรับไฟล์ที่แก้ ยังไม่ได้รัน E2E/manual test ครบทุก case ในเอกสาร ## Remaining Issues - ปุ่ม submit เดิมในฟอร์มยังถูกซ่อนไว้ ควรลบออกในรอบ cleanup - success message บางจุดยังไม่แยก wording ระหว่าง draft กับ submit แบบครบทุกสถานะ - ยังไม่ได้ทำ manual regression ครบทั้ง 10 case ตาม checklist