# 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.