Files
Denso/srcs/RobotNet10/Commons/RobotNet10.MapManager/Controllers/VehiclesManagerController.cs
2026-07-03 16:31:37 +07:00

307 lines
11 KiB
C#

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
};
}
}