Admin Service Request Status Update Feature
[!NOTE] Purpose of this Document: This is a comprehensive technical reference for the Admin Override feature. It details API contracts, database interactions, real-time synchronization, architectural design decisions, and system limitations.
1. Feature Overview
The Admin Service Request Status Update feature provides system administrators with a high-level override mechanism to forcefully change the state of any service request.
While technicians are bound by a rigid, linear state machine dictated by their mobile application, administrators were originally going to be able to jump states. However, to prevent data corruption and maintain identical lifecycle tracking, administrators are now strictly bound to the exact same step-by-step state machine as technicians (Assigned -> Accepted -> EnRoute -> InProgress -> Completed).
Admins cannot skip steps (e.g., you cannot jump from Accepted directly to InProgress; you must go to EnRoute first). The only exception is Canceled, which can be triggered from any state.
2. API Contract
PUT /service-requests/{requestId}/status
Updates the status of a specific service request.
Authorization Requirements:
- Valid Bearer Token
- Requires Custom Scope:
Right.admin_userusingScopeOperator.And
Request Payload (AdminUpdateServiceRequestStatusRequest)
{
"Status": "Completed", // ENUM: Pending, EnRoute, InProgress, Canceled, Completed
"Mileage": 15.5, // (Decimal) Required ONLY if Status == "Completed"
"CompletedServices": [ // (List of GUIDs) Required ONLY if Status == "Completed"
"3fa85f64-5717-4562-b3fc-2c963f66afa6"
],
"AdditionalServices": [ // (List of GUIDs) Optional
"2db85f64-5717-4562-b3fc-2c963f66afb7"
],
"Evidences": [ // (List of Strings/URLs) Optional
"https://storage.provider.com/evidence-1.jpg"
]
}
Example Responses
200 OK (Success)
{
"status": 200,
"message": "Service request status updated successfully"
}
400 Bad Request (Validation Failure)
{
"status": 400,
"message": "Mileage and Completed Services are required when updating status to Completed."
}
403 Forbidden (State Machine Block)
{
"status": 403,
"message": "Admin cannot update status to Assigned directly. Please use the assignment feature."
}
3. System Architecture & Workflow
The override workflow is centralized within ServiceRequestService.UpdateServiceRequestStatusAdmin.
Sequence Diagram
sequenceDiagram
actor Admin
participant API as ServiceManagementController
participant Service as ServiceRequestService
participant DAL as ServiceRequestDal
participant TechDAL as TechnicianDal
participant RealTime as RealTimeService (SignalR)
participant Cache as RouteCacheService
Admin->>API: PUT /admin/service-requests/{id}/status
API->>Service: UpdateServiceRequestStatusAdmin()
Note over Service: 1. Validate Admin & Guard 'Assigned' Status
Service->>DAL: GetServiceRequestBasicInfo()
alt Status == Completed
Service->>Service: Validate Mileage & Services
Service->>DAL: CompleteServiceRequestDal()
Service->>Service: CreateInvoiceForCompletedServiceAsync()
else All Other Statuses
Service->>DAL: ForceUpdateServiceRequestStatus()
end
Note over Service, TechDAL: 2. Sync Technician Global State
Service->>TechDAL: UpdateTechnicianAvailabilityStatus()
Note over Service, RealTime: 3. Trigger Side-Effects
alt Is Canceled, Pending, or Completed
Service->>Cache: InvalidateRouteAsync()
Service->>RealTime: BroadcastServiceStopped()
Service->>RealTime: BroadcastTechnicianStatusChangeAsync(Available)
else Is InProgress
Service->>RealTime: BroadcastTechnicianStatusChangeAsync(Servicing)
Service->>RealTime: BroadcastServiceStartedAsync()
Service->>Service: SendPushNotification(Customer)
else Is EnRoute
Service->>RealTime: BroadcastTechnicianStatusChangeAsync(EnRoute)
Service->>Service: BroadcastJourneyStartedEventsAsync()
end
Service-->>API: Return Success
API-->>Admin: 200 OK
4. State Transition Matrix (Case Handling)
The system automatically manages cleanup and notifications depending on the chosen destination state:
🟢 Forcing Completed
- Workflow: Validates that
MileageandCompletedServicesare provided in the payload. Calculates the final financial total (Base Services + Additional Services). ExecutesCompleteServiceRequestDalto log the completion. Automatically generates a system invoice (CreateInvoiceForCompletedServiceAsync). - Side-Effects: Frees up the technician (
TechnicianAvailabilityStatus.Available), invalidates the route cache, and stops live tracking (BroadcastServiceStopped). - Use Case: The technician finished the job but their mobile app crashed or lost connectivity before they could hit "Complete" to generate the invoice.
🔴 Forcing Canceled
- Workflow: Uses raw SQL to forcefully update the status to
Canceledand stamps thecancelledattimestamp in the database. - Side-Effects: If the job was actively
EnRouteorInProgress, both the Customer and the Technician receive immediate push notifications ("Admin canceled the request"). Live map tracking is terminated, the route cache is dropped, and the technician is markedAvailable. - Use Case: A customer calls the dispatch office to cancel while a technician is already driving toward them.
🟡 Forcing InProgress
- Workflow: Uses raw SQL to update the status to
InProgressand stampsstartedat. Updates the technician's global availability toServicing. - Side-Effects: Broadcasts
BroadcastServiceStartedAsync(updating the web dashboard map) and fires a "Your service has started" push notification to the customer's phone. - Use Case: A technician arrived on site and started working, but forgot to hit "Start Job" in the app. The admin corrects the state so the customer is properly informed.
🔵 Forcing EnRoute
- Workflow: Updates the status to
EnRouteand shifts the technician's global availability toEnRoute. - Side-Effects: Fetches the technician's details and triggers
BroadcastJourneyStartedEventsAsync. This immediately updates the live tracking map and sends a "Technician is on the way" push notification to the customer. - Use Case: A technician called dispatch to confirm they are driving, but their mobile device died. The admin triggers the journey so the customer isn't left waiting blindly.
⚪ Forcing Pending
- Workflow: Resets the request entirely using raw SQL.
- Side-Effects: The assigned technician is stripped of the job and made
Available. Tracking broadcasts are killed, and the route cache is wiped. - Use Case: A job needs to be completely rescheduled for a future date, destroying the current active tracking session.
5. Architectural Decisions & Differences from Technician Flow
| Characteristic | Technician Flow (HandleTechnicianWorkAction) | Admin Flow (UpdateServiceRequestStatusAdmin) |
|---|---|---|
| Authentication Strategy | Strictly validates the token belongs to the assigned technician. | Validates the token belongs to an Admin. Does not require the Admin to be assigned to the job. |
| State Machine Strictness | Highly linear. Must progress step-by-step. | Exactly the same as technicians. Admins cannot skip steps (e.g., Assigned must go to Accepted, then EnRoute, etc.). |
| Database Strategy | Uses heavily abstracted business-layer wrappers. | Uses optimized direct SQL overrides (ForceUpdateServiceRequestStatus) to inject specific timestamps (startedat, stoppedat) while forcefully skipping intermediary data checks. |
[!TIP] Why separate them? We could have added "admin bypass flags" into the standard technician methods. However, this creates tangled, error-prone code that weakens security. A dedicated admin route keeps the technician pipeline rigidly secure while providing admins a surgical tool to manipulate the database.
6. System Limitations & Guardrails
To prevent critical system corruption, the Admin Override implements several hardcoded limitations:
[!IMPORTANT] No State Jumping Allowed Admins are blocked from jumping over states (e.g., from
Assignedstraight toInProgress). They must call the endpoint sequentially for every intermediate step to maintain perfect timestamp integrity and trigger the correct live socket events.
[!IMPORTANT] Cannot Change Status to
AssignedAdmins are blocked from using this endpoint to selectAssigned. Assignment involves a highly complex workflow (allocating calendar slots, sending dispatch push notifications to technicians, checking shift overlaps). Admins must use the dedicatedAssignServiceRequestToTechnicianfeature for assignments.
[!IMPORTANT] Cannot Start or Complete Unassigned Jobs If a job currently has no technician assigned (e.g.,
TechnicianIdis null), the admin is strictly blocked from forcing the status toEnRoute,InProgress,Stopped, orCompleted. A job cannot logically progress into an active state if there is no human assigned to execute it.
[!CAUTION] Missing Telemetry on Force-Starts When an admin forces a job to
EnRoute, the system successfully broadcasts the journey start. However, if the technician's mobile app is currently turned off or lacks GPS signal, the live customer tracking map will simply show the technician's last known position (a static pin) until their app reconnects to send live telemetry. The admin override cannot artificially produce real-time GPS pings.
7. Affected Files (Code Map)
VanTrackerService/Models/ServiceRequest/ServiceRequest.cs: AddedAdminUpdateServiceRequestStatusRequestpayload model.VanTrackerService/Controllers/ServiceManagementController.cs: Exposed thePUT /admin/service-requests/{requestId}/statusendpoint.VanTrackerService/Services/ServiceRequest/ServiceRequestService.cs: Contains the core orchestration logic insideUpdateServiceRequestStatusAdmin.VanTrackerService/DAL/ServiceRequest/ServiceRequestDal.cs: Contains theForceUpdateServiceRequestStatusraw SQL injection method.