swiftops-backend / docs /agent /implementation-notes /TICKET_ACTIONS_IMPLEMENTATION.md
kamau1's picture
Fix incorrect router prefix causing self-assign endpoint 404 and update all related documentation.
061cea4
# Ticket Actions System - Implementation Summary
## What Was Built
A dynamic ticket action system that calculates available actions based on ticket state, user assignment, and journey progress. The backend determines what buttons to show, and the frontend simply renders them.
## Files Created
1. **`src/app/services/ticket_action_service.py`**
- Core service that calculates available actions
- Method: `get_available_actions(ticket, current_user, db)`
- Returns: actions, current_assignment, team_info, message
2. **`supabase/migrations/20251128112603_rename_unassigned_to_completed.sql`**
- Renames enum value `unassigned` β†’ `completed`
- Better semantic meaning for completed assignments
3. **`docs/agent/frontend/TICKET_ACTIONS_SYSTEM.md`**
- Complete frontend integration guide
- Action flow states
- Example implementation
## Files Modified
1. **`src/app/models/enums.py`**
- Changed `UNASSIGNED = "unassigned"` β†’ `COMPLETED = "completed"`
2. **`src/app/services/ticket_assignment_service.py`**
- Added `AssignmentAction` import
- Updated `complete_assignment()` to set `action = COMPLETED`
- Updated `drop_assignment()` to:
- Set `action = DROPPED`
- Set ticket status to `PENDING_REVIEW`
- Drop all team members if team ticket
- Added `drop_type` parameter
- Updated `self_assign_ticket()` to:
- Set `action = ACCEPTED` (auto-accepted)
- Set `responded_at` timestamp
3. **`src/app/schemas/ticket_assignment.py`**
- Added `drop_type` field to `AssignmentDrop` schema
4. **`src/app/api/v1/tickets.py`**
- Updated `GET /tickets/{ticket_id}/detail` endpoint
- Added `TicketActionService` import
- Added to response: `available_actions`, `current_assignment`, `team_info`, `message`
## Key Business Rules
### Assignment Action States
- `assigned` - Dispatcher assigned, agent hasn't responded
- `accepted` - Agent accepted assignment
- `rejected` - Agent rejected assignment
- `dropped` - Agent dropped mid-work
- `reassigned` - Dispatcher reassigned to different agent
- `completed` - Work finished
### Ticket Status Flow
1. `open` - Available for pickup
2. `assigned` - Agent(s) assigned
3. `in_progress` - Agent started journey
4. `pending_review` - Agent dropped, awaiting PM/dispatcher action
5. `completed` - Work finished
6. `cancelled` - Ticket cancelled
### Drop Behavior
- Agent drops β†’ assignment action = `dropped`
- Ticket status β†’ `pending_review`
- If team ticket β†’ ALL team members dropped
- PM/dispatcher reviews and decides: reopen, cancel, or reschedule
### Team Tickets
- `required_team_size` defines how many agents needed
- Multiple agents can pick until full
- ANY team member can complete
- Completing closes ALL team assignments
- Dropping closes ALL team assignments
### Self-Assignment
- Agent picks ticket β†’ auto-accepted (no accept/reject step)
- Creates assignment with `action = accepted`, `responded_at = now()`
- Agent can immediately start journey
## Action Flow
```
NO ASSIGNMENT (ticket open)
↓ [pick]
ACCEPTED (auto-accepted for self-assign)
↓ [start_journey]
IN_TRANSIT (journey started)
↓ [record_arrival]
ON_SITE (arrived at location)
↓ [complete]
COMPLETED
At any point after ACCEPTED:
↓ [drop]
DROPPED (pending_review)
```
## API Endpoints Used
### For Field Agents
- `GET /api/v1/tickets/{ticket_id}/detail` - Get ticket with available actions
- `POST /api/v1/ticket-assignments/tickets/{ticket_id}/self-assign` - Pick ticket
- `POST /api/v1/ticket-assignments/assignments/{assignment_id}/accept` - Accept assignment
- `POST /api/v1/ticket-assignments/assignments/{assignment_id}/reject` - Reject assignment
- `POST /api/v1/ticket-assignments/assignments/{assignment_id}/start-journey` - Start journey
- `POST /api/v1/ticket-assignments/assignments/{assignment_id}/arrived` - Record arrival
- `POST /api/v1/ticket-assignments/assignments/{assignment_id}/complete` - Complete work
- `POST /api/v1/ticket-assignments/assignments/{assignment_id}/drop` - Drop ticket
### For PM/Dispatcher
- `POST /api/v1/ticket-assignments/tickets/{ticket_id}/assign` - Assign to single agent
- `POST /api/v1/ticket-assignments/tickets/{ticket_id}/assign-team` - Assign to team
- Review dropped tickets (status = `pending_review`)
- Decide: reopen, cancel, or reschedule
## Testing Checklist
### Solo Agent Flow
- [ ] Agent picks open ticket
- [ ] Agent starts journey
- [ ] Agent records arrival
- [ ] Agent completes ticket
- [ ] Verify assignment action = `completed`
- [ ] Verify ticket status = `completed`
### Team Flow
- [ ] Agent 1 picks ticket (1/2)
- [ ] Agent 2 picks ticket (2/2)
- [ ] Agent 1 drops ticket
- [ ] Verify Agent 2 also dropped
- [ ] Verify ticket status = `pending_review`
### Drop Flow
- [ ] Agent drops with type "reschedule"
- [ ] Verify ticket status = `pending_review`
- [ ] Verify assignment action = `dropped`
- [ ] PM can see dropped tickets
### Dispatcher Assignment Flow
- [ ] Dispatcher assigns ticket to agent
- [ ] Agent sees accept/reject buttons
- [ ] Agent accepts
- [ ] Agent completes workflow
### View Only States
- [ ] Rejected assignment shows message
- [ ] Dropped assignment shows message
- [ ] Completed assignment shows message
- [ ] Pending review ticket shows message
### Capacity Limits
- [ ] Agent with 4 active tickets can't pick more
- [ ] Agent with 3 active tickets can pick 1 more
### Regional Access (No Restrictions)
- [ ] Agent can pick tickets from any region in their project
- [ ] Region is for filtering/preference, not access control
- [ ] Agents go where the work is to earn a living
## Migration Steps
1. **Run SQL migration:**
```bash
# In Supabase SQL Editor or via migration tool
psql -f supabase/migrations/20251128112603_rename_unassigned_to_completed.sql
```
2. **Deploy backend changes:**
- All Python files compile successfully
- No breaking changes to existing endpoints
3. **Update frontend:**
- Use `available_actions` from ticket detail response
- Render buttons dynamically
- Handle drop modal with `drop_type` field
## Notes
- **No breaking changes** - Existing endpoints still work
- **Backward compatible** - Old clients can still use manual button logic
- **Progressive enhancement** - New clients get dynamic actions
- **Security** - Backend validates all actions, frontend just displays
- **Scalability** - Easy to add new actions (just update calculator)
## Future Enhancements
1. **Action permissions** - Some actions only for certain roles
2. **Action conditions** - "Complete only if expenses approved"
3. **Action metadata** - "Requires GPS", "Requires photo"
4. **Action history** - Track which actions were available when
5. **Action analytics** - Which actions are most used/skipped