feat: Controladores con operaciones CRUD completas
This commit is contained in:
205
backend/Controllers/EquiposController.cs
Normal file
205
backend/Controllers/EquiposController.cs
Normal file
@@ -0,0 +1,205 @@
|
||||
using Dapper;
|
||||
using Inventario.API.Data;
|
||||
using Inventario.API.Helpers;
|
||||
using Inventario.API.Models;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
namespace Inventario.API.Controllers
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class EquiposController : ControllerBase
|
||||
{
|
||||
private readonly DapperContext _context;
|
||||
|
||||
public EquiposController(DapperContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// --- GET /api/equipos ---
|
||||
// Consulta todos los equipos con sus relaciones
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> Consultar()
|
||||
{
|
||||
// Query para traer todo en una sola llamada a la BD
|
||||
var query = @"
|
||||
SELECT
|
||||
e.*,
|
||||
s.Id as SectorId, s.Nombre as SectorNombre,
|
||||
u.Id as UsuarioId, u.Username, u.Password,
|
||||
d.Id as DiscoId, d.Mediatype, d.Size,
|
||||
mr.Id as MemoriaRamId, mr.part_number as PartNumber, mr.Fabricante, mr.Tamano, mr.Velocidad, emr.Slot
|
||||
FROM dbo.equipos e
|
||||
LEFT JOIN dbo.sectores s ON e.sector_id = s.id
|
||||
LEFT JOIN dbo.usuarios_equipos ue ON e.id = ue.equipo_id
|
||||
LEFT JOIN dbo.usuarios u ON ue.usuario_id = u.id
|
||||
LEFT JOIN dbo.equipos_discos ed ON e.id = ed.equipo_id
|
||||
LEFT JOIN dbo.discos d ON ed.disco_id = d.id
|
||||
LEFT JOIN dbo.equipos_memorias_ram emr ON e.id = emr.equipo_id
|
||||
LEFT JOIN dbo.memorias_ram mr ON emr.memoria_ram_id = mr.id;";
|
||||
|
||||
using (var connection = _context.CreateConnection())
|
||||
{
|
||||
var equipoDict = new Dictionary<int, Equipo>();
|
||||
|
||||
await connection.QueryAsync<Equipo, Sector, Usuario, Disco, MemoriaRamDetalle, Equipo>(
|
||||
query, (equipo, sector, usuario, disco, memoria) =>
|
||||
{
|
||||
if (!equipoDict.TryGetValue(equipo.Id, out var equipoActual))
|
||||
{
|
||||
equipoActual = equipo;
|
||||
equipoActual.Sector = sector;
|
||||
equipoDict.Add(equipoActual.Id, equipoActual);
|
||||
}
|
||||
if (usuario != null && !equipoActual.Usuarios.Any(u => u.Id == usuario.Id))
|
||||
equipoActual.Usuarios.Add(usuario);
|
||||
if (disco != null && !equipoActual.Discos.Any(d => d.Id == disco.Id))
|
||||
equipoActual.Discos.Add(disco);
|
||||
if (memoria != null && !equipoActual.MemoriasRam.Any(m => m.Id == memoria.Id && m.Slot == memoria.Slot))
|
||||
equipoActual.MemoriasRam.Add(memoria);
|
||||
|
||||
return equipoActual;
|
||||
},
|
||||
splitOn: "SectorId,UsuarioId,DiscoId,MemoriaRamId"
|
||||
);
|
||||
return Ok(equipoDict.Values);
|
||||
}
|
||||
}
|
||||
|
||||
// --- GET /api/equipos/{hostname} ---
|
||||
[HttpGet("{hostname}")]
|
||||
public async Task<IActionResult> ConsultarDetalle(string hostname)
|
||||
{
|
||||
var query = @"SELECT
|
||||
e.*,
|
||||
s.Id as SectorId, s.Nombre as SectorNombre,
|
||||
u.Id as UsuarioId, u.Username, u.Password
|
||||
FROM dbo.equipos e
|
||||
LEFT JOIN dbo.sectores s ON e.sector_id = s.id
|
||||
LEFT JOIN dbo.usuarios_equipos ue ON e.id = ue.equipo_id
|
||||
LEFT JOIN dbo.usuarios u ON ue.usuario_id = u.id
|
||||
WHERE e.Hostname = @Hostname;";
|
||||
|
||||
using (var connection = _context.CreateConnection())
|
||||
{
|
||||
var equipoDict = new Dictionary<int, Equipo>();
|
||||
var equipo = (await connection.QueryAsync<Equipo, Sector, Usuario, Equipo>(
|
||||
query, (e, sector, usuario) =>
|
||||
{
|
||||
if (!equipoDict.TryGetValue(e.Id, out var equipoActual))
|
||||
{
|
||||
equipoActual = e;
|
||||
equipoActual.Sector = sector;
|
||||
equipoDict.Add(equipoActual.Id, equipoActual);
|
||||
}
|
||||
if (usuario != null && !equipoActual.Usuarios.Any(u => u.Id == usuario.Id))
|
||||
equipoActual.Usuarios.Add(usuario);
|
||||
|
||||
return equipoActual;
|
||||
},
|
||||
new { Hostname = hostname },
|
||||
splitOn: "SectorId,UsuarioId"
|
||||
)).FirstOrDefault();
|
||||
|
||||
if (equipo == null) return NotFound("Equipo no encontrado.");
|
||||
|
||||
return Ok(equipo);
|
||||
}
|
||||
}
|
||||
|
||||
// --- POST /api/equipos/{hostname} ---
|
||||
[HttpPost("{hostname}")]
|
||||
public async Task<IActionResult> Ingresar(string hostname, [FromBody] Equipo equipoData)
|
||||
{
|
||||
var findQuery = "SELECT * FROM dbo.equipos WHERE Hostname = @Hostname;";
|
||||
|
||||
using (var connection = _context.CreateConnection())
|
||||
{
|
||||
var equipoExistente = await connection.QuerySingleOrDefaultAsync<Equipo>(findQuery, new { Hostname = hostname });
|
||||
|
||||
if (equipoExistente == null)
|
||||
{
|
||||
// Crear
|
||||
var insertQuery = @"INSERT INTO dbo.equipos (Hostname, Ip, Mac, Motherboard, Cpu, Ram_installed, Ram_slots, Os, Architecture)
|
||||
VALUES (@Hostname, @Ip, @Mac, @Motherboard, @Cpu, @Ram_installed, @Ram_slots, @Os, @Architecture);
|
||||
SELECT CAST(SCOPE_IDENTITY() as int);";
|
||||
var nuevoId = await connection.ExecuteScalarAsync<int>(insertQuery, equipoData);
|
||||
equipoData.Id = nuevoId;
|
||||
return CreatedAtAction(nameof(ConsultarDetalle), new { hostname = equipoData.Hostname }, equipoData);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Actualizar y registrar historial
|
||||
var cambios = new Dictionary<string, (string anterior, string nuevo)>();
|
||||
|
||||
// Comparamos campos para registrar en historial
|
||||
if (equipoData.Ip != equipoExistente.Ip) cambios["ip"] = (equipoExistente.Ip, equipoData.Ip);
|
||||
if (equipoData.Mac != equipoExistente.Mac) cambios["mac"] = (equipoExistente.Mac ?? "", equipoData.Mac ?? "");
|
||||
|
||||
var updateQuery = @"UPDATE dbo.equipos SET Ip = @Ip, Mac = @Mac, Motherboard = @Motherboard,
|
||||
Cpu = @Cpu, Ram_installed = @Ram_installed, Ram_slots = @Ram_slots, Os = @Os, Architecture = @Architecture
|
||||
WHERE Hostname = @Hostname;";
|
||||
await connection.ExecuteAsync(updateQuery, equipoData);
|
||||
|
||||
if (cambios.Count > 0)
|
||||
{
|
||||
await HistorialHelper.RegistrarCambios(_context, equipoExistente.Id, cambios);
|
||||
}
|
||||
|
||||
return Ok(equipoData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// --- PUT /api/equipos/{id} ---
|
||||
[HttpPut("{id}")]
|
||||
public async Task<IActionResult> Actualizar(int id, [FromBody] Equipo equipoData)
|
||||
{
|
||||
var updateQuery = @"UPDATE dbo.equipos SET Hostname = @Hostname, Ip = @Ip, Mac = @Mac, Motherboard = @Motherboard,
|
||||
Cpu = @Cpu, Ram_installed = @Ram_installed, Ram_slots = @Ram_slots, Os = @Os, Architecture = @Architecture
|
||||
WHERE Id = @Id;";
|
||||
using (var connection = _context.CreateConnection())
|
||||
{
|
||||
// Asignamos el ID del parámetro de la ruta al objeto que recibimos.
|
||||
equipoData.Id = id;
|
||||
// Ahora pasamos el objeto completo a Dapper.
|
||||
var filasAfectadas = await connection.ExecuteAsync(updateQuery, equipoData);
|
||||
if (filasAfectadas == 0) return NotFound("Equipo no encontrado.");
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
|
||||
// --- DELETE /api/equipos/{id} ---
|
||||
[HttpDelete("{id}")]
|
||||
public async Task<IActionResult> Borrar(int id)
|
||||
{
|
||||
// La base de datos está configurada con ON DELETE CASCADE, por lo que las relaciones se borrarán automáticamente.
|
||||
var query = "DELETE FROM dbo.equipos WHERE Id = @Id;";
|
||||
using (var connection = _context.CreateConnection())
|
||||
{
|
||||
var filasAfectadas = await connection.ExecuteAsync(query, new { Id = id });
|
||||
if (filasAfectadas == 0) return NotFound("Equipo no encontrado.");
|
||||
return NoContent();
|
||||
}
|
||||
}
|
||||
|
||||
// --- GET /api/equipos/{hostname}/historial ---
|
||||
[HttpGet("{hostname}/historial")]
|
||||
public async Task<IActionResult> ConsultarHistorial(string hostname)
|
||||
{
|
||||
var query = @"SELECT h.* FROM dbo.historial_equipos h
|
||||
JOIN dbo.equipos e ON h.equipo_id = e.id
|
||||
WHERE e.Hostname = @Hostname
|
||||
ORDER BY h.fecha_cambio DESC;";
|
||||
using (var connection = _context.CreateConnection())
|
||||
{
|
||||
var equipo = await connection.QueryFirstOrDefaultAsync<Equipo>("SELECT Id FROM dbo.equipos WHERE Hostname = @Hostname", new { Hostname = hostname });
|
||||
if (equipo == null) return NotFound("Equipo no encontrado.");
|
||||
|
||||
var historial = await connection.QueryAsync<HistorialEquipo>(query, new { Hostname = hostname });
|
||||
return Ok(new { equipo = hostname, historial });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user