Feat Widget Tabla de Resultados Por Seccion

This commit is contained in:
2025-09-04 14:35:12 -03:00
parent ff6c2f29e7
commit f41b4eaa1c
14 changed files with 475 additions and 10 deletions

View File

@@ -773,4 +773,105 @@ public class ResultadosController : ControllerBase
return Ok(resultado);
}
// En src/Elecciones.Api/Controllers/ResultadosController.cs
[HttpGet("tabla-ranking-seccion/{seccionId}")]
public async Task<IActionResult> GetTablaRankingPorSeccion(string seccionId)
{
// 1. Obtener los ámbitos de los municipios de la sección
var municipios = await _dbContext.AmbitosGeograficos.AsNoTracking()
.Where(a => a.NivelId == 30 && a.SeccionProvincialId == seccionId)
.OrderBy(a => a.Nombre).Select(a => new { a.Id, a.Nombre }).ToListAsync();
if (!municipios.Any())
{
return Ok(new
{
Categorias = new List<object>(),
PartidosPrincipales = new Dictionary<int, List<object>>(),
ResultadosPorMunicipio = new List<object>()
});
}
var municipiosIds = municipios.Select(m => m.Id).ToList();
// 2. Obtener todos los resultados de votos para esos municipios en una sola consulta
var resultadosCrudos = await _dbContext.ResultadosVotos.AsNoTracking()
.Include(r => r.AgrupacionPolitica)
.Where(r => municipiosIds.Contains(r.AmbitoGeograficoId))
.ToListAsync();
var categoriasMap = await _dbContext.CategoriasElectorales.AsNoTracking().ToDictionaryAsync(c => c.Id);
// 3. Determinar las categorías activas en la sección
var categoriasActivas = resultadosCrudos.Select(r => r.CategoriaId).Distinct()
.Select(id => categoriasMap.GetValueOrDefault(id)).Where(c => c != null)
.OrderBy(c => c!.Orden).Select(c => new { c!.Id, c.Nombre }).ToList();
// 4. Determinar los 2 partidos principales POR CATEGORÍA a nivel SECCIÓN
var partidosPorCategoria = categoriasActivas.ToDictionary(
c => c.Id,
c =>
{
var resultadosCategoriaSeccion = resultadosCrudos.Where(r => r.CategoriaId == c.Id);
var totalVotosSeccionCategoria = (decimal)resultadosCategoriaSeccion.Sum(r => r.CantidadVotos);
return resultadosCategoriaSeccion
// --- CAMBIO CLAVE: Agrupamos por el ID (string), no por el objeto ---
.GroupBy(r => r.AgrupacionPolitica.Id)
.Select(g => new
{
// g.Key ahora es el AgrupacionPoliticaId
// Tomamos la entidad completa del primer elemento del grupo
Agrupacion = g.First().AgrupacionPolitica,
TotalVotos = g.Sum(r => r.CantidadVotos)
})
.OrderByDescending(x => x.TotalVotos)
.Take(2)
.Select((x, index) => new
{
Puesto = index + 1,
x.Agrupacion.Id,
Nombre = x.Agrupacion.NombreCorto ?? x.Agrupacion.Nombre,
PorcentajeTotalSeccion = totalVotosSeccionCategoria > 0 ? (x.TotalVotos / totalVotosSeccionCategoria) * 100 : 0
})
.ToList();
}
);
// 5. Construir los datos para las filas de la tabla (resultados por municipio)
var resultadosPorMunicipio = municipios.Select(municipio =>
{
var resultadosDelMunicipio = resultadosCrudos.Where(r => r.AmbitoGeograficoId == municipio.Id);
var celdas = resultadosDelMunicipio
.GroupBy(r => r.CategoriaId)
.ToDictionary(
g => g.Key, // CategoriaId
g =>
{
var totalVotosMunicipioCategoria = (decimal)g.Sum(r => r.CantidadVotos);
return g.ToDictionary(
r => r.AgrupacionPoliticaId, // PartidoId
r => totalVotosMunicipioCategoria > 0 ? (r.CantidadVotos / totalVotosMunicipioCategoria) * 100 : 0
);
}
);
return new
{
MunicipioId = municipio.Id,
MunicipioNombre = municipio.Nombre,
Celdas = celdas
};
}).ToList();
return Ok(new
{
Categorias = categoriasActivas,
PartidosPorCategoria = partidosPorCategoria,
ResultadosPorMunicipio = resultadosPorMunicipio
});
}
}