Initial commit
This commit is contained in:
@@ -0,0 +1,306 @@
|
||||
using Microsoft.AspNetCore.Authorization;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using RobotNet10.MapEditor.Shared.DTOs.VehicleType;
|
||||
using RobotNet10.MapEditor.Shared.DTOs.Requests;
|
||||
using RobotNet10.MapEditor.Shared.DTOs.Responses;
|
||||
using RobotNet10.MapManager.Services;
|
||||
|
||||
namespace RobotNet10.MapManager.Controllers;
|
||||
|
||||
/// <summary>
|
||||
/// Controller for managing vehicle types
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/vehicles")]
|
||||
[Authorize]
|
||||
public class VehiclesManagerController(
|
||||
IVehicleTypeService vehicleTypeService,
|
||||
ILogger<VehiclesManagerController> logger) : ControllerBase
|
||||
{
|
||||
private readonly IVehicleTypeService _vehicleTypeService = vehicleTypeService;
|
||||
private readonly ILogger<VehiclesManagerController> _logger = logger;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new vehicle type
|
||||
/// </summary>
|
||||
/// <param name="request">Vehicle type creation request</param>
|
||||
/// <returns>Created vehicle type</returns>
|
||||
[HttpPost]
|
||||
[ProducesResponseType(typeof(VehicleTypeDto), 201)]
|
||||
[ProducesResponseType(400)]
|
||||
public async Task<ActionResult<VehicleTypeDto>> CreateVehicleType([FromBody] CreateVehicleTypeRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var vehicleType = await _vehicleTypeService.CreateAsync(
|
||||
request.VehicleTypeId,
|
||||
request.VehicleTypeName,
|
||||
request.Description,
|
||||
request.Specifications,
|
||||
request.Actions);
|
||||
|
||||
var dto = MapToDto(vehicleType);
|
||||
|
||||
return CreatedAtAction(
|
||||
nameof(GetVehicleType),
|
||||
new { vehicleTypeId = vehicleType.Id },
|
||||
dto);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to create vehicle type: {VehicleTypeId}", request.VehicleTypeId);
|
||||
var errorCode = ex.Message.Contains("already exists")
|
||||
? "VEHICLE_TYPE_ALREADY_EXISTS"
|
||||
: "VALIDATION_ERROR";
|
||||
return BadRequest(CreateErrorResponse(ex.Message, errorCode));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get all vehicle types
|
||||
/// </summary>
|
||||
/// <param name="isActive">Optional filter by active status</param>
|
||||
/// <returns>List of vehicle types</returns>
|
||||
[HttpGet]
|
||||
[ProducesResponseType(typeof(List<VehicleTypeDto>), 200)]
|
||||
public async Task<ActionResult<List<VehicleTypeDto>>> GetAllVehicleTypes([FromQuery] bool? isActive)
|
||||
{
|
||||
List<Data.VehicleType> vehicleTypes;
|
||||
|
||||
if (isActive.HasValue)
|
||||
{
|
||||
vehicleTypes = await _vehicleTypeService.GetByActiveStatusAsync(isActive.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
vehicleTypes = await _vehicleTypeService.GetAllAsync();
|
||||
}
|
||||
|
||||
var dtos = vehicleTypes.Select(MapToDto).ToList();
|
||||
|
||||
return Ok(dtos);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get vehicle type by database ID
|
||||
/// </summary>
|
||||
/// <param name="vehicleTypeId">Vehicle type database ID</param>
|
||||
/// <returns>Vehicle type details</returns>
|
||||
[HttpGet("{vehicleTypeId}")]
|
||||
[ProducesResponseType(typeof(VehicleTypeDto), 200)]
|
||||
[ProducesResponseType(404)]
|
||||
public async Task<ActionResult<VehicleTypeDto>> GetVehicleType(Guid vehicleTypeId)
|
||||
{
|
||||
var vehicleType = await _vehicleTypeService.GetByIdAsync(vehicleTypeId);
|
||||
|
||||
if (vehicleType == null)
|
||||
{
|
||||
return NotFound(CreateErrorResponse(
|
||||
$"Vehicle type with ID '{vehicleTypeId}' not found",
|
||||
"VEHICLE_TYPE_NOT_FOUND"));
|
||||
}
|
||||
|
||||
return Ok(MapToDto(vehicleType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get vehicle type by VehicleTypeId string
|
||||
/// </summary>
|
||||
/// <param name="vehicleTypeId">Vehicle type identifier string (e.g., "AMR-T800")</param>
|
||||
/// <returns>Vehicle type details</returns>
|
||||
[HttpGet("vehicleTypeId/{vehicleTypeId}")]
|
||||
[ProducesResponseType(typeof(VehicleTypeDto), 200)]
|
||||
[ProducesResponseType(404)]
|
||||
public async Task<ActionResult<VehicleTypeDto>> GetVehicleTypeByStringId(string vehicleTypeId)
|
||||
{
|
||||
var vehicleType = await _vehicleTypeService.GetByVehicleTypeIdAsync(vehicleTypeId);
|
||||
|
||||
if (vehicleType == null)
|
||||
{
|
||||
return NotFound(CreateErrorResponse(
|
||||
$"Vehicle type with VehicleTypeId '{vehicleTypeId}' not found",
|
||||
"VEHICLE_TYPE_NOT_FOUND"));
|
||||
}
|
||||
|
||||
return Ok(MapToDto(vehicleType));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Search vehicle types by query string
|
||||
/// Searches in VehicleTypeId and VehicleTypeName (case-insensitive)
|
||||
/// </summary>
|
||||
/// <param name="query">Search query</param>
|
||||
/// <returns>List of matching vehicle types</returns>
|
||||
[HttpGet("search")]
|
||||
[ProducesResponseType(typeof(List<VehicleTypeDto>), 200)]
|
||||
public async Task<ActionResult<List<VehicleTypeDto>>> SearchVehicleTypes([FromQuery] string query)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(query))
|
||||
{
|
||||
return BadRequest(CreateErrorResponse(
|
||||
"Query parameter is required",
|
||||
"VALIDATION_ERROR"));
|
||||
}
|
||||
|
||||
var vehicleTypes = await _vehicleTypeService.SearchAsync(query);
|
||||
var dtos = vehicleTypes.Select(MapToDto).ToList();
|
||||
|
||||
return Ok(dtos);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get usage information for a vehicle type
|
||||
/// </summary>
|
||||
/// <param name="id">Vehicle type database ID</param>
|
||||
/// <returns>Usage information</returns>
|
||||
[HttpGet("{id}/usage")]
|
||||
[ProducesResponseType(typeof(VehicleTypeUsageInfoDto), 200)]
|
||||
[ProducesResponseType(404)]
|
||||
public async Task<ActionResult<VehicleTypeUsageInfoDto>> GetVehicleTypeUsage(Guid id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var usageInfo = await _vehicleTypeService.GetUsageInfoAsync(id);
|
||||
var dto = MapUsageInfoToDto(usageInfo);
|
||||
|
||||
return Ok(dto);
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
_logger.LogWarning(ex, "Failed to get usage info for vehicle type: {Id}", id);
|
||||
return NotFound(CreateErrorResponse(ex.Message, "VEHICLE_TYPE_NOT_FOUND"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update vehicle type
|
||||
/// </summary>
|
||||
/// <param name="vehicleTypeId">Vehicle type database ID</param>
|
||||
/// <param name="request">Update request</param>
|
||||
/// <returns>Updated vehicle type</returns>
|
||||
[HttpPut("{vehicleTypeId}")]
|
||||
[ProducesResponseType(typeof(VehicleTypeDto), 200)]
|
||||
[ProducesResponseType(404)]
|
||||
public async Task<ActionResult<VehicleTypeDto>> UpdateVehicleType(
|
||||
Guid vehicleTypeId,
|
||||
[FromBody] UpdateVehicleTypeRequest request)
|
||||
{
|
||||
try
|
||||
{
|
||||
var vehicleType = await _vehicleTypeService.UpdateAsync(
|
||||
vehicleTypeId,
|
||||
request.VehicleTypeName,
|
||||
request.Description,
|
||||
request.Specifications,
|
||||
request.Actions,
|
||||
request.IsActive);
|
||||
|
||||
return Ok(MapToDto(vehicleType));
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
if (_logger.IsEnabled(LogLevel.Warning)) _logger.LogWarning(ex, "Failed to update vehicle type: {VehicleTypeId}", vehicleTypeId);
|
||||
return NotFound(CreateErrorResponse(ex.Message, "VEHICLE_TYPE_NOT_FOUND"));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Delete vehicle type
|
||||
/// </summary>
|
||||
/// <param name="vehicleTypeId">Vehicle type database ID</param>
|
||||
/// <returns>No content on success</returns>
|
||||
[HttpDelete("{vehicleTypeId}")]
|
||||
[ProducesResponseType(204)]
|
||||
[ProducesResponseType(404)]
|
||||
[ProducesResponseType(400)]
|
||||
public async Task<IActionResult> DeleteVehicleType(Guid vehicleTypeId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var deleted = await _vehicleTypeService.DeleteAsync(vehicleTypeId);
|
||||
|
||||
if (!deleted)
|
||||
{
|
||||
return NotFound(CreateErrorResponse(
|
||||
$"Vehicle type with ID '{vehicleTypeId}' not found",
|
||||
"VEHICLE_TYPE_NOT_FOUND"));
|
||||
}
|
||||
|
||||
return NoContent();
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
if (_logger.IsEnabled(LogLevel.Warning)) _logger.LogWarning(ex, "Failed to delete vehicle type: {VehicleTypeId}", vehicleTypeId);
|
||||
|
||||
var errorCode = ex.Message.Contains("referenced")
|
||||
? "VEHICLE_TYPE_IN_USE"
|
||||
: "VALIDATION_ERROR";
|
||||
|
||||
var details = new Dictionary<string, object>();
|
||||
if (errorCode == "VEHICLE_TYPE_IN_USE")
|
||||
{
|
||||
// Try to get usage info for details
|
||||
try
|
||||
{
|
||||
var usageInfo = await _vehicleTypeService.GetUsageInfoAsync(vehicleTypeId);
|
||||
details["nodePropertiesCount"] = usageInfo.NodePropertiesCount;
|
||||
details["edgePropertiesCount"] = usageInfo.EdgePropertiesCount;
|
||||
details["totalUsageCount"] = usageInfo.TotalUsageCount;
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore if we can't get usage info
|
||||
}
|
||||
}
|
||||
|
||||
return BadRequest(CreateErrorResponse(ex.Message, errorCode, details));
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to map entity to DTO
|
||||
private static VehicleTypeDto MapToDto(Data.VehicleType vehicleType)
|
||||
{
|
||||
return new VehicleTypeDto
|
||||
{
|
||||
Id = vehicleType.Id,
|
||||
VehicleTypeId = vehicleType.VehicleTypeId,
|
||||
VehicleTypeName = vehicleType.VehicleTypeName,
|
||||
Description = vehicleType.Description,
|
||||
Specifications = vehicleType.Specifications,
|
||||
Actions = vehicleType.Actions,
|
||||
IsActive = vehicleType.IsActive,
|
||||
CreatedDate = vehicleType.CreatedDate
|
||||
};
|
||||
}
|
||||
|
||||
// Helper method to map usage info to DTO
|
||||
private static VehicleTypeUsageInfoDto MapUsageInfoToDto(VehicleTypeUsageInfo usageInfo)
|
||||
{
|
||||
return new VehicleTypeUsageInfoDto
|
||||
{
|
||||
VehicleTypeId = usageInfo.VehicleTypeId,
|
||||
VehicleTypeIdString = usageInfo.VehicleTypeIdString,
|
||||
VehicleTypeName = usageInfo.VehicleTypeName,
|
||||
NodePropertiesCount = usageInfo.NodePropertiesCount,
|
||||
EdgePropertiesCount = usageInfo.EdgePropertiesCount,
|
||||
TotalUsageCount = usageInfo.TotalUsageCount,
|
||||
CanDelete = usageInfo.CanDelete
|
||||
};
|
||||
}
|
||||
|
||||
// Helper method to create error response
|
||||
private static ErrorResponseDto CreateErrorResponse(
|
||||
string error,
|
||||
string? errorCode = null,
|
||||
Dictionary<string, object>? details = null)
|
||||
{
|
||||
return new ErrorResponseDto
|
||||
{
|
||||
Error = error,
|
||||
ErrorCode = errorCode,
|
||||
Details = details
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user