$npx -y skills add Impertio-Studio/Frappe_Claude_Skill_Package --skill frappe-impl-workflowUse when implementing document Workflows, approval chains, or state-based transitions in Frappe. Prevents stuck documents from missing transitions, broken approval chains, and permission errors on workflow actions. Covers Workflow DocType, Workflow State, Workflow Action, transit
| 1 | # Frappe Workflow Implementation |
| 2 | |
| 3 | Step-by-step guide for implementing document workflows in Frappe. Covers design, setup, testing, and common approval chain patterns. |
| 4 | |
| 5 | ## Quick Reference: Implementation Checklist |
| 6 | |
| 7 | ``` |
| 8 | 1. □ Design states and transitions on paper/diagram first |
| 9 | 2. □ Create Workflow State records (master list) |
| 10 | 3. □ Create Workflow Action Master records (Approve, Reject, etc.) |
| 11 | 4. □ Create the Workflow DocType record |
| 12 | 5. □ Add states with correct doc_status values |
| 13 | 6. □ Add transitions with roles, actions, and conditions |
| 14 | 7. □ Set allow_edit roles per state |
| 15 | 8. □ Configure email notifications (optional) |
| 16 | 9. □ Test every transition path with test users |
| 17 | 10. □ Verify self-approval blocking works as expected |
| 18 | ``` |
| 19 | |
| 20 | ## Step 1: Design Your Workflow |
| 21 | |
| 22 | Before touching the UI, map out your workflow on paper. |
| 23 | |
| 24 | ### Identify States |
| 25 | |
| 26 | **ALWAYS** start by listing every distinct document stage: |
| 27 | |
| 28 | ``` |
| 29 | Example — Purchase Order Approval: |
| 30 | Draft → Pending Review → Pending Approval → Approved → Submitted → Cancelled |
| 31 | ``` |
| 32 | |
| 33 | ### Map DocStatus to States |
| 34 | |
| 35 | For submittable DocTypes, ALWAYS assign `doc_status` correctly: |
| 36 | |
| 37 | | Stage | doc_status | Meaning | |
| 38 | |-------|:-:|---------| |
| 39 | | All "in-progress" states | 0 | Document is Draft, editable | |
| 40 | | Final approved/active state | 1 | Document is Submitted, locked | |
| 41 | | Cancelled state | 2 | Document is Cancelled | |
| 42 | |
| 43 | **NEVER** assign `doc_status = 1` to intermediate approval states. A submitted document cannot return to draft. Once submitted, the only forward path is another submitted state or cancellation. |
| 44 | |
| 45 | ### Map Transitions |
| 46 | |
| 47 | For each state, define: What actions are possible? Who can perform them? Any conditions? |
| 48 | |
| 49 | ``` |
| 50 | Draft →[Submit for Review / Creator]→ Pending Review |
| 51 | Pending Review →[Approve / Reviewer]→ Pending Approval |
| 52 | Pending Review →[Reject / Reviewer]→ Draft |
| 53 | Pending Approval →[Approve / Manager]→ Approved |
| 54 | Pending Approval →[Reject / Manager]→ Draft |
| 55 | Approved →[Submit / Manager]→ Submitted (doc_status=1) |
| 56 | Submitted →[Cancel / Manager]→ Cancelled (doc_status=2) |
| 57 | ``` |
| 58 | |
| 59 | ## Step 2: Create Prerequisite Records |
| 60 | |
| 61 | ### 2a. Create Workflow States |
| 62 | |
| 63 | Navigate to **Workflow State** list or create via API: |
| 64 | |
| 65 | ```python |
| 66 | # Create states with appropriate styles |
| 67 | states = [ |
| 68 | {"workflow_state_name": "Draft", "style": ""}, |
| 69 | {"workflow_state_name": "Pending Review", "style": "Primary"}, |
| 70 | {"workflow_state_name": "Pending Approval", "style": "Warning"}, |
| 71 | {"workflow_state_name": "Approved", "style": "Success"}, |
| 72 | {"workflow_state_name": "Submitted", "style": "Info"}, |
| 73 | {"workflow_state_name": "Rejected", "style": "Danger"}, |
| 74 | {"workflow_state_name": "Cancelled", "style": "Inverse"}, |
| 75 | ] |
| 76 | for s in states: |
| 77 | if not frappe.db.exists("Workflow State", s["workflow_state_name"]): |
| 78 | frappe.get_doc({"doctype": "Workflow State", **s}).insert() |
| 79 | ``` |
| 80 | |
| 81 | Available styles: `Primary`, `Success`, `Warning`, `Danger`, `Info`, `Inverse` (or empty for default). |
| 82 | |
| 83 | ### 2b. Create Workflow Action Masters |
| 84 | |
| 85 | ```python |
| 86 | actions = ["Submit for Review", "Approve", "Reject", "Send Back", "Cancel"] |
| 87 | for action in actions: |
| 88 | if not frappe.db.exists("Workflow Action Master", action): |
| 89 | frappe.get_doc({ |
| 90 | "doctype": "Workflow Action Master", |
| 91 | "workflow_action_name": action |
| 92 | }).insert() |
| 93 | ``` |
| 94 | |
| 95 | ## Step 3: Create the Workflow |
| 96 | |
| 97 | ### Via UI |
| 98 | |
| 99 | Navigate to **Setup > Workflow > New Workflow**: |
| 100 | |
| 101 | 1. Set **Workflow Name** (e.g., "Purchase Order Approval") |
| 102 | 2. Set **Document Type** (e.g., "Purchase Order") |
| 103 | 3. Check **Is Active** |
| 104 | 4. Add states in the **States** table |
| 105 | 5. Add transitions in the **Transitions** table |
| 106 | |
| 107 | ### Via Python |
| 108 | |
| 109 | ```python |
| 110 | workflow = frappe.get_doc({ |
| 111 | "doctype": "Workflow", |
| 112 | "workflow_name": "Purchase Order Approval", |
| 113 | "document_type": "Purchase Order", |
| 114 | "is_active": 1, |
| 115 | "send_email_alert": 1, |
| 116 | "states": [ |
| 117 | {"state": "Draft", "doc_status": "0", "allow_edit": "Purchase User"}, |
| 118 | {"state": "Pending Approval", "doc_status": "0", "allow_edit": "Purchase Manager"}, |
| 119 | {"state": "Approved", "doc_status": "1", "allow_edit": "Purchase Manager"}, |
| 120 | {"state": "Rejected", "doc_status": "0", "allow_edit |