Spaces:
Sleeping
Self-Assignment Feature
Overview
The self-assignment feature empowers field agents to pick their own work from an available ticket pool, reducing dispatcher workload and giving agents autonomy over their daily schedule.
Key Benefits
For Agents
- Autonomy: Choose tickets based on location, complexity, or schedule
- Better Route Planning: Agents know their areas and can optimize travel
- Faster Pickup: No waiting for dispatcher assignment
- Workload Control: Visual capacity management (max 4 active tickets)
For Dispatchers
- Reduced Workload: Agents handle routine assignments themselves
- Focus on Priorities: Dispatch only VIP/escalated tickets manually
- Better Resource Utilization: Agents pick work they're best suited for
For Business
- Faster Ticket Resolution: Reduced assignment delays
- Improved Efficiency: Better geographic clustering
- Audit Trail: Complete tracking of who picked what and when
How It Works
1. Available Ticket Pool
Agents see tickets that are:
- β Status = OPEN (not assigned, in_progress, completed, or cancelled)
- β
In Agent's Region (based on
project_team.project_region_id) - β From Agent's Projects (agent must be on project team)
- β Ordered by Priority (high priority, urgent, oldest first)
GET /api/v1/assignments/tickets/available-for-me
Response:
{
"agent_id": "agent-uuid",
"agent_region_id": "region-uuid",
"current_active_count": 2,
"max_capacity": 4,
"remaining_capacity": 2,
"available_tickets": [
{
"id": "ticket-uuid",
"ticket_name": "John Doe - Fiber Installation",
"ticket_type": "installation",
"service_type": "fiber",
"priority": "high",
"status": "open",
"work_description": "Install 50Mbps fiber connection",
"scheduled_date": "2024-03-20",
"due_date": "2024-03-20T17:00:00Z",
"sla_violated": false,
"project_region_id": "region-uuid"
}
],
"total_available": 15
}
2. Self-Assign Ticket
Agent picks ticket from pool:
POST /api/v1/assignments/tickets/{ticket_id}/self-assign
Request:
{
"execution_order": 1,
"planned_start_time": "2024-03-20T09:00:00Z",
"notes": "I know this area well, can complete quickly"
}
Validations:
- β Ticket is OPEN (not already assigned)
- β Agent is on project team
- β Agent's region matches ticket region
- β Agent has capacity (< 4 active tickets)
- β No duplicate active assignment
Effects:
- Creates assignment with
action='self_assigned'andis_self_assigned=True assigned_by_user_id=user_id(self)- Ticket status changes:
openβassigned
Regional Filtering
Agent Regional Assignment
In project_team table:
project_region_id = NULL: Agent can work all regions in that projectproject_region_id = <region_id>: Agent limited to specific region
Ticket Pool Filtering
System shows tickets based on agent's regional assignments:
# If agent can work all regions in Project A
Agent can see: All tickets from Project A (regardless of ticket.project_region_id)
# If agent is limited to Region X in Project A
Agent can see: Only tickets from Project A where ticket.project_region_id = Region X
Capacity Management
Rules
- Max Active Tickets: 4 per agent
- Active Definition:
ended_at IS NULL - Daily Limit: None (agent can complete 10+ tickets per day)
- Prevents Hoarding: Can't pick more than 4 at once
Lifecycle Example
Morning:
Agent has 0 active β Picks 3 tickets β Now has 3 active
Mid-Day:
Agent completes 2 tickets β Now has 1 active
Agent picks 2 more tickets β Now has 3 active
Afternoon:
Agent drops 1 ticket (customer unavailable) β Now has 2 active
Agent picks 2 more tickets β Now has 4 active (AT CAPACITY)
End of Day:
Agent completes 3 tickets β Now has 1 active
Total completed: 8 tickets in one day β
Assignment Types
Manual Assignment (Dispatcher/PM)
Use Cases:
- VIP customers requiring best technician
- Escalated tickets needing immediate attention
- Team assignments (multiple agents)
- Scheduled appointments
Action: 'assigned'
is_self_assigned: False
Self-Assignment (Agent)
Use Cases:
- Routine installations
- Standard support tickets
- Agent-driven scheduling
- Regional work optimization
Action: 'self_assigned'
is_self_assigned: True
Multiple Assignment Attempts
Same Ticket, Multiple Days
Agents can be assigned to same ticket multiple times (different attempts):
Monday:
Agent picks Ticket #123 β Arrives β Customer unavailable β Drops ticket
Assignment #1: ended_at = Monday 2PM
Tuesday:
Ticket #123 reopened β Agent picks again β Completes successfully
Assignment #2: ended_at = Tuesday 11AM
Benefits:
- Each attempt has separate expense tracking
- Complete audit trail preserved
- Historical data for performance metrics
Validation:
- β Can't have 2+ active assignments for same ticket
- β Can have multiple historical assignments for same ticket
API Endpoints
Self-Assignment
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| GET | /api/v1/assignments/tickets/available-for-me |
Get available tickets for agent | Agent |
| POST | /api/v1/assignments/tickets/{ticket_id}/self-assign |
Self-assign ticket | Agent |
Manual Assignment (Existing)
| Method | Endpoint | Description | Auth |
|---|---|---|---|
| POST | /api/v1/assignments/tickets/{ticket_id}/assign |
Assign to agent | Dispatcher/PM |
| POST | /api/v1/assignments/tickets/{ticket_id}/assign-team |
Assign to team | Dispatcher/PM |
Agent Actions (Existing)
| Method | Endpoint | Description |
|---|---|---|
| POST | /assignments/{id}/accept |
Accept assignment |
| POST | /assignments/{id}/reject |
Reject assignment |
| POST | /assignments/{id}/start-journey |
Begin travel |
| POST | /assignments/{id}/arrived |
Mark arrival |
| POST | /assignments/{id}/complete |
Complete work |
| POST | /assignments/{id}/drop |
Drop ticket |
Error Handling
409 Conflict
{
"detail": "Ticket is not available for self-assignment (status: assigned)"
}
Reason: Someone else picked the ticket first (race condition)
409 Conflict
{
"detail": "Agent has reached capacity (4 active tickets)"
}
Reason: Agent already has 4 active tickets
403 Forbidden
{
"detail": "This ticket is not in your assigned region"
}
Reason: Ticket's region doesn't match agent's regional assignment
400 Bad Request
{
"detail": "Agent is not on this project's team"
}
Reason: Agent not added to project team
Database Schema
ticket_assignments Table
CREATE TABLE ticket_assignments (
id UUID PRIMARY KEY,
ticket_id UUID REFERENCES tickets(id),
user_id UUID REFERENCES users(id),
assigned_by_user_id UUID REFERENCES users(id), -- Self: user_id = assigned_by_user_id
-- Assignment type
action TEXT, -- 'assigned' | 'self_assigned' | 'rejected' | 'dropped' | etc.
is_self_assigned BOOLEAN DEFAULT FALSE, -- TRUE for self-picked tickets
-- Execution planning
execution_order INTEGER,
planned_start_time TIMESTAMPTZ,
-- Timeline
assigned_at TIMESTAMPTZ NOT NULL,
responded_at TIMESTAMPTZ,
journey_started_at TIMESTAMPTZ,
arrived_at TIMESTAMPTZ,
ended_at TIMESTAMPTZ, -- NULL = active, NOT NULL = closed
-- Metadata
notes TEXT,
reason TEXT
);
project_team Table
CREATE TABLE project_team (
id UUID PRIMARY KEY,
project_id UUID REFERENCES projects(id),
user_id UUID REFERENCES users(id),
-- Regional assignment
project_region_id UUID REFERENCES project_regions(id), -- NULL = all regions
role TEXT,
assigned_at TIMESTAMPTZ,
removed_at TIMESTAMPTZ
);
Testing Scenarios
Scenario 1: Agent Picks Available Ticket
1. Agent calls GET /tickets/available-for-me
2. System returns 15 open tickets in agent's region
3. Agent picks ticket #1
4. POST /tickets/{ticket-1}/self-assign
5. Assignment created with is_self_assigned=True
6. Ticket status: open β assigned
Scenario 2: Race Condition (Two Agents Pick Same Ticket)
1. Agent A and Agent B both see ticket #123 in pool
2. Agent A picks ticket #123 at 9:00:01
3. Agent B tries to pick ticket #123 at 9:00:02
4. System returns 409: "Ticket is not available" (already assigned)
5. Agent B picks different ticket from pool
Scenario 3: At Capacity
1. Agent has 4 active tickets
2. Agent tries to pick 5th ticket
3. System returns 409: "Agent has reached capacity (4 active tickets)"
4. Agent must complete/drop existing ticket first
Scenario 4: Regional Restriction
1. Agent assigned to Region A only
2. Ticket #456 is in Region B
3. Agent tries to pick ticket #456
4. System returns 403: "This ticket is not in your assigned region"
5. Agent can only pick tickets from Region A
Scenario 5: Customer Unavailable - Re-pick
Day 1:
1. Agent picks ticket #789
2. Agent arrives at site
3. Customer unavailable
4. Agent drops ticket (ended_at = Day 1)
Day 2:
1. Ticket #789 reopened (status = open)
2. Agent picks ticket #789 again (NEW assignment)
3. Agent completes work
4. Two assignments in history for same ticket
Configuration
Capacity Settings
In ticket_assignment_service.py:
MAX_AGENT_CAPACITY = 4 # Maximum active tickets per agent
Rationale:
- Minimum 3 tickets per day expected
- +1 for ambitious agents
- Prevents ticket hoarding
- Maintains work quality
Future Enhancements
Potential Features
- Smart Recommendations: AI suggests best tickets based on agent skills/location
- Auto-Assignment: System auto-assigns based on proximity and workload
- Team Self-Assignment: Agents pick team tickets together
- Scheduled Picking: Agents reserve tickets for specific time slots
- Priority Booking: High-performing agents get first pick
- Geographic Clustering: Show map view of available tickets
Migration Path
Phase 1: Current State (Manual Only)
- All assignments done by dispatcher
- No agent autonomy
Phase 2: Hybrid (Manual + Self)
- Agents can self-assign routine tickets
- Dispatchers assign VIP/escalated tickets
- Monitor adoption and performance
Phase 3: Future (AI-Assisted)
- System recommends optimal tickets
- Smart auto-assignment for urgent cases
- Dispatchers handle exceptions only
Monitoring & Metrics
Key Metrics to Track
- Self-Assignment Rate: % of tickets self-assigned vs dispatcher-assigned
- Pickup Time: Time from ticket creation to assignment
- Completion Rate: % of self-assigned tickets completed vs dropped
- Regional Distribution: Even workload across regions
- Agent Satisfaction: Survey feedback on autonomy
Dashboard Views
- Dispatcher: See which agents are self-assigning effectively
- Agent: See capacity and available work
- Manager: Compare manual vs self-assignment performance
Summary
β Implemented Features:
- Available ticket pool filtering by region
- Self-assignment with validation
- Capacity management (max 4 active)
- Multiple assignment attempts per ticket
- Complete audit trail
β Benefits:
- Reduced dispatcher workload
- Agent autonomy and efficiency
- Faster ticket pickup
- Better route optimization
β Safeguards:
- Regional restrictions enforced
- Capacity limits prevent hoarding
- Race condition handling
- Complete validation and error handling