// backend/Controllers/AdminController.cs using Dapper; using Inventario.API.Data; using Microsoft.AspNetCore.Mvc; namespace Inventario.API.Controllers { [ApiController] [Route("api/[controller]")] public class AdminController : ControllerBase { private readonly DapperContext _context; public AdminController(DapperContext context) { _context = context; } // DTO para devolver los valores y su conteo public class ComponenteValorDto { public string Valor { get; set; } = ""; public int Conteo { get; set; } } [HttpGet("componentes/{tipo}")] public async Task GetComponenteValores(string tipo) { var allowedTypes = new Dictionary { { "os", "Os" }, { "cpu", "Cpu" }, { "motherboard", "Motherboard" }, { "architecture", "Architecture" } }; if (!allowedTypes.TryGetValue(tipo.ToLower(), out var columnName)) { return BadRequest("Tipo de componente no válido."); } var query = $@" SELECT {columnName} AS Valor, COUNT(*) AS Conteo FROM dbo.equipos WHERE {columnName} IS NOT NULL AND {columnName} != '' GROUP BY {columnName} ORDER BY Conteo DESC, Valor ASC;"; using (var connection = _context.CreateConnection()) { var valores = await connection.QueryAsync(query); return Ok(valores); } } // DTO para la petición de unificación public class UnificarComponenteDto { public required string ValorNuevo { get; set; } public required string ValorAntiguo { get; set; } } [HttpPut("componentes/{tipo}/unificar")] public async Task UnificarComponenteValores(string tipo, [FromBody] UnificarComponenteDto dto) { var allowedTypes = new Dictionary { { "os", "Os" }, { "cpu", "Cpu" }, { "motherboard", "Motherboard" }, { "architecture", "Architecture" } }; if (!allowedTypes.TryGetValue(tipo.ToLower(), out var columnName)) { return BadRequest("Tipo de componente no válido."); } if (dto.ValorAntiguo == dto.ValorNuevo) { return BadRequest("El valor antiguo y el nuevo no pueden ser iguales."); } var query = $@" UPDATE dbo.equipos SET {columnName} = @ValorNuevo WHERE {columnName} = @ValorAntiguo;"; using (var connection = _context.CreateConnection()) { var filasAfectadas = await connection.ExecuteAsync(query, new { dto.ValorNuevo, dto.ValorAntiguo }); return Ok(new { message = $"Se unificaron {filasAfectadas} registros.", filasAfectadas }); } } // DTO para devolver los valores de RAM y su conteo public class RamMaestraDto { public int Id { get; set; } public string? Part_number { get; set; } public string? Fabricante { get; set; } public int Tamano { get; set; } public int? Velocidad { get; set; } public int Conteo { get; set; } } [HttpGet("componentes/ram")] public async Task GetComponentesRam() { var query = @" SELECT mr.Id, mr.part_number as PartNumber, mr.Fabricante, mr.Tamano, mr.Velocidad, COUNT(emr.memoria_ram_id) as Conteo FROM dbo.memorias_ram mr LEFT JOIN dbo.equipos_memorias_ram emr ON mr.id = emr.memoria_ram_id GROUP BY mr.Id, mr.part_number, mr.Fabricante, mr.Tamano, mr.Velocidad ORDER BY Conteo DESC, mr.Fabricante, mr.Tamano;"; using (var connection = _context.CreateConnection()) { var valores = await connection.QueryAsync(query); return Ok(valores); } } [HttpDelete("componentes/ram/{id}")] public async Task BorrarComponenteRam(int id) { using (var connection = _context.CreateConnection()) { // 1. Verificación de seguridad: Asegurarse de que el módulo no esté en uso. var usageQuery = "SELECT COUNT(*) FROM dbo.equipos_memorias_ram WHERE memoria_ram_id = @Id;"; var usageCount = await connection.ExecuteScalarAsync(usageQuery, new { Id = id }); if (usageCount > 0) { return Conflict($"Este módulo de RAM está en uso por {usageCount} equipo(s) y no puede ser eliminado."); } // 2. Si no está en uso, proceder con la eliminación. var deleteQuery = "DELETE FROM dbo.memorias_ram WHERE Id = @Id;"; var filasAfectadas = await connection.ExecuteAsync(deleteQuery, new { Id = id }); if (filasAfectadas == 0) { return NotFound("Módulo de RAM no encontrado."); } return NoContent(); } } [HttpDelete("componentes/{tipo}/{valor}")] public async Task BorrarComponenteTexto(string tipo, string valor) { var allowedTypes = new Dictionary { { "os", "Os" }, { "cpu", "Cpu" }, { "motherboard", "Motherboard" }, { "architecture", "Architecture" } }; if (!allowedTypes.TryGetValue(tipo.ToLower(), out var columnName)) { return BadRequest("Tipo de componente no válido."); } using (var connection = _context.CreateConnection()) { // 1. Verificación de seguridad: Asegurarse de que el valor no esté en uso. var usageQuery = $"SELECT COUNT(*) FROM dbo.equipos WHERE {columnName} = @Valor;"; var usageCount = await connection.ExecuteScalarAsync(usageQuery, new { Valor = valor }); if (usageCount > 0) { return Conflict($"Este valor está en uso por {usageCount} equipo(s) y no puede ser eliminado. Intente unificarlo en su lugar."); } // Esta parte es más conceptual. Un componente de texto no existe en una tabla maestra, // por lo que no hay nada que "eliminar". El hecho de que el conteo sea 0 significa // que ya no existe en la práctica. Devolvemos éxito para confirmar esto. // Si tuviéramos tablas maestras (ej: dbo.sistemas_operativos), aquí iría la consulta DELETE. return NoContent(); } } } }