feat: Implementa lógica completa de sincronización de discos
This commit is contained in:
@@ -259,13 +259,125 @@ namespace Inventario.API.Controllers
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("{hostname}/asociardiscos")]
|
[HttpPost("{hostname}/asociardiscos")]
|
||||||
public async Task<IActionResult> AsociarDiscos(string hostname, [FromBody] List<Disco> discos)
|
public async Task<IActionResult> AsociarDiscos(string hostname, [FromBody] List<Disco> discosDesdeCliente)
|
||||||
{
|
{
|
||||||
// La lógica aquí es compleja, la implementaremos en un paso posterior si es necesaria.
|
// 1. OBTENER EL EQUIPO
|
||||||
// Por ahora, devolvemos un endpoint funcional pero que no hace nada.
|
var equipoQuery = "SELECT * FROM dbo.equipos WHERE Hostname = @Hostname;";
|
||||||
Console.WriteLine($"Recibida solicitud para asociar {discos.Count} discos al equipo {hostname}");
|
using var connection = _context.CreateConnection();
|
||||||
await Task.CompletedTask; // Simula trabajo asíncrono
|
connection.Open();
|
||||||
return Ok(new { message = "Endpoint de asociación de discos recibido, lógica pendiente." });
|
var equipo = await connection.QuerySingleOrDefaultAsync<Equipo>(equipoQuery, new { Hostname = hostname });
|
||||||
|
|
||||||
|
if (equipo == null)
|
||||||
|
{
|
||||||
|
return NotFound("Equipo no encontrado.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iniciar una transacción para asegurar que todas las operaciones se completen o ninguna lo haga.
|
||||||
|
using var transaction = connection.BeginTransaction();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 2. OBTENER ASOCIACIONES Y DISCOS ACTUALES DE LA BD
|
||||||
|
var discosActualesQuery = @"
|
||||||
|
SELECT d.Id, d.Mediatype, d.Size, ed.Id as EquipoDiscoId
|
||||||
|
FROM dbo.equipos_discos ed
|
||||||
|
JOIN dbo.discos d ON ed.disco_id = d.id
|
||||||
|
WHERE ed.equipo_id = @EquipoId;";
|
||||||
|
|
||||||
|
// Creamos una clase anónima temporal para mapear el resultado del JOIN
|
||||||
|
var discosEnDb = (await connection.QueryAsync(discosActualesQuery, new { EquipoId = equipo.Id }, transaction)).Select(d => new
|
||||||
|
{
|
||||||
|
Id = (int)d.Id,
|
||||||
|
Mediatype = (string)d.Mediatype,
|
||||||
|
Size = (int)d.Size,
|
||||||
|
EquipoDiscoId = (int)d.EquipoDiscoId
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
// 3. AGRUPAR Y CONTAR DISCOS (del cliente y de la BD)
|
||||||
|
// Crea un diccionario estilo: {"SSD_256": 2, "HDD_1024": 1}
|
||||||
|
var discosClienteContados = discosDesdeCliente
|
||||||
|
.GroupBy(d => $"{d.Mediatype}_{d.Size}")
|
||||||
|
.ToDictionary(g => g.Key, g => g.Count());
|
||||||
|
|
||||||
|
var discosDbContados = discosEnDb
|
||||||
|
.GroupBy(d => $"{d.Mediatype}_{d.Size}")
|
||||||
|
.ToDictionary(g => g.Key, g => g.Count());
|
||||||
|
|
||||||
|
var cambios = new Dictionary<string, (string anterior, string nuevo)>();
|
||||||
|
|
||||||
|
// 4. CALCULAR Y EJECUTAR ELIMINACIONES
|
||||||
|
var discosAEliminar = new List<int>();
|
||||||
|
foreach (var discoDb in discosEnDb)
|
||||||
|
{
|
||||||
|
var key = $"{discoDb.Mediatype}_{discoDb.Size}";
|
||||||
|
if (discosClienteContados.TryGetValue(key, out int count) && count > 0)
|
||||||
|
{
|
||||||
|
// Este disco todavía existe en el cliente, decrementamos el contador y lo saltamos.
|
||||||
|
discosClienteContados[key]--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Este disco ya no está en el cliente, marcamos su asociación para eliminar.
|
||||||
|
discosAEliminar.Add(discoDb.EquipoDiscoId);
|
||||||
|
|
||||||
|
// Registrar para el historial
|
||||||
|
var nombreDisco = $"Disco {discoDb.Mediatype} {discoDb.Size}GB";
|
||||||
|
var anterior = discosDbContados.GetValueOrDefault(key, 0);
|
||||||
|
if (!cambios.ContainsKey(nombreDisco)) cambios[nombreDisco] = (anterior.ToString(), (anterior - 1).ToString());
|
||||||
|
else cambios[nombreDisco] = (anterior.ToString(), (int.Parse(cambios[nombreDisco].nuevo) - 1).ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (discosAEliminar.Any())
|
||||||
|
{
|
||||||
|
await connection.ExecuteAsync("DELETE FROM dbo.equipos_discos WHERE Id IN @Ids;", new { Ids = discosAEliminar }, transaction);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. CALCULAR Y EJECUTAR INSERCIONES
|
||||||
|
foreach (var discoCliente in discosDesdeCliente)
|
||||||
|
{
|
||||||
|
var key = $"{discoCliente.Mediatype}_{discoCliente.Size}";
|
||||||
|
if (discosDbContados.TryGetValue(key, out int count) && count > 0)
|
||||||
|
{
|
||||||
|
// Este disco ya existía, decrementamos para no volver a añadirlo.
|
||||||
|
discosDbContados[key]--;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Este es un disco nuevo que hay que asociar.
|
||||||
|
var disco = await connection.QuerySingleOrDefaultAsync<Disco>("SELECT * FROM dbo.discos WHERE Mediatype = @Mediatype AND Size = @Size;", discoCliente, transaction);
|
||||||
|
if (disco == null) continue; // Si el disco no existe en la tabla maestra, lo ignoramos
|
||||||
|
|
||||||
|
await connection.ExecuteAsync("INSERT INTO dbo.equipos_discos (equipo_id, disco_id) VALUES (@EquipoId, @DiscoId);", new { EquipoId = equipo.Id, DiscoId = disco.Id }, transaction);
|
||||||
|
|
||||||
|
// Registrar para el historial
|
||||||
|
var nombreDisco = $"Disco {disco.Mediatype} {disco.Size}GB";
|
||||||
|
var anterior = discosDbContados.GetValueOrDefault(key, 0);
|
||||||
|
if (!cambios.ContainsKey(nombreDisco)) cambios[nombreDisco] = (anterior.ToString(), (anterior + 1).ToString());
|
||||||
|
else cambios[nombreDisco] = (anterior.ToString(), (int.Parse(cambios[nombreDisco].nuevo) + 1).ToString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 6. REGISTRAR CAMBIOS Y CONFIRMAR TRANSACCIÓN
|
||||||
|
if (cambios.Count > 0)
|
||||||
|
{
|
||||||
|
// Formateamos los valores para el historial
|
||||||
|
var cambiosFormateados = cambios.ToDictionary(
|
||||||
|
kvp => kvp.Key,
|
||||||
|
kvp => ($"{kvp.Value.anterior} Instalados", $"{kvp.Value.nuevo} Instalados")
|
||||||
|
);
|
||||||
|
await HistorialHelper.RegistrarCambios(_context, equipo.Id, cambiosFormateados);
|
||||||
|
}
|
||||||
|
|
||||||
|
transaction.Commit();
|
||||||
|
|
||||||
|
return Ok(new { message = "Discos sincronizados correctamente." });
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
transaction.Rollback();
|
||||||
|
// Loggear el error en el servidor
|
||||||
|
Console.WriteLine($"Error al asociar discos para {hostname}: {ex.Message}");
|
||||||
|
return StatusCode(500, "Ocurrió un error interno al procesar la solicitud.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpPost("{hostname}/ram")]
|
[HttpPost("{hostname}/ram")]
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Inventario.API")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Inventario.API")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+85bd1915e09fdb3a2af7e28d58b8ba794a9e6360")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+e14476ff8885fa0a5be99dba6f353b305f754677")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Inventario.API")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Inventario.API")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Inventario.API")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Inventario.API")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
Reference in New Issue
Block a user