Feat Widget Tabla de Resultados Por Seccion
This commit is contained in:
		| @@ -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 | ||||
|         }); | ||||
|     } | ||||
| } | ||||
		Reference in New Issue
	
	Block a user