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:

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

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

// OLD (broken)
POST /api/v1/api/v1/tickets/{id}/self-assign

// NEW (correct)
POST /api/v1/ticket-assignments/tickets/{id}/self-assign

Expenses:

// OLD (broken)
POST /api/v1/api/v1/

// NEW (correct)
POST /api/v1/expenses/

Progress Reports:

// OLD (broken)
POST /api/v1/api/v1/

// NEW (correct)
POST /api/v1/progress-reports/

Incident Reports:

// OLD (broken)
POST /api/v1/api/v1/

// NEW (correct)
POST /api/v1/incident-reports/

Testing

After server restart, verify these endpoints work:

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