Workflow¶
หน้านี้อธิบาย state machine ของ Annual Inspection อย่างละเอียด รวมถึง การจัดการ edge case ที่อาจเจอในการใช้งานจริง
State Diagram¶
stateDiagram-v2
[*] --> Draft
state Draft {
[*] --> EmptyDraft
EmptyDraft --> HasLines: Add Equipment (wizard)
HasLines --> EmptyDraft: ลบ line ทุกบรรทัด
}
Draft --> InProgress: Start Inspection
note left of InProgress
ต้องมี ≥1 line ก่อน
end note
state InProgress {
[*] --> SettingConditions
SettingConditions --> AllMarked: บันทึก condition ครบ
AllMarked --> SettingConditions: แก้ condition ใหม่
}
InProgress --> Submitted: Submit
note right of Submitted
ต้องไม่มี unmarked line
+ ทำ condition propagation
end note
Submitted --> Draft: Reset to Draft
note left of Submitted
Manager group เท่านั้น
end note
Submitted --> [*] Transition: Draft → In Progress¶
Trigger¶
คลิกปุ่ม Start Inspection ที่ header
Precondition¶
- มี อย่างน้อย 1 line ใน
line_ids - ผู้ใช้มีสิทธิ์เขียน (Asset Officer หรือ ผู้ใช้ในหน่วยงานเดียวกัน)
Effect¶
| ฟิลด์ | เปลี่ยนเป็น |
|---|---|
state | in_progress |
start_date | fields.Datetime.now() |
ผลข้างเคียง¶
- รายการครุภัณฑ์ในตาราง ล็อก —
equipment_idกลายเป็น readonly - ปุ่ม Add Equipment และ Start Inspection จะ hidden
- ปุ่ม Submit ปรากฏขึ้น
Error case¶
| สาเหตุ | Error | วิธีแก้ |
|---|---|---|
| ไม่มี line | "Cannot start an inspection with no equipment lines." | กลับไป Add Equipment ก่อน |
Transition: In Progress → Submitted¶
Trigger¶
คลิกปุ่ม Submit ที่ header
Precondition¶
- ทุก line ต้องมี
conditionที่ไม่ใช่False - ถ้า
conditionเป็นbrokenหรือdeteriorated→ ต้องมีdamage_description
Effect¶
| ฟิลด์ | เปลี่ยนเป็น |
|---|---|
state | submitted |
submitted_date | fields.Datetime.now() |
ผลข้างเคียง (สำคัญ!)¶
ระบบจะทำ condition propagation อัตโนมัติ:
# Pseudo-code
for condition, lines in inspection.line_ids.grouped("condition").items():
lines.equipment_id.sudo().write({"current_condition": condition})
→ maintenance.equipment.current_condition ของครุภัณฑ์ทุกชิ้นใน inspection จะถูกอัพเดทให้ตรงกับสถานะที่เพิ่งตรวจพบ
ทำไมต้อง sudo()
Asset Officer อาจไม่มีสิทธิ์เขียน maintenance.equipment (ทะเบียนหลัก) sudo() bypass ACL ในขั้นตอนนี้ — โดยมี state guard ป้องกัน: _propagate_condition_to_master จะทำงานเฉพาะเมื่อ state == 'submitted'
Error case¶
| สาเหตุ | Error | วิธีแก้ |
|---|---|---|
| มี line ยังไม่ตรวจ | "All equipment must have a condition set before submitting. Missing: …" | กลับไประบุ condition |
broken/deteriorated ไม่มีคำอธิบาย | "Please describe how X is damaged" | กรอก damage_description |
Transition: Submitted → Draft (Reset)¶
Trigger¶
คลิกปุ่ม Reset to Draft ที่ header
Precondition¶
- ผู้ใช้ต้องอยู่ในกลุ่ม
maintenance.group_equipment_manager - (กลุ่ม Asset Officer ไม่มีสิทธิ์ — ต้องส่งคำขอ Manager)
Effect¶
| ฟิลด์ | เปลี่ยนเป็น |
|---|---|
state | draft |
start_date / submitted_date | คงเดิม (ยังเก็บไว้เพื่อ audit) |
ผลข้างเคียง¶
- ครุภัณฑ์ใน
maintenance.equipment.current_conditionไม่ rollback — สถานะที่ propagate ไปแล้วจะยังอยู่ - ถ้า resubmit ครั้งใหม่ →
submitted_dateจะถูกเขียนทับ - รายการครุภัณฑ์กลับมาแก้/เพิ่ม/ลบได้เหมือนเดิม
Audit trail¶
ทุก transition จะถูกบันทึกใน mail.thread chatter ของ inspection:
- เปลี่ยน state ใคร เมื่อไหร่
- ค่า
start_date,submitted_dateที่เปลี่ยน
Sub-workflow: เพิ่มครุภัณฑ์ผ่าน Wizard¶
Domain ของ wizard¶
[
("active", "=", True),
("id", "not in", already_added_ids),
("department_id", "in", [department_id, False]),
]
→ wizard แสดง:
- ครุภัณฑ์ที่ active เท่านั้น
- ที่ ยังไม่ถูกเพิ่ม ใน inspection นี้
- หน่วยงานตรงกับ inspection หรือไม่มีหน่วยงาน (เพื่อให้ครุภัณฑ์กลางถูกตรวจได้)
Snapshot ที่ถูก copy¶
ตอน action_add_selected ของ wizard จะ copy ฟิลด์เหล่านี้จาก equipment master:
| Equipment field | Inspection line field |
|---|---|
name | equipment_name |
ref | ref_no |
category_id.complete_name | category_name |
brand_id.name | brand_name |
equipment_model_id.name | model_name |
effective_date | effective_date |
cost | cost |
employee_id.name | employee_name |
roots_criticality_color | criticality_color |
current_condition | condition (pre-fill) |
ทำไมต้อง snapshot
หลังจาก inspection ถูก submit ไปแล้ว ถ้ามีการแก้ทะเบียนหลัก (เช่น เปลี่ยนผู้ใช้งาน) รายงานที่พิมพ์ไปแล้วจะยังคงตรงกับข้อมูล ณ เวลาตรวจ
Edge cases และวิธีแก้¶
Case 1: ครุภัณฑ์ใหม่เพิ่งซื้อหลังจากเริ่มตรวจ¶
Scenario: เริ่มตรวจวันที่ 1 ต.ค. → ซื้อครุภัณฑ์ใหม่ 5 ต.ค. → ตอนนี้ state = In Progress
Resolution: ครุภัณฑ์ใหม่จะ ไม่ถูกเพิ่ม อัตโนมัติ เพราะ inspection ล็อกที่ Draft แล้ว ทางเลือก:
- Manager Reset to Draft → เพิ่มครุภัณฑ์ใหม่ → Submit ใหม่
- ปล่อยไว้ — ครุภัณฑ์ใหม่จะถูกตรวจในปีถัดไป
Case 2: ครุภัณฑ์โอนข้ามหน่วยงานระหว่างที่ตรวจ¶
Scenario: Inspection ของหน่วยงาน A กำลังตรวจ → ครุภัณฑ์ชิ้นหนึ่งถูกโอนไป หน่วยงาน B → ปัจจุบัน department_id ของ equipment = B
Resolution: - ใน inspection ของ A: snapshot ที่บันทึกไว้ตอน Add ยังเป็น A → ยังตรวจได้ปกติ - ใน inspection ของ B (ถ้ามี): จะเห็นครุภัณฑ์ชิ้นนี้ใน wizard ของ B ได้ด้วย - ทั้ง 2 inspection สามารถมี line ของครุภัณฑ์เดียวกัน เพราะ _sql_constraints จำกัดที่ระดับ (inspection_id, equipment_id) ไม่ใช่ระดับ equipment เดียวกันข้าม inspection
Case 3: ลืม Submit ก่อนสิ้นปีงบประมาณ¶
ระบบ ไม่บังคับ ส่งภายในกำหนด — เป็นความรับผิดชอบของหน่วยงาน แต่ field submitted_date จะแสดงวันที่ส่งจริง — ถ้าส่งช้าจะปรากฏใน audit log
Case 4: เปลี่ยนหน่วยงานหลังเพิ่ม Line แล้ว¶
department_id ที่ header จะกลายเป็น readonly เมื่อ state = draft และมี line แล้ว (เพราะ snapshot ครุภัณฑ์ผูกกับหน่วยงานเดิม)
ถ้าเลือกผิดตอนสร้าง:
- ลบ inspection (Asset Officer มีสิทธิ์ลบใน Draft)
- สร้างใหม่ ด้วยหน่วยงานที่ถูกต้อง
หน้าที่เกี่ยวข้อง¶
- เริ่มใช้งาน — ขั้นตอน end-to-end
- Configuration — ตั้งค่าหน่วยงาน, sequence, สิทธิ์
- Reporting — รายงานและ analytics