Skip to main content
Version: RK Auto

Technician-Van Management Features

Author(s)

  • Sanket Mal
  • Ashik Ikbal

Last Updated Date

2025-01-01


Feature Overview

The Technician-Van Management system provides comprehensive fleet management and technician-vehicle assignment capabilities for the RKAuto Van Tracker platform. This feature enables administrators to manage service vans, assign them to technicians, track assignment history, and monitor vehicle availability in real-time.

Key Features

  • Van Fleet Management: Complete CRUD operations for service vehicle inventory
  • VIN Decoding Integration: Auto-populate vehicle details using NHTSA API
  • Technician-Van Assignment: Dynamic assignment and reassignment of vans to technicians
  • Assignment History Tracking: Complete audit trail of all van assignments
  • Real-Time Availability: Track current van status and technician assignments
  • Automatic Unassignment: Cascade updates when technician status changes to disabled
  • Role-Based Access: Admin-only write operations, read access for technicians

User Types & Workflows

  1. Admin: Add van → Decode VIN → Assign technician → Manage assignments → View history
  2. Technician: View assigned van → View own assignment history → Track current assignment

Requirements

Functional Requirements

IDRequirementPriority
FR-1Admin can add new van with VIN decodingHigh
FR-2Admin can optionally assign technician during van creationMedium
FR-3Admin can update van details and reassign techniciansHigh
FR-4Admin can view all vans with pagination and filtersHigh
FR-5Admin and technician can view technician assignment historyMedium
FR-6Admin can view complete van assignment historyMedium
FR-7System auto-unassigns van when technician is disabledHigh
FR-8Prevent assigning van to technician already assigned a vanHigh
FR-9Track assignment and unassignment timestampsMedium
FR-10Update technician list API to include current van infoHigh

Non-Functional Requirements

IDRequirementTarget
NFR-1API response time< 500ms (95th percentile)
NFR-2VIN validationReal-time validation on input
NFR-3Pagination performanceSupport 1000+ vans efficiently
NFR-4Assignment history retentionMaintain complete audit trail
NFR-5Database transactionACID compliance for assignments

Security Requirements

  • Only Admin role can create, update, and delete vans
  • Only Admin role can assign/unassign technicians to vans
  • Technicians can only view their own assignment history
  • Admin can only view all technician assignment history
  • VIN must be unique across the system
  • Registration numbers must be unique

Component Responsibilities

  1. VanController: HTTP endpoint handling, request validation, authorization
  2. VanService: Business logic, VIN decoding, assignment management, history tracking
  3. VanDal: Database operations, transaction management, complex queries
  4. NHTSA VIN API: External service for vehicle information decoding
  5. PostgreSQL: Van data persistence, assignment tracking, relationship management

Database Schema (PostgreSQL)

Core Tables

vanmaster - Service van inventory and current assignments

Note: This table was already created in migration script 000001-AddUserManagementRelatedTables.

Table Structure:

-- Table already exists from 000001-AddUserManagementRelatedTables migration
-- Shown here for reference

vanmaster (
vanid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
registrationnumber VARCHAR(50) NOT NULL UNIQUE,
vin VARCHAR(17) NOT NULL UNIQUE,
make VARCHAR(50),
model VARCHAR(50),
year INT,
trim VARCHAR(50),
bodytype VARCHAR(50),
status VARCHAR(20) DEFAULT 'Active',
currentlatitude VARCHAR(50),
currentlongitude VARCHAR(50),
createdat TIMESTAMP NOT NULL DEFAULT NOW(),
updatedat TIMESTAMP NOT NULL DEFAULT NOW(),
createdby VARCHAR(100),
updatedby VARCHAR(100)
);

-- Existing indexes
CREATE INDEX idx_vanmaster_status ON vanmaster(status);
CREATE INDEX idx_vanmaster_vin ON vanmaster(vin);

vanassignmenthistory - Complete audit trail of van assignments

CREATE TABLE IF NOT EXISTS vanassignmenthistory (
assignmentid UUID PRIMARY KEY DEFAULT gen_random_uuid(),
vanid UUID NOT NULL,
technicianid UUID NOT NULL,
actionat TIMESTAMPTZ NOT NULL DEFAULT NOW(),
actionby UUID,
action VARCHAR(10),

CONSTRAINT fk_assignment_van
FOREIGN KEY (vanid)
REFERENCES vanmaster(vanid)
ON DELETE CASCADE,
CONSTRAINT fk_assignment_technician
FOREIGN KEY (technicianid)
REFERENCES technicianmaster(technicianid)
ON DELETE CASCADE
);

CREATE INDEX idx_vanassignmenthistory_vanid ON vanassignmenthistory(vanid);
CREATE INDEX idx_vanassignmenthistory_technicianid ON vanassignmenthistory(technicianid);
CREATE INDEX idx_vanassignmenthistory_actionat ON vanassignmenthistory(actionat);
CREATE INDEX idx_vanassignmenthistory_action ON vanassignmenthistory(action);

technicianmaster - Updated to include availability status

-- Migration to add new column for availability status
ALTER TABLE technicianmaster
ADD COLUMN IF NOT EXISTS availabilitystatus VARCHAR(20) DEFAULT 'Available';

CREATE INDEX idx_technicianmaster_availabilitystatus ON technicianmaster(availabilitystatus);

Enumerations

VanStatus - Vehicle operational status

public enum VanStatus
{
Active = 1, // Vehicle is operational and can be used
Maintenance = 2, // Vehicle is in shop for repairs
OutOfService = 3, // Vehicle is broken/damaged
Retired = 4 // Vehicle decommissioned
}

TechnicianAvailabilityStatus - Technician current work status

public enum TechnicianAvailabilityStatus
{
Available = 1, // Roaming around city, available for requests
EnRoute = 2, // Driving to customer location
Servicing = 3, // Actively working on a car
Offline = 4, // Technician off-duty / logged out
OnBreak = 5 // Technician on lunch/break
}

SortDirection - Sorting direction for list queries

public enum SortDirection
{
ASC = 1, // Ascending order
DESC // Descending order
}

VanSortBy - Sorting options for van list

public enum VanSortBy
{
RegistrationNumber = 1,
VIN,
Make,
Model,
Year,
Status,
CreatedAt,
UpdatedAt
}

VanAssignmentHistorySortBy - Sorting options for van assignment history

public enum VanAssignmentHistorySortBy
{
ActionAt = 1,
TechnicianCode = 2,
TechnicianName = 3,
Action = 4
}

TechnicianAssignmentHistorySortBy - Sorting options for technician assignment history

public enum TechnicianAssignmentHistorySortBy
{
ActionAt = 1,
VanRegNumber,
Make,
Model,
Year,
Action
}

VanAssignmentAction - Assignment action type

public enum VanAssignmentAction
{
Assign = 1,
UnAssign
}

C# Request/Response Models

1. Add Van

public record VanRequest
{
[JsonIgnore]
public Guid? VanId { get; init; }

[Required(ErrorMessage = "Registration number is required")]
[MaxLength(50, ErrorMessage = "Registration number cannot exceed 50 characters")]
public required string RegistrationNumber { get; init; }

[Required(ErrorMessage = "VIN is required")]
[StringLength(17, MinimumLength = 17, ErrorMessage = "VIN must be exactly 17 characters")]
[RegularExpression(@"^[A-HJ-NPR-Z0-9]{17}$", ErrorMessage = "Invalid VIN format")]
public required string VIN { get; init; }

[Required(ErrorMessage = "Make is required")]
[MaxLength(50, ErrorMessage = "Make cannot exceed 50 characters")]
public required string Make { get; init; }

[Required(ErrorMessage = "Model is required")]
[MaxLength(50, ErrorMessage = "Model cannot exceed 50 characters")]
public required string Model { get; init; }

[Required(ErrorMessage = "Year is required")]
[Range(1900, 2100, ErrorMessage = "Year must be between 1900 and 2100")]
public required int Year { get; init; }

[MaxLength(50, ErrorMessage = "Trim cannot exceed 50 characters")]
public string? Trim { get; init; }

[MaxLength(50, ErrorMessage = "Body type cannot exceed 50 characters")]
public string? BodyType { get; init; }

public VanStatus Status { get; init; } = VanStatus.Active;

// Optional: Assign technician during van creation/update
public Guid? TechnicianId { get; init; }
}

2. Update Van

// Uses same VanRequest model as Add Van
// VanId is passed in route parameter

3. Van Assign/Unassign Request

public record VanAssignUnassignRequest
{
[Required(ErrorMessage = "Technician ID is required")]
public required Guid TechnicianId { get; init; }

[Required(ErrorMessage = "Action is required")]
public required VanAssignmentAction Action { get; init; }
}

4. Van Details Response

public record VanDetails
{
public Guid VanId { get; init; }
public string RegistrationNumber { get; init; } = string.Empty;
public string VIN { get; init; } = string.Empty;
public string Make { get; init; } = string.Empty;
public string Model { get; init; } = string.Empty;
public int Year { get; init; }
public string? Trim { get; init; }
public string? BodyType { get; init; }
public VanStatus Status { get; init; }
public string StatusDisplayName { get; init; } = string.Empty;
public TechnicianBasicInfo? AssignedTechnician { get; init; }
public DateTime CreatedAt { get; init; }
public DateTime UpdatedAt { get; init; }
}

public record TechnicianBasicInfo
{
public Guid TechnicianId { get; init; }
public string TechnicianCode { get; init; } = string.Empty;
public string FirstName { get; init; } = string.Empty;
public string LastName { get; init; } = string.Empty;
public string Email { get; init; } = string.Empty;
public string PhoneNumber { get; init; } = string.Empty;
public TechnicianAvailabilityStatus AvailabilityStatus { get; init; }
}

5. Technician with Van Response (Updated Technician List)

public record TechnicianDetails
{
public Guid TechnicianId { get; init; }
public Guid UserId { get; init; }
public string TechnicianCode { get; init; } = string.Empty;
public string Email { get; init; } = string.Empty;
public string FirstName { get; init; } = string.Empty;
public string LastName { get; init; } = string.Empty;
public string PhoneNumber { get; init; } = string.Empty;
public UserStatus Status { get; init; }
public string Specialization { get; init; } = string.Empty;
public List<string> Skills { get; init; } = new();
public string EmployeeType { get; init; } = string.Empty;
public TechnicianAvailabilityStatus AvailabilityStatus { get; init; }
public DateOnly JoiningDate { get; init; }
public string? EmergencyContactName { get; init; }
public string? EmergencyContactPhone { get; init; }
public string? ProfileImageUrl { get; init; }
public List<TechnicianAddress> Addresses { get; init; } = new();
public VanInfo? CurrentVan { get; init; }
public DateTime CreatedAt { get; init; }
}

6. Van List Filter

public record VanFilter
{
public string? SearchKeyword { get; set; } // Global search across VIN, registration number, make, model
public VanStatus? Status { get; set; } // Filter by van status
public string? Make { get; set; } // Filter by manufacturer
public string? Model { get; set; } // Filter by model
public int? YearFrom { get; set; }
public int? YearTo { get; set; }
public bool? HasAssignedTechnician { get; set; } // Filter vans with/without technician
public Guid? TechnicianId { get; set; } // Filter by specific technician
public VanSortBy SortBy { get; set; } = VanSortBy.CreatedAt;
public SortDirection SortDirection { get; set; } = SortDirection.DESC;
public int RowsPerPage { get; set; } = 10;
public int PageNumber { get; set; } = 1;
}

7. Van Assignment History Response

public record VanAssignmentHistoryResponse
{
public Guid AssignmentId { get; init; }
public VanInfo Van { get; init; } = new();
public TechnicianInfo Technician { get; init; } = new();
public DateTime ActionAt { get; init; }
public string? ActionBy { get; init; }
public VanAssignmentAction Action { get; init; }
}

public record VanInfo
{
public Guid VanId { get; init; }
public string VanNumber { get; init; } = string.Empty;
public string? RegistrationNumber { get; init; }
public string? Make { get; init; }
public string? Model { get; init; }
public int? Year { get; init; }
}

public record TechnicianInfo
{
public Guid TechnicianId { get; init; }
public string TechnicianCode { get; init; } = string.Empty;
public string TechnicianName { get; init; } = string.Empty;
public string? Email { get; init; }
public string? PhoneNumber { get; init; }
}

8. Van Assignment History Filter

public record VanAssignmentHistoryFilter
{
public DateTime? FromDate { get; set; }
public DateTime? ToDate { get; set; }
public VanAssignmentAction? Action { get; set; } // Filter by action type
public VanAssignmentHistorySortBy SortBy { get; set; } = VanAssignmentHistorySortBy.ActionAt;
public SortDirection SortDirection { get; set; } = SortDirection.DESC;
public int RowsPerPage { get; set; } = 10;
public int PageNumber { get; set; } = 1;
}

9. Technician Assignment History Filter

public record TechnicianAssignmentHistoryFilter
{
public DateTime? FromDate { get; set; }
public DateTime? ToDate { get; set; }
public VanAssignmentAction? Action { get; set; } // Filter by action type
public TechnicianAssignmentHistorySortBy SortBy { get; set; } = TechnicianAssignmentHistorySortBy.ActionAt;
public SortDirection SortDirection { get; set; } = SortDirection.DESC;
public int RowsPerPage { get; set; } = 10;
public int PageNumber { get; set; } = 1;
}

Common Response Models

public record CommonResponse
{
public int Status { get; init; }
public string? Message { get; init; }
}

public record ServerPaginatedData<T>
{
public List<T> Data { get; set; } = [];
public int TotalNumber { get; set; }
public bool HasPreviousPage { get; set; }
public bool HasNextPage { get; set; }
public int TotalPages { get; set; }
public int PageNumber { get; set; }
public int RowsPerPage { get; set; }
}

API Endpoints Overview

Van Management Endpoints

NoEndpointMethodAuth RequiredDescriptionRequest ModelResponse Model
1/vanPOSTYes (Admin)Add new van with optional technicianVanRequestCommonResponse
2/van/{vanId}PUTYes (Admin)Update van details and assignmentVanRequestCommonResponse
3/van/{vanId}/technician-assign-unassignPOSTYes (Admin)Assign or unassign technician to vanVanAssignUnassignRequestCommonResponse
4/vansGETYes (Admin)Get all vans with paginationVanFilter (Query)ServerPaginatedData<VanDetails>
5/van/{vanId}GETYes (Admin)Get single van detailsNoneVanDetails
6/van/{vanId}/assignment-historyGETYes (Admin)Get complete history of a vanVanAssignmentHistoryFilterServerPaginatedData<VanAssignmentHistoryResponse>

Technician Endpoints (Updated)

NoEndpointMethodAuth RequiredDescriptionRequest ModelResponse Model
7/techniciansGETYes (Admin)Get all technicians with van infoTechnicianFilterServerPaginatedData<TechnicianDetails>
8/technician/{technicianId}/assignment-historyGETYes (Admin/Technician)Get technician's van assignment historyTechnicianAssignmentHistoryFilterServerPaginatedData<VanAssignmentHistoryResponse>

HTTP Status Codes

Status CodeDescriptionWhen Used
200OKSuccessful request
201CreatedVan created successfully
400Bad RequestInvalid input, validation failure
401UnauthorizedInvalid credentials, missing auth
403ForbiddenInsufficient permissions
404Not FoundVan/Technician not found
409ConflictVIN/Registration already exists, Technician already assigned
500Internal Server ErrorServer-side error

API Request & Response Examples

1. Add Van API

Endpoint: POST /van

Request Body:

{
"registrationNumber": "DL-1AB-1234",
"vin": "1HGBH41JXMN109186",
"make": "Honda",
"model": "Accord",
"year": 2021,
"trim": "EX-L",
"bodyType": "Sedan",
"status": 1,
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab"
}

Success Response (201 Created):

{
"status": 201,
"message": "Van added successfully"
}

Error Response - VIN Already Exists (409 Conflict):

{
"status": 409,
"message": "Van with VIN '1HGBH41JXMN109186' already exists"
}

Error Response - Technician Already Assigned (409 Conflict):

{
"status": 409,
"message": "Technician is already assigned to another van"
}

2. Update Van API

Endpoint: PUT /van/{vanId}

Request Body:

{
"registrationNumber": "DL-1AB-1234",
"vin": "1HGBH41JXMN109186",
"make": "Honda",
"model": "Accord",
"year": 2021,
"trim": "EX-L",
"bodyType": "Sedan",
"status": 2,
"technicianId": "b2c3d4e5-f6a7-8901-bcde-2345678901bc"
}

Success Response (200 OK):

{
"status": 200,
"message": "Van updated successfully"
}

Error Response - Van Not Found (404 Not Found):

{
"status": 404,
"message": "Van not found"
}

3. Van Technician Assign/Unassign API

Endpoint: POST /van/{vanId}/technician-assign-unassign

Request Body (Assign Technician):

{
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab",
"action": 1
}

Request Body (Unassign Technician):

{
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab",
"action": 2
}

Success Response (200 OK):

{
"status": 200,
"message": "Technician assigned to van successfully"
}

Success Response - Unassign (200 OK):

{
"status": 200,
"message": "Technician unassigned from van successfully"
}

Error Response - Van Not Found (404 Not Found):

{
"status": 404,
"message": "Van not found"
}

Error Response - Technician Not Found (404 Not Found):

{
"status": 404,
"message": "Technician not found"
}

Error Response - Technician Already Assigned (409 Conflict):

{
"status": 409,
"message": "Technician is already assigned to another van"
}

Error Response - Van Already Assigned to Different Technician (409 Conflict):

{
"status": 409,
"message": "Van is already assigned to a different technician"
}

4. Get Van List API

Endpoint: GET /vans

Query Parameters:

?searchKeyword=honda&status=1&hasAssignedTechnician=true&rowsPerPage=10&pageNumber=1

Success Response (200 OK):

{
"data": [
{
"vanId": "f1e2d3c4-b5a6-7890-cdef-3456789012cd",
"registrationNumber": "DL-1AB-1234",
"vin": "1HGBH41JXMN109186",
"make": "Honda",
"model": "Accord",
"year": 2021,
"trim": "EX-L",
"bodyType": "Sedan",
"status": 1,
"statusDisplayName": "Active",
"assignedTechnician": {
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab",
"technicianCode": "TECH-001",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@rkauto.com",
"phoneNumber": "+1-555-0100",
"availabilityStatus": 1
},
"createdAt": "2025-01-01T10:00:00Z",
"updatedAt": "2025-01-01T15:30:00Z"
},
{
"vanId": "a2b3c4d5-e6f7-8901-defg-4567890123de",
"registrationNumber": "DL-2BC-5678",
"vin": "2HGBH41JXMN109187",
"make": "Honda",
"model": "CR-V",
"year": 2022,
"trim": "Touring",
"bodyType": "SUV",
"status": 1,
"statusDisplayName": "Active",
"assignedTechnician": {
"technicianId": "b2c3d4e5-f6a7-8901-bcde-2345678901bc",
"technicianCode": "TECH-002",
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@rkauto.com",
"phoneNumber": "+1-555-0101",
"availabilityStatus": 2
},
"createdAt": "2025-01-02T09:00:00Z",
"updatedAt": "2025-01-02T11:00:00Z"
}
],
"totalNumber": 25,
"hasPreviousPage": false,
"hasNextPage": true,
"totalPages": 3,
"pageNumber": 1,
"rowsPerPage": 10
}

5. Get Single Van Details API

Endpoint: GET /van/{vanId}

Success Response (200 OK):

{
"status": 200,
"message": "Van retrieved successfully",
"data": {
"vanId": "f1e2d3c4-b5a6-7890-cdef-3456789012cd",
"registrationNumber": "DL-1AB-1234",
"vin": "1HGBH41JXMN109186",
"make": "Honda",
"model": "Accord",
"year": 2021,
"trim": "EX-L",
"bodyType": "Sedan",
"status": 1,
"statusDisplayName": "Active",
"assignedTechnician": {
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab",
"technicianCode": "TECH-001",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@rkauto.com",
"phoneNumber": "+1-555-0100",
"availabilityStatus": 1
},
"createdAt": "2025-01-01T10:00:00Z",
"updatedAt": "2025-01-01T15:30:00Z"
}
}

Error Response - Van Not Found (404 Not Found):

{
"status": 404,
"message": "Van not found"
}

6. Get Van Assignment History API

Endpoint: GET /van/{vanId}/assignment-history

Query Parameters:

?fromDate=2024-01-01&toDate=2025-12-31&action=1&rowsPerPage=10&pageNumber=1

Success Response (200 OK):

{
"data": [
{
"assignmentId": "c1d2e3f4-a5b6-7890-efgh-5678901234ef",
"van": {
"vanId": "f1e2d3c4-b5a6-7890-cdef-3456789012cd",
"registrationNumber": "DL-1AB-1234",
"make": "Honda",
"model": "Accord",
"year": 2021
},
"technician": {
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab",
"technicianCode": "TECH-001",
"technicianName": "John Doe",
"email": "john.doe@rkauto.com",
"phoneNumber": "+1-555-0100"
},
"actionAt": "2025-01-01T10:00:00Z",
"actionBy": "admin@rkauto.com",
"action": 1
},
{
"assignmentId": "d2e3f4a5-b6c7-8901-fghi-6789012345fg",
"van": {
"vanId": "f1e2d3c4-b5a6-7890-cdef-3456789012cd",
"registrationNumber": "DL-1AB-1234",
"make": "Honda",
"model": "Accord",
"year": 2021
},
"technician": {
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab",
"technicianCode": "TECH-001",
"technicianName": "John Doe",
"email": "john.doe@rkauto.com",
"phoneNumber": "+1-555-0100"
},
"actionAt": "2025-01-08T09:00:00Z",
"actionBy": "admin@rkauto.com",
"action": 2
},
{
"assignmentId": "e3f4a5b6-c7d8-9012-ghij-7890123456gh",
"van": {
"vanId": "f1e2d3c4-b5a6-7890-cdef-3456789012cd",
"registrationNumber": "DL-1AB-1234",
"make": "Honda",
"model": "Accord",
"year": 2021
},
"technician": {
"technicianId": "b2c3d4e5-f6a7-8901-bcde-2345678901bc",
"technicianCode": "TECH-002",
"technicianName": "Jane Smith",
"email": "jane.smith@rkauto.com",
"phoneNumber": "+1-555-0101"
},
"actionAt": "2025-01-08T09:00:00Z",
"actionBy": "admin@rkauto.com",
"action": 1
},
{
"assignmentId": "f4a5b6c7-d8e9-0123-hijk-8901234567hi",
"van": {
"vanId": "f1e2d3c4-b5a6-7890-cdef-3456789012cd",
"registrationNumber": "DL-1AB-1234",
"make": "Honda",
"model": "Accord",
"year": 2021
},
"technician": {
"technicianId": "b2c3d4e5-f6a7-8901-bcde-2345678901bc",
"technicianCode": "TECH-002",
"technicianName": "Jane Smith",
"email": "jane.smith@rkauto.com",
"phoneNumber": "+1-555-0101"
},
"actionAt": "2025-01-20T17:00:00Z",
"actionBy": "admin@rkauto.com",
"action": 2
}
],
"totalNumber": 8,
"hasPreviousPage": false,
"hasNextPage": false,
"totalPages": 1,
"pageNumber": 1,
"rowsPerPage": 10
}

7. Get Technician List with Van Info API

Endpoint: GET /technicians

Query Parameters:

?searchKeyword=john&hasVanAssigned=true&rowsPerPage=10&pageNumber=1

Success Response (200 OK):

{
"data": [
{
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab",
"technicianCode": "TECH-001",
"firstName": "John",
"lastName": "Doe",
"email": "john.doe@rkauto.com",
"phoneNumber": "+1-555-0100",
"joiningDate": "2024-01-15T00:00:00Z",
"employeeType": "Full-Time",
"specialization": "Engine Specialist",
"skills": ["Engine Repair", "Diagnostics", "Oil Change"],
"availabilityStatus": 1,
"currentVan": {
"vanId": "f1e2d3c4-b5a6-7890-cdef-3456789012cd",
"registrationNumber": "DL-1AB-1234",
"make": "Honda",
"model": "Accord",
"year": 2021,
"status": 1
},
"createdAt": "2024-01-15T08:00:00Z",
"updatedAt": "2025-01-01T10:00:00Z"
},
{
"technicianId": "b2c3d4e5-f6a7-8901-bcde-2345678901bc",
"technicianCode": "TECH-002",
"firstName": "Jane",
"lastName": "Smith",
"email": "jane.smith@rkauto.com",
"phoneNumber": "+1-555-0101",
"joiningDate": "2024-02-01T00:00:00Z",
"employeeType": "Full-Time",
"specialization": "Transmission Expert",
"skills": ["Transmission Repair", "Brake Service", "Suspension"],
"availabilityStatus": 2,
"currentVan": {
"vanId": "a2b3c4d5-e6f7-8901-defg-4567890123de",
"registrationNumber": "DL-2BC-5678",
"make": "Honda",
"model": "CR-V",
"year": 2022,
"status": 1
},
"createdAt": "2024-02-01T08:00:00Z",
"updatedAt": "2025-01-02T09:00:00Z"
}
],
"totalNumber": 15,
"hasPreviousPage": false,
"hasNextPage": true,
"totalPages": 2,
"pageNumber": 1,
"rowsPerPage": 10
}

8. Get Technician Assignment History API

Endpoint: GET /technician/{technicianId}/assignment-history

Query Parameters:

?fromDate=2024-01-01&action=1&rowsPerPage=10&pageNumber=1

Success Response (200 OK):

{
"data": [
{
"assignmentId": "c1d2e3f4-a5b6-7890-efgh-5678901234ef",
"van": {
"vanId": "f1e2d3c4-b5a6-7890-cdef-3456789012cd",
"registrationNumber": "DL-1AB-1234",
"make": "Honda",
"model": "Accord",
"year": 2021
},
"technician": {
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab",
"technicianCode": "TECH-001",
"technicianName": "John Doe",
"email": "john.doe@rkauto.com",
"phoneNumber": "+1-555-0100"
},
"actionAt": "2025-01-01T10:00:00Z",
"actionBy": "admin@rkauto.com",
"action": 1
},
{
"assignmentId": "d2e3f4a5-b6c7-8901-fghi-6789012345fg",
"van": {
"vanId": "f1e2d3c4-b5a6-7890-cdef-3456789012cd",
"registrationNumber": "DL-1AB-1234",
"make": "Honda",
"model": "Accord",
"year": 2021
},
"technician": {
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab",
"technicianCode": "TECH-001",
"technicianName": "John Doe",
"email": "john.doe@rkauto.com",
"phoneNumber": "+1-555-0100"
},
"actionAt": "2025-01-08T09:00:00Z",
"actionBy": "admin@rkauto.com",
"action": 2
},
{
"assignmentId": "e3f4a5b6-c7d8-9012-ghij-7890123456gh",
"van": {
"vanId": "a2b3c4d5-e6f7-8901-defg-4567890123de",
"registrationNumber": "DL-2BC-5678",
"make": "Honda",
"model": "CR-V",
"year": 2022
},
"technician": {
"technicianId": "a1b2c3d4-e5f6-7890-abcd-1234567890ab",
"technicianCode": "TECH-001",
"technicianName": "John Doe",
"email": "john.doe@rkauto.com",
"phoneNumber": "+1-555-0100"
},
"actionAt": "2025-01-08T09:00:00Z",
"actionBy": "admin@rkauto.com",
"action": 1
}
],
"totalNumber": 3,
"hasPreviousPage": false,
"hasNextPage": false,
"totalPages": 1,
"pageNumber": 1,
"rowsPerPage": 10
}

Business Logic & Workflows

1. Add Van Workflow

1. Admin enters VIN (17 characters)
2. System validates VIN format
3. System calls NHTSA VIN Decoder API
4. Auto-populate: Make, Model, Year, Body Type, Trim
5. Admin reviews and edits if needed
6. Admin enters Registration Number
7. Admin optionally selects available technician
8. System validates:
- VIN uniqueness
- Registration number uniqueness
- Technician availability (not already assigned to another van)
9. Create van record in vanmaster table
10. If technician assigned:
- Update technicianmaster.currentvanid
- Create entry in vanassignmenthistory
11. Return van details with assignment info

2. Update Van Workflow

1. Admin updates van details (make, model, status, etc.)
2. Admin changes technician assignment:
Case A: Assign new technician to unassigned van
Case B: Reassign van from one technician to another
Case C: Unassign van from current technician
3. System validates:
- New technician (if any) is not already assigned to another van
- Van exists and is editable
4. For Case B or Case C:
- Update previous assignment: set unassignedat = NOW()
- Update previous technician: set currentvanid = NULL
5. For Case A or Case B:
- Update vanmaster.currenttechnicianid
- Update new technician: set currentvanid
- Create new entry in van_assignment_history
6. Return updated van details

3. Disable Technician Cascade Logic

When technician status changes to Disabled:
1. Check if technician has assigned van (currentvanid IS NOT NULL)
2. If yes:
- Get vanid from technician record
- Update vanassignmenthistory: set unassignedat = NOW()
- Update technicianmaster: set currentvanid = NULL
3. Update technician status to Disabled
4. Commit transaction

Development Tasks & Estimates

Phase 1: Core Van Management (3 days)

TaskEstimated HoursPriorityOptimization Strategy
Database migration script3hHighUse existing migration templates
Add Van API6hHighLeverage existing CRUD patterns
Update Van API4hHighReuse Add Van validation logic
Get Van List API5hHighApply existing pagination patterns
Get Single Van Details API2hMediumSimple query, minimal logic
VIN Decoder Integration4hHighBasic HTTP client wrapper

Subtotal: 24 hours

Phase 2: Assignment History (2 days)

TaskEstimated HoursPriorityOptimization Strategy
Van Assignment History API4hMediumReuse list API patterns
Technician Assignment History API4hMediumClone van history logic
Assignment/Unassignment Logic6hHighCore business logic - minimal viable
Cascade Unassignment on Disable3hHighDatabase trigger or event handler

Subtotal: 17 hours

Phase 3: Technician Updates (1 day)

TaskEstimated HoursPriorityOptimization Strategy
Update Technician List API (add van)3hHighAdd join query to existing API
Add availability status field2hMediumSingle column migration + model
Update technician models1hMediumStraightforward model updates

Subtotal: 6 hours

Phase 4: Testing & Documentation (2.5 days)

TaskEstimated HoursPriorityOptimization Strategy
Unit Tests8hHighFocus on critical paths only
Integration Tests6hHighTest key workflows (add/assign/history)
API Documentation (Swagger)2hMediumAuto-generate from attributes
Performance Testing4hMediumBasic load testing on list endpoints

Subtotal: 20 hours


Total Estimated Time: 2 weeks (67 hours)

Time Savings: 32 hours

Optimization Approach

  • Reuse Existing Patterns: Leverage established CRUD, pagination, and filtering patterns
  • Parallel Development: Database migrations and API endpoints can be developed concurrently
  • Auto-Generation: Use Swagger attributes for automatic API documentation
  • Focused Testing: Prioritize critical business logic over exhaustive coverage
  • Template Utilization: Apply proven migration and boilerplate templates

Notes

Key Implementation Considerations

  1. Assignment Tracking Design:

    • Assignment relationship is maintained via technicianmaster.currentvanid only
    • To get assigned technician for a van: SELECT * FROM technicianmaster WHERE currentvanid = @vanid
    • To get assigned van for a technician: Use currentvanid directly from technician record
    • This unidirectional approach prevents data inconsistency issues
  2. VIN Decoding Integration:

    • Use NHTSA VIN Decoder API: https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVin/{VIN}?format=json
    • Cache decoded results to reduce external API calls
    • Handle API failures gracefully with manual entry fallback
    • Validate VIN format before making external calls
  3. Assignment Transaction Logic:

    BEGIN TRANSACTION;

    -- Unassign previous technician (if any)
    UPDATE vanassignmenthistory
    SET unassignedat = NOW(), unassignedby = @admin_user
    WHERE vanid = @vanid AND unassignedat IS NULL;

    UPDATE technicianmaster
    SET currentvanid = NULL
    WHERE currentvanid = @vanid;

    -- Assign new technician
    UPDATE technicianmaster
    SET currentvanid = @vanid
    WHERE technicianid = @new_technician_id;

    UPDATE vanmaster
    SET updatedat = NOW()
    WHERE vanid = @vanid;

    INSERT INTO vanassignmenthistory (vanid, technicianid, assignedby)
    VALUES (@vanid, @new_technician_id, @admin_user);

    COMMIT;
  4. Validation Rules:

    • VIN must be exactly 17 alphanumeric characters (no I, O, Q)
    • Registration number format varies by state/country (configurable regex)
    • Technician can only be assigned to one van at a time
    • Van can only be assigned to one technician at a time
    • Cannot delete van with active assignments (must unassign first)
  5. Performance Optimization:

    • Index on frequently queried columns (status, currentvanid in technicianmaster)
    • Use pagination for all list endpoints
    • Implement caching for van list queries
    • Consider materialized views for complex history queries
  6. Security Considerations:

    • Only Admin role can modify van data
    • Technicians can only view their own assignment history
    • Log all assignment/unassignment operations
    • Validate user permissions before any write operation
  7. Future Enhancements:

    • GPS tracking integration for real-time van location
    • Maintenance schedule tracking
    • Fuel consumption and mileage tracking
    • Van availability calendar
    • Automated assignment based on technician location
    • Mobile app notifications for assignment changes
    • Van inspection checklist integration
    • Insurance and registration expiry alerts