Skip to main content
ClaudeWave
Instalar en Claude Code
Copiar
git clone --depth 1 https://github.com/Impertio-Studio/Frappe_Claude_Skill_Package /tmp/frappe-impl-workflow && cp -r /tmp/frappe-impl-workflow/skills/source/impl/frappe-impl-workflow ~/.claude/skills/frappe-impl-workflow
Después abre una sesión nueva de Claude Code; el skill carga automáticamente.

SKILL.md

# Frappe Workflow Implementation

Step-by-step guide for implementing document workflows in Frappe. Covers design, setup, testing, and common approval chain patterns.

## Quick Reference: Implementation Checklist

```
1. □ Design states and transitions on paper/diagram first
2. □ Create Workflow State records (master list)
3. □ Create Workflow Action Master records (Approve, Reject, etc.)
4. □ Create the Workflow DocType record
5. □ Add states with correct doc_status values
6. □ Add transitions with roles, actions, and conditions
7. □ Set allow_edit roles per state
8. □ Configure email notifications (optional)
9. □ Test every transition path with test users
10. □ Verify self-approval blocking works as expected
```

## Step 1: Design Your Workflow

Before touching the UI, map out your workflow on paper.

### Identify States

**ALWAYS** start by listing every distinct document stage:

```
Example — Purchase Order Approval:
  Draft → Pending Review → Pending Approval → Approved → Submitted → Cancelled
```

### Map DocStatus to States

For submittable DocTypes, ALWAYS assign `doc_status` correctly:

| Stage | doc_status | Meaning |
|-------|:-:|---------|
| All "in-progress" states | 0 | Document is Draft, editable |
| Final approved/active state | 1 | Document is Submitted, locked |
| Cancelled state | 2 | Document is Cancelled |

**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.

### Map Transitions

For each state, define: What actions are possible? Who can perform them? Any conditions?

```
Draft         →[Submit for Review / Creator]→     Pending Review
Pending Review →[Approve / Reviewer]→              Pending Approval
Pending Review →[Reject / Reviewer]→               Draft
Pending Approval →[Approve / Manager]→             Approved
Pending Approval →[Reject / Manager]→              Draft
Approved      →[Submit / Manager]→                 Submitted (doc_status=1)
Submitted     →[Cancel / Manager]→                 Cancelled (doc_status=2)
```

## Step 2: Create Prerequisite Records

### 2a. Create Workflow States

Navigate to **Workflow State** list or create via API:

```python
# Create states with appropriate styles
states = [
    {"workflow_state_name": "Draft", "style": ""},
    {"workflow_state_name": "Pending Review", "style": "Primary"},
    {"workflow_state_name": "Pending Approval", "style": "Warning"},
    {"workflow_state_name": "Approved", "style": "Success"},
    {"workflow_state_name": "Submitted", "style": "Info"},
    {"workflow_state_name": "Rejected", "style": "Danger"},
    {"workflow_state_name": "Cancelled", "style": "Inverse"},
]
for s in states:
    if not frappe.db.exists("Workflow State", s["workflow_state_name"]):
        frappe.get_doc({"doctype": "Workflow State", **s}).insert()
```

Available styles: `Primary`, `Success`, `Warning`, `Danger`, `Info`, `Inverse` (or empty for default).

### 2b. Create Workflow Action Masters

```python
actions = ["Submit for Review", "Approve", "Reject", "Send Back", "Cancel"]
for action in actions:
    if not frappe.db.exists("Workflow Action Master", action):
        frappe.get_doc({
            "doctype": "Workflow Action Master",
            "workflow_action_name": action
        }).insert()
```

## Step 3: Create the Workflow

### Via UI

Navigate to **Setup > Workflow > New Workflow**:

1. Set **Workflow Name** (e.g., "Purchase Order Approval")
2. Set **Document Type** (e.g., "Purchase Order")
3. Check **Is Active**
4. Add states in the **States** table
5. Add transitions in the **Transitions** table

### Via Python

```python
workflow = frappe.get_doc({
    "doctype": "Workflow",
    "workflow_name": "Purchase Order Approval",
    "document_type": "Purchase Order",
    "is_active": 1,
    "send_email_alert": 1,
    "states": [
        {"state": "Draft", "doc_status": "0", "allow_edit": "Purchase User"},
        {"state": "Pending Approval", "doc_status": "0", "allow_edit": "Purchase Manager"},
        {"state": "Approved", "doc_status": "1", "allow_edit": "Purchase Manager"},
        {"state": "Rejected", "doc_status": "0", "allow_edit": "Purchase User"},
        {"state": "Cancelled", "doc_status": "2"},
    ],
    "transitions": [
        {
            "state": "Draft",
            "action": "Submit for Review",
            "next_state": "Pending Approval",
            "allowed": "Purchase User",
            "allow_self_approval": 1,
        },
        {
            "state": "Pending Approval",
            "action": "Approve",
            "next_state": "Approved",
            "allowed": "Purchase Manager",
            "allow_self_approval": 0,
        },
        {
            "state": "Pending Approval",
            "action": "Reject",
            "next_state": "Rejected",
            "allowed": "Purchase Manager",
        },
        {
            "state": "Rejected",
            "action": "Submit for Review",
            "next_state": "Pending Approval",
            "allowed": "Purchase User",
        },
        {
            "state": "Approved",
            "action": "Cancel",
            "next_state": "Cancelled",
            "allowed": "Purchase Manager",
        },
    ],
})
workflow.insert()
```

## Step 4: Configure Advanced Features

### Conditional Transitions

Add Python conditions to show transitions only when criteria are met:

```python
# Only allow approval for orders above 50000 by Senior Manager
{
    "state": "Pending Approval",
    "action": "Approve",
    "next_state": "Approved",
    "allowed": "Senior Manager",
    "condition": "doc.grand_total > 50000",
}

# Standard approval for orders up to 50000
{
    "state": "Pending Approval",
    "action": "Approve",
    "next_state": "Approved",
    "allowed": "Purchase Manager",
    "condition": "doc.grand_total <= 50000",
}
```

**ALWAYS** use `doc.fieldname` syntax in conditions (the document is exposed as a