Test Public Side

This commit is contained in:
2025-09-03 13:49:35 -03:00
parent 32e85b9b9d
commit a81f1fe894
33 changed files with 1205 additions and 133 deletions

View File

@@ -63,21 +63,40 @@ public class CatalogosController : ControllerBase
}
[HttpGet("secciones-electorales")]
public async Task<IActionResult> GetSeccionesElectorales()
public async Task<IActionResult> GetSeccionesElectorales([FromQuery] int? categoriaId)
{
var secciones = await _dbContext.AmbitosGeograficos
var seccionesQuery = _dbContext.AmbitosGeograficos
.AsNoTracking()
// Buscamos los ámbitos que son Secciones Electorales (Nivel 20)
.Where(a => a.NivelId == 20 && a.SeccionProvincialId != null)
.Select(a => new MunicipioSimpleDto // Reutilizamos el DTO porque tiene la misma estructura {Id, Nombre}
{
Id = a.SeccionProvincialId!, // El ID que usaremos es el SeccionProvincialId
Nombre = a.Nombre
})
.OrderBy(s => s.Nombre)
.Where(a => a.NivelId == 20); // Nivel 20 = Sección Electoral
// Si NO se proporciona una categoriaId, devolvemos todas las secciones.
if (categoriaId == null)
{
var todasLasSecciones = await seccionesQuery
.OrderBy(a => a.Nombre)
.Select(a => new { Id = a.SeccionProvincialId, a.Nombre })
.ToListAsync();
return Ok(todasLasSecciones);
}
// --- LÓGICA DE FILTRADO ---
// 1. Encontrar las Secciones Provinciales que SÍ tienen resultados para la categoría solicitada.
// Usamos ProyeccionesBancas como fuente de verdad, ya que es el dato más relevante.
var seccionesActivasIds = await _dbContext.ProyeccionesBancas
.AsNoTracking()
.Where(p => p.CategoriaId == categoriaId)
.Select(p => p.AmbitoGeografico.SeccionProvincialId)
.Distinct()
.ToListAsync();
return Ok(secciones);
// 2. Filtramos la lista de secciones.
var seccionesFiltradas = await seccionesQuery
.Where(s => seccionesActivasIds.Contains(s.SeccionProvincialId))
.OrderBy(a => a.Nombre)
.Select(a => new { Id = a.SeccionProvincialId, a.Nombre })
.ToListAsync();
return Ok(seccionesFiltradas);
}
// Nivel 20: Sección Electoral

View File

@@ -531,8 +531,8 @@ public class ResultadosController : ControllerBase
return Ok(configuracionPublica);
}
[HttpGet("concejales/{seccionId}")]
public async Task<IActionResult> GetResultadosConcejalesPorSeccion(string seccionId)
[HttpGet("seccion-resultados/{seccionId}")]
public async Task<IActionResult> GetResultadosAgregadosPorSeccion(string seccionId, [FromQuery] int categoriaId)
{
var municipiosDeLaSeccion = await _dbContext.AmbitosGeograficos
.AsNoTracking()
@@ -548,40 +548,51 @@ public class ResultadosController : ControllerBase
var resultadosMunicipales = await _dbContext.ResultadosVotos
.AsNoTracking()
.Include(r => r.AgrupacionPolitica)
.Where(r => r.CategoriaId == 7 && municipiosDeLaSeccion.Contains(r.AmbitoGeograficoId))
// Usamos la categoriaId del parámetro
.Where(r => r.CategoriaId == categoriaId && municipiosDeLaSeccion.Contains(r.AmbitoGeograficoId))
.ToListAsync();
var logosConcejales = await _dbContext.LogosAgrupacionesCategorias
var logos = await _dbContext.LogosAgrupacionesCategorias
.AsNoTracking()
.Where(l => l.CategoriaId == 7)
// Usamos la categoriaId del parámetro
.Where(l => l.CategoriaId == categoriaId)
.ToDictionaryAsync(l => l.AgrupacionPoliticaId);
var totalVotosSeccion = (decimal)resultadosMunicipales.Sum(r => r.CantidadVotos);
var resultadosFinales = resultadosMunicipales
// 1. Agrupamos por el ID del partido para evitar duplicados.
.GroupBy(r => r.AgrupacionPoliticaId)
.Select(g => new
{
// 2. Obtenemos la entidad completa del primer elemento del grupo.
Agrupacion = g.First().AgrupacionPolitica,
Votos = g.Sum(r => r.CantidadVotos)
})
.OrderByDescending(r => r.Votos)
.Select(r => new
{
Id = r.Agrupacion.Id, // Aseguramos que el Id esté en el objeto final
Id = r.Agrupacion.Id,
r.Agrupacion.Nombre,
r.Agrupacion.NombreCorto,
r.Agrupacion.Color,
LogoUrl = logosConcejales.GetValueOrDefault(r.Agrupacion.Id)?.LogoUrl,
LogoUrl = logos.GetValueOrDefault(r.Agrupacion.Id)?.LogoUrl,
Votos = r.Votos,
// 3. Usamos el nombre de propiedad correcto que el frontend espera: 'votosPorcentaje'
VotosPorcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0
Porcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0
})
.ToList();
return Ok(resultadosFinales);
// Devolvemos un objeto para poder añadir la fecha de actualización
var seccionAmbito = await _dbContext.AmbitosGeograficos.AsNoTracking()
.FirstOrDefaultAsync(a => a.SeccionProvincialId == seccionId && a.NivelId == 20);
var estadoRecuento = seccionAmbito != null
? await _dbContext.EstadosRecuentos.AsNoTracking()
.FirstOrDefaultAsync(e => e.AmbitoGeograficoId == seccionAmbito.Id && e.CategoriaId == categoriaId)
: null;
return Ok(new
{
UltimaActualizacion = estadoRecuento?.FechaTotalizacion ?? DateTime.UtcNow,
Resultados = resultadosFinales
});
}
[HttpGet("mapa-por-seccion")]