Files
alla-tms/docs/reports/training-record-submit-workflow-review.md
2026-07-16 09:53:14 +07:00

6.9 KiB

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 ส่ง record ไปสถานะ pending ก่อนเรียก route upload ในบางเส้นทาง ขณะที่ business rule ของ route upload ใน 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