kamau1's picture
Add TicketStatusHistory model and integrate automatic status logging into ticket assignment workflow.
a71d9fe
# Router Prefix Fix - Correcting Double /api/v1 Issue
## Problem
Four routers were configured with prefix `/api/v1`, which caused double prefixing since the main app already adds `/api/v1`:
```python
# WRONG - causes /api/v1/api/v1/...
api_router.include_router(ticket_assignments.router, prefix="/api/v1", tags=["..."])
api_router.include_router(expenses.router, prefix="/api/v1", tags=["..."])
api_router.include_router(progress_reports.router, prefix="/api/v1", tags=["..."])
api_router.include_router(incident_reports.router, prefix="/api/v1", tags=["..."])
```
## URL Construction
FastAPI builds URLs by concatenating:
1. Main app prefix: `/api/v1` (from main.py)
2. Router prefix: `/api/v1` (WRONG - duplicates the prefix)
3. Route path: `/tickets/{id}/self-assign`
Result: `/api/v1/api/v1/tickets/{id}/self-assign` ❌
## Solution
Changed router prefixes to be semantic paths without `/api/v1`:
```python
# CORRECT - results in /api/v1/ticket-assignments/...
api_router.include_router(ticket_assignments.router, prefix="/ticket-assignments", tags=["..."])
api_router.include_router(expenses.router, prefix="/expenses", tags=["..."])
api_router.include_router(progress_reports.router, prefix="/progress-reports", tags=["..."])
api_router.include_router(incident_reports.router, prefix="/incident-reports", tags=["..."])
```
## Fixed Endpoints
### 1. Ticket Assignments
**Before:** `/api/v1/api/v1/tickets/{id}/self-assign` ❌
**After:** `/api/v1/ticket-assignments/tickets/{id}/self-assign` βœ…
**Routes affected:**
- `POST /api/v1/ticket-assignments/tickets/{ticket_id}/self-assign` - Self-assign ticket
- `POST /api/v1/ticket-assignments/tickets/{ticket_id}/assign` - Assign to agent
- `POST /api/v1/ticket-assignments/tickets/{ticket_id}/assign-team` - Assign to team
- `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
- `GET /api/v1/ticket-assignments/tickets/available-for-me` - Get available tickets
- `GET /api/v1/ticket-assignments/assignments/{assignment_id}` - Get assignment details
- `GET /api/v1/ticket-assignments/tickets/{ticket_id}/assignments` - Get ticket assignments
### 2. Expenses
**Before:** `/api/v1/api/v1/` ❌
**After:** `/api/v1/expenses/` βœ…
**Routes affected:**
- `POST /api/v1/expenses/` - Create expense
- `GET /api/v1/expenses/` - List expenses
- `GET /api/v1/expenses/{expense_id}` - Get expense
- `PATCH /api/v1/expenses/{expense_id}` - Update expense
- `POST /api/v1/expenses/{expense_id}/approve` - Approve expense
- `POST /api/v1/expenses/{expense_id}/payment-details` - Add payment details
- `POST /api/v1/expenses/{expense_id}/mark-paid` - Mark as paid
- `GET /api/v1/expenses/stats` - Get expense stats
- `DELETE /api/v1/expenses/{expense_id}` - Delete expense
### 3. Progress Reports
**Before:** `/api/v1/api/v1/` ❌
**After:** `/api/v1/progress-reports/` βœ…
**Routes affected:**
- `POST /api/v1/progress-reports/` - Create progress report
- `GET /api/v1/progress-reports/` - List progress reports
- `GET /api/v1/progress-reports/stats` - Get stats
- `GET /api/v1/progress-reports/{report_id}` - Get report
- `PATCH /api/v1/progress-reports/{report_id}` - Update report
- `DELETE /api/v1/progress-reports/{report_id}` - Delete report
### 4. Incident Reports
**Before:** `/api/v1/api/v1/` ❌
**After:** `/api/v1/incident-reports/` βœ…
**Routes affected:**
- `POST /api/v1/incident-reports/` - Create incident report
- `GET /api/v1/incident-reports/` - List incident reports
- `GET /api/v1/incident-reports/stats` - Get stats
- `GET /api/v1/incident-reports/{report_id}` - Get report
- `PATCH /api/v1/incident-reports/{report_id}` - Update report
- `POST /api/v1/incident-reports/{report_id}/resolve` - Resolve incident
- `DELETE /api/v1/incident-reports/{report_id}` - Delete report
## Files Modified
- `src/app/api/v1/router.py` - Fixed 4 router prefixes
## Breaking Changes
**Yes - this is a breaking change for any frontend code calling these endpoints.**
### Frontend Updates Required
If your frontend is calling any of these endpoints, you need to update the URLs:
**Ticket Assignments:**
```javascript
// OLD (broken)
POST /api/v1/api/v1/tickets/{id}/self-assign
// NEW (correct)
POST /api/v1/ticket-assignments/tickets/{id}/self-assign
```
**Expenses:**
```javascript
// OLD (broken)
POST /api/v1/api/v1/
// NEW (correct)
POST /api/v1/expenses/
```
**Progress Reports:**
```javascript
// OLD (broken)
POST /api/v1/api/v1/
// NEW (correct)
POST /api/v1/progress-reports/
```
**Incident Reports:**
```javascript
// OLD (broken)
POST /api/v1/api/v1/
// NEW (correct)
POST /api/v1/incident-reports/
```
## Testing
After server restart, verify these endpoints work:
```bash
# Test ticket assignment
curl -X POST "http://localhost:7860/api/v1/ticket-assignments/tickets/{ticket_id}/self-assign" \
-H "Authorization: Bearer {token}"
# Test expense creation
curl -X POST "http://localhost:7860/api/v1/expenses/" \
-H "Authorization: Bearer {token}"
# Test progress report creation
curl -X POST "http://localhost:7860/api/v1/progress-reports/" \
-H "Authorization: Bearer {token}"
# Test incident report creation
curl -X POST "http://localhost:7860/api/v1/incident-reports/" \
-H "Authorization: Bearer {token}"
```
## Migration Steps
1. **Deploy backend changes** - Server restart required
2. **Update frontend** - Change all API calls to use new URLs
3. **Test all affected features** - Verify ticket assignments, expenses, reports work
## Why This Happened
The routers were likely copied from a template or created at different times without consistent prefix conventions. The `/api/v1` prefix should only be added at the main app level, not at individual router levels.
## Prevention
When creating new routers, use semantic prefixes:
- βœ… `prefix="/users"`
- βœ… `prefix="/tickets"`
- βœ… `prefix="/ticket-assignments"`
- ❌ `prefix="/api/v1"` (never do this)
The `/api/v1` prefix is already added by the main app, so individual routers should only specify their resource path.