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:
Unique identifier for the rule
Human-readable description of the rule
Whether the rule is active
Rule priority (higher priority rules are evaluated first)
Target DocType (typically “HD Ticket”)
Python expression to determine when rule applies
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:
Whether the rule is disabled
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