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

181 lines
6.1 KiB
C#

using Microsoft.EntityFrameworkCore;
using RobotNet10.MapEditor.Shared.DTOs.Requests;
using RobotNet10.MapManager.Data;
namespace RobotNet10.MapManager.Services;
/// <summary>
/// Service implementation for managing stations
/// </summary>
public class StationService(MapDbContext context) : IStationService
{
private readonly MapDbContext _context = context;
public async Task<Station> CreateAsync(CreateStationRequest request)
{
// Check if station ID already exists in this level
var exists = await _context.Stations
.AnyAsync(s => s.LevelId == request.LayoutLevelId && s.StationId == request.StationId);
if (exists)
{
throw new InvalidOperationException(
$"Station with ID '{request.StationId}' already exists in this layout level");
}
using var transaction = await _context.Database.BeginTransactionAsync();
try
{
var station = new Station
{
LevelId = request.LayoutLevelId,
StationId = request.StationId,
StationName = request.StationName,
StationDescription = request.StationDescription,
StationHeight = request.StationHeight,
X = request.X,
Y = request.Y,
Theta = request.Theta
};
_context.Stations.Add(station);
await _context.SaveChangesAsync();
// Add interaction nodes if provided
if (request.InteractionNodeIds != null && request.InteractionNodeIds.Count != 0)
{
foreach (var nodeId in request.InteractionNodeIds)
{
var interactionNode = new StationInteractionNode
{
StationId = station.Id,
NodeId = nodeId
};
_context.StationInteractionNodes.Add(interactionNode);
}
await _context.SaveChangesAsync();
}
await transaction.CommitAsync();
// Reload with interaction nodes
return (await GetByIdAsync(station.Id, includeInteractionNodes: true))!;
}
catch
{
await transaction.RollbackAsync();
throw;
}
}
public async Task<List<Station>> GetStationsByLevelAsync(Guid layoutLevelId, bool includeInteractionNodes = true)
{
var query = _context.Stations.Where(s => s.LevelId == layoutLevelId);
if (includeInteractionNodes)
{
query = query
.Include(s => s.InteractionNodes)
.ThenInclude(sin => sin.Node);
}
return await query.OrderBy(s => s.StationId).ToListAsync();
}
public async Task<Station?> GetByIdAsync(Guid stationId, bool includeInteractionNodes = true)
{
var query = _context.Stations.Where(s => s.Id == stationId);
if (includeInteractionNodes)
{
query = query
.Include(s => s.InteractionNodes)
.ThenInclude(sin => sin.Node)
.ThenInclude(n => n.VehicleProperties);
}
return await query.FirstOrDefaultAsync();
}
public async Task<Station> UpdateAsync(Guid stationId, UpdateStationRequest request)
{
var station = await GetByIdAsync(stationId, includeInteractionNodes: true) ??
throw new InvalidOperationException($"Station with ID '{stationId}' not found");
// Update properties
if (request.StationName != null)
station.StationName = request.StationName;
if (request.StationDescription != null)
station.StationDescription = request.StationDescription;
if (request.StationHeight.HasValue)
station.StationHeight = request.StationHeight.Value;
if (request.X.HasValue)
station.X = request.X.Value;
if (request.Y.HasValue)
station.Y = request.Y.Value;
if (request.Theta.HasValue)
station.Theta = request.Theta.Value;
// Update interaction nodes if provided
if (request.InteractionNodeIds != null)
{
// Remove existing interaction nodes
var existingInteractionNodes = await _context.StationInteractionNodes
.Where(sin => sin.StationId == stationId)
.ToListAsync();
_context.StationInteractionNodes.RemoveRange(existingInteractionNodes);
// Add new interaction nodes
foreach (var nodeId in request.InteractionNodeIds)
{
// Verify node exists
var nodeExists = await _context.Nodes.AnyAsync(n => n.Id == nodeId);
if (!nodeExists)
{
throw new InvalidOperationException($"Node with ID '{nodeId}' not found");
}
var interactionNode = new StationInteractionNode
{
StationId = stationId,
NodeId = nodeId
};
_context.StationInteractionNodes.Add(interactionNode);
}
}
await _context.SaveChangesAsync();
// Reload with interaction nodes
return (await GetByIdAsync(stationId, includeInteractionNodes: true))!;
}
public async Task<bool> DeleteAsync(Guid stationId)
{
var station = await GetByIdAsync(stationId, includeInteractionNodes: false);
if (station == null)
{
return false;
}
// Delete interaction nodes (cascade will handle this, but explicit for clarity)
var interactionNodes = await _context.StationInteractionNodes
.Where(sin => sin.StationId == stationId)
.ToListAsync();
_context.StationInteractionNodes.RemoveRange(interactionNodes);
// Delete station
_context.Stations.Remove(station);
await _context.SaveChangesAsync();
return true;
}
}