: / ฐานความรู้ / ลำดับของ Frappe Workflow Transition สำคัญกว่าที่คิด

ลำดับของ Frappe Workflow Transition สำคัญกว่าที่คิด


Created:5/7/2026


TLDR

ลำดับของ workflow transition สำคัญมาก transition ที่มี idx สูงกว่า (อยู่ท้ายลิสต์) มีความสำคัญสูงกว่าและจะชนะเสมอเมื่อมีหลาย transition ที่ match กัน

Excalidraw diagram

Use Case

สำหรับ workflow ของ Purchase Order เรามี requirement สองข้อ:

  • ถ้า Purchase User submit PO สถานะควรเปลี่ยนเป็น Pending Approval
  • ถ้า Purchase Manager submit PO สถานะควรข้ามไปเป็น Submitted เลย

ตอนแรกที่เราเพิ่ม transition เราเรียงลำดับแบบนี้:

  1. Draft -> Submitted (Allowed: Purchase Manager)
  2. Draft -> Pending Approval (Allowed: Purchase User)

แล้วก็สังเกตเห็นปัญหา: เมื่อ user ที่มีทั้ง role Purchase User และ Purchase Manager submit PO document กลับเปลี่ยนสถานะไปเป็น Pending Approval แทนที่จะเป็น Submitted ซึ่งไม่ถูกต้อง - ใครก็ตามที่มี role Purchase Manager ควรข้ามขั้นตอน approval ไปได้เลย

เราเลยดูเพิ่มเติมว่าทำไมถึงเป็นแบบนั้น

สาเหตุของปัญหา

จริงๆ แล้วนี่ไม่ใช่ bug - แต่เป็นแค่วิธีที่ Frappe ทำงาน

โค้ดอยู่ใน frappe/model/workflow.py ในฟังก์ชัน apply_workflow หลังจาก collect transition ทั้งหมดที่ user มีสิทธิ์ใช้ได้แล้ว มันจะเลือก transition ที่ match กับ action ที่กดแบบนี้:

# find the transition
transition = None
for t in transitions:
    if t.action == action:
        transition = t        # ← last match overwrites

ใน loop นี้ไม่มี break ทุก transition ที่ match จะทับของเดิม ดังนั้น transition ที่อยู่ท้ายสุดในลิสต์จะชนะเสมอ

get_transitions สร้างลิสต์นั้นโดย iterate workflow.transitions ตาม idx:

for transition in workflow.transitions:
    if transition.state == current_state and transition.allowed in roles:
        if not is_transition_condition_satisfied(transition, doc):
            continue
        transitions.append(transition.as_dict())

ดังนั้น transition ที่อยู่ ท้ายกว่า ในลิสต์ (idx สูงกว่า) จะถูก apply - ไม่ว่า role hierarchy จะเป็นยังไงก็ตาม

วิธีแก้ไข

แก้ได้ง่ายมาก - แค่เรียงลำดับ transition ใหม่ให้ transition ที่มี priority สูงกว่าหรือ specific กว่าอยู่ ท้ายสุด ในกรณีของเรา แค่สลับลำดับ:

  1. Draft -> Pending Approval (Allowed: Purchase User)
  2. Draft -> Submitted (Allowed: Purchase Manager)

ตอนนี้เมื่อ Purchase Manager submit PO transition ทั้งสองตัว match - แต่เนื่องจาก "Draft -> Submitted" อยู่ท้ายสุดในลิสต์ มันจึงชนะ

กฎง่ายๆ คือ: วาง transition ที่มีสิทธิ์สูงกว่าหรือ specific กว่าไว้ด้านล่างเสมอ


อยากได้คนช่วยคิดและลงมือทำ?เราพร้อมช่วยคุณวางแผนและลงมือทำให้ง่าย และรวดเร็ว
จ้างเรา