Skip to main content

Overview

Assignment Rules automate the process of assigning tickets to agents based on conditions like ticket type, priority, team, and other criteria. They enable round-robin assignment, load balancing, and custom assignment logic.

Assignment Rule DocType

Assignment Rules are configured through the standard Frappe Assignment Rule DocType. Key configuration includes:
name
string
Unique identifier for the rule
description
string
Human-readable description of the rule
disabled
boolean
default:"false"
Whether the rule is active
priority
integer
Rule priority (higher priority rules are evaluated first)
document_type
string
Target DocType (typically “HD Ticket”)
assign_condition
text
Python expression to determine when rule applies
rule
Select
Assignment strategy: Round Robin, Load Balancing, or Based on Field

Get Assignment Rules List

Retrieve all assignment rules with user information.
This endpoint is defined in helpdesk/api/assignment_rule.py:4
@frappe.whitelist()
def get_assignment_rules_list():
    """Get list of assignment rules with user existence check
    
    Returns:
        List of assignment rule objects with users_exists flag
    """

Permissions

Requires read permission on Assignment Rule DocType. Throws PermissionError if user lacks permission.

Response

Returns an array of assignment rule objects:
name
string
Rule identifier
description
string
Rule description
disabled
boolean
Whether the rule is disabled
priority
integer
Rule priority
users_exists
boolean
Whether this rule has users assigned to it

Behavior

  • Orders rules by modified desc (most recently modified first)
  • Checks the Assignment Rule User child table to determine if users are assigned
  • Sets users_exists to true if the rule has at least one user configured

Example Request

import frappe

rules = frappe.call(
    "helpdesk.api.assignment_rule.get_assignment_rules_list"
)

for rule in rules:
    status = "✓ Has users" if rule['users_exists'] else "✗ No users"
    active = "Active" if not rule['disabled'] else "Disabled"
    print(f"{rule['name']}: {status} ({active})")

Example Response

[
  {
    "name": "Technical Support Round Robin",
    "description": "Assign technical tickets in round-robin fashion",
    "disabled": false,
    "priority": 10,
    "users_exists": true
  },
  {
    "name": "High Priority Escalation",
    "description": "Assign high priority tickets to senior agents",
    "disabled": false,
    "priority": 20,
    "users_exists": true
  },
  {
    "name": "New Assignment Rule",
    "description": "Draft rule not yet configured",
    "disabled": true,
    "priority": 1,
    "users_exists": false
  }
]

Get Assignment Rule Details

Retrieve complete configuration for a specific rule:
import frappe

rule = frappe.get_doc("Assignment Rule", "Technical Support Round Robin")

print(f"Description: {rule.description}")
print(f"Rule Type: {rule.rule}")
print(f"Condition: {rule.assign_condition}")

# List assigned users
for user in rule.users:
    print(f"Agent: {user.user}")

Create Assignment Rule

import frappe

# Create a round-robin assignment rule
rule = frappe.get_doc({
    "doctype": "Assignment Rule",
    "name": "Support Team Round Robin",
    "description": "Distribute tickets evenly among support team",
    "document_type": "HD Ticket",
    "disabled": 0,
    "priority": 5,
    "rule": "Round Robin",
    "assign_condition": "doc.ticket_type == 'General Support'"
})

# Add users to the round-robin
rule.append("users", {"user": "[email protected]"})
rule.append("users", {"user": "[email protected]"})
rule.append("users", {"user": "[email protected]"})

rule.insert()
print(f"Created rule: {rule.name}")

Assignment Rule Types

Round Robin

Distributes tickets evenly among assigned users in rotation:
rule = frappe.get_doc({
    "doctype": "Assignment Rule",
    "name": "Evening Shift Round Robin",
    "rule": "Round Robin",
    "assign_condition": "frappe.utils.now_datetime().hour >= 17"
})

Load Balancing

Assigns to the user with the fewest open assignments:
rule = frappe.get_doc({
    "doctype": "Assignment Rule",
    "name": "High Priority Load Balance",
    "rule": "Load Balancing",
    "assign_condition": "doc.priority == 'High'"
})

Based on Field

Assigns based on a field value in the document:
rule = frappe.get_doc({
    "doctype": "Assignment Rule",
    "name": "Team Based Assignment",
    "rule": "Based on Field",
    "field": "agent_group",  # Assigns based on ticket's agent_group
    "assign_condition": "doc.ticket_type == 'Technical'"
})

Assignment Conditions

The assign_condition field accepts Python expressions evaluated against the document:

Simple Conditions

# Assign only high priority
"doc.priority == 'High'"

# Assign specific ticket type
"doc.ticket_type == 'Technical Support'"

# Assign from specific customer
"doc.customer == 'Acme Corp'"

Complex Conditions

# Multiple criteria
"doc.priority == 'High' and doc.ticket_type == 'Bug Report'"

# Time-based
"frappe.utils.now_datetime().hour >= 9 and frappe.utils.now_datetime().hour < 17"

# Team-based
"doc.agent_group == 'Technical Support' and doc.status == 'Open'"

# Customer domain
"'@enterprise.com' in doc.raised_by"

Update Assignment Rule

import frappe

rule = frappe.get_doc("Assignment Rule", "Support Team Round Robin")

# Update priority
rule.priority = 15

# Add more users
rule.append("users", {"user": "[email protected]"})

# Update condition
rule.assign_condition = "doc.priority in ['High', 'Critical']"

rule.save()

Disable/Enable Assignment Rule

import frappe

# Disable a rule
frappe.db.set_value(
    "Assignment Rule",
    "Old Support Rule",
    "disabled",
    1
)

# Enable a rule
frappe.db.set_value(
    "Assignment Rule",
    "New Support Rule",
    "disabled",
    0
)

Delete Assignment Rule

import frappe

frappe.delete_doc("Assignment Rule", "Deprecated Rule")

Base Support Rotation

Helpdesk settings include a reference to a base support rotation rule:
import frappe

# Get the base support rotation rule
settings = frappe.get_single("HD Settings")
base_rule = settings.base_support_rotation

if base_rule:
    rule = frappe.get_doc("Assignment Rule", base_rule)
    print(f"Base rotation: {rule.description}")

Team Restrictions

When team restrictions are enabled in HD Settings:
import frappe

settings = frappe.get_single("HD Settings")

if settings.restrict_tickets_by_agent_group:
    # Assignment rules can be filtered by agent's team
    print("Team restrictions enabled")
    
if settings.assign_within_team:
    # Auto-assign only to agents within the ticket's team
    print("Assign within team enabled")

Assignment Rule Priority

Rules are evaluated in priority order (higher number = higher priority):
import frappe

# Get all active rules sorted by priority
rules = frappe.get_list(
    "Assignment Rule",
    filters={
        "disabled": 0,
        "document_type": "HD Ticket"
    },
    fields=["name", "priority", "description"],
    order_by="priority desc"
)

for rule in rules:
    print(f"Priority {rule.priority}: {rule.name}")

Example: Complete Assignment Setup

import frappe

# 1. Create high-priority rule (evaluated first)
high_priority_rule = frappe.get_doc({
    "doctype": "Assignment Rule",
    "name": "Critical Tickets",
    "description": "Assign critical tickets to senior agents",
    "document_type": "HD Ticket",
    "priority": 100,
    "rule": "Load Balancing",
    "assign_condition": "doc.priority == 'Critical'"
})
high_priority_rule.append("users", {"user": "[email protected]"})
high_priority_rule.append("users", {"user": "[email protected]"})
high_priority_rule.insert()

# 2. Create team-specific rule
tech_support_rule = frappe.get_doc({
    "doctype": "Assignment Rule",
    "name": "Technical Support",
    "description": "Round-robin for technical tickets",
    "document_type": "HD Ticket",
    "priority": 50,
    "rule": "Round Robin",
    "assign_condition": "doc.ticket_type == 'Technical'"
})
tech_support_rule.append("users", {"user": "[email protected]"})
tech_support_rule.append("users", {"user": "[email protected]"})
tech_support_rule.insert()

# 3. Create default fallback rule (lowest priority)
default_rule = frappe.get_doc({
    "doctype": "Assignment Rule",
    "name": "Default Assignment",
    "description": "Default rule for all other tickets",
    "document_type": "HD Ticket",
    "priority": 1,
    "rule": "Load Balancing",
    "assign_condition": "True"  # Always matches
})
default_rule.append("users", {"user": "[email protected]"})
default_rule.append("users", {"user": "[email protected]"})
default_rule.insert()

print("Assignment rules configured")

Monitoring Assignment Rules

import frappe

# Check which rule would apply to a ticket
ticket = frappe.get_doc("HD Ticket", "12345")

rules = frappe.get_list(
    "Assignment Rule",
    filters={
        "disabled": 0,
        "document_type": "HD Ticket"
    },
    fields=["name", "priority", "assign_condition"],
    order_by="priority desc"
)

for rule in rules:
    try:
        if eval(rule.assign_condition, {"doc": ticket, "frappe": frappe}):
            print(f"Matching rule: {rule.name} (priority {rule.priority})")
            break
    except Exception as e:
        print(f"Error in rule {rule.name}: {e}")

Standard Frappe API Methods

  • frappe.get_doc("Assignment Rule", rule_name) - Get single rule
  • frappe.get_list("Assignment Rule", filters={...}) - Query rules
  • frappe.delete_doc("Assignment Rule", rule_name) - Delete rule

Build docs developers (and LLMs) love