Feat Se Añade Sondeo Resultados Nivel 50

This commit is contained in:
2025-10-27 17:02:22 -03:00
parent 3a43c4a74a
commit 63cc5ecec8
3 changed files with 38 additions and 11 deletions

View File

@@ -88,18 +88,15 @@ public class ElectoralApiService : IElectoralApiService
return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync<List<AgrupacionDto>>() : null;
}
public async Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string? seccionId, string? municipioId, int categoriaId)
public async Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string? seccionId, string? municipioId, int categoriaId, string? circuitoId = null)
{
using RateLimitLease lease = await _rateLimiter.AcquireAsync(1);
if (!lease.IsAcquired) return null;
var client = _httpClientFactory.CreateClient("ElectoralApiClient");
// Construimos la URL base únicamente con los parámetros obligatorios.
var requestUri = $"/api/resultados/getResultados?distritoId={distritoId}&categoriaId={categoriaId}";
// Añadimos 'seccionId' a la URL SOLO si tiene un valor válido.
// Esto evita que se genere el problemático "&seccionId=" cuando es nulo o vacío.
if (!string.IsNullOrEmpty(seccionId))
{
requestUri += $"&seccionId={seccionId}";
@@ -108,6 +105,10 @@ public class ElectoralApiService : IElectoralApiService
{
requestUri += $"&municipioId={municipioId}";
}
if (!string.IsNullOrEmpty(circuitoId))
{
requestUri += $"&circuitoId={circuitoId}";
}
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
request.Headers.Add("Authorization", $"Bearer {authToken}");

View File

@@ -11,7 +11,7 @@ public interface IElectoralApiService
// Métodos para catálogos
Task<CatalogoDto?> GetCatalogoAmbitosAsync(string authToken, int categoriaId);
Task<List<AgrupacionDto>?> GetAgrupacionesAsync(string authToken, string? distritoId, int categoriaId);
Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string? seccionId, string? municipioId, int categoriaId);
Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string? seccionId, string? municipioId, int categoriaId, string? circuitoId = null);
Task<RepartoBancasDto?> GetBancasAsync(string authToken, string distritoId, string? seccionProvincialId, int categoriaId);
Task<List<string>?> GetTelegramasTotalizadosAsync(string authToken, string distritoId, string seccionId, int? categoriaId = null);
Task<TelegramaFileDto?> GetTelegramaFileAsync(string authToken, string mesaId);

View File

@@ -76,7 +76,7 @@ public class CriticalDataWorker : BackgroundService
var ambitosProvinciales = await dbContext.AmbitosGeograficos.AsNoTracking().Where(a => a.NivelId == 10 && a.DistritoId != null).ToListAsync(stoppingToken);
var ambitoNacional = await dbContext.AmbitosGeograficos.AsNoTracking().FirstOrDefaultAsync(a => a.NivelId == 1 || a.NivelId == 0, stoppingToken);
var categorias = await dbContext.CategoriasElectorales.AsNoTracking().ToListAsync(stoppingToken);
var categorias = await dbContext.CategoriasElectorales.AsNoTracking().Where(c => c.Id == 2 || c.Id == 3).ToListAsync(stoppingToken); // <-- Filtrado para Senadores y Diputados
if (!ambitosProvinciales.Any() || !categorias.Any()) return;
@@ -91,7 +91,6 @@ public class CriticalDataWorker : BackgroundService
var resultadosDto = await _apiService.GetResultadosAsync(authToken, provincia.DistritoId!, null, null, categoria.Id);
if (resultadosDto == null) continue;
// --- Guardar los datos agregados inmediatamente ---
await GuardarDatosAgregadosAsync(dbContext, provincia.Id, categoria.Id, resultadosDto, stoppingToken);
if (DateTime.TryParse(resultadosDto.FechaTotalizacion, out var fechaApi))
@@ -182,19 +181,46 @@ public class CriticalDataWorker : BackgroundService
using var scope = _serviceProvider.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<EleccionesDbContext>();
// 1. Obtenemos todos los municipios Y circuitos de la provincia en consultas eficientes.
var municipiosDeLaProvincia = await dbContext.AmbitosGeograficos
.AsNoTracking()
.Where(a => a.NivelId == 30 && a.DistritoId == distritoId && a.SeccionId != null)
.ToListAsync();
_logger.LogInformation("Iniciando descarga detallada para {Count} municipios del distrito {DistritoId}...", municipiosDeLaProvincia.Count, distritoId);
var circuitosDeLaProvincia = await dbContext.AmbitosGeograficos
.AsNoTracking()
.Where(a => a.NivelId == 50 && a.DistritoId == distritoId && a.SeccionId != null && a.CircuitoId != null)
.ToListAsync();
// 2. Agrupamos los circuitos por el SeccionId (ID del municipio) para una búsqueda rápida.
var circuitosPorMunicipio = circuitosDeLaProvincia
.GroupBy(c => c.SeccionId)
.ToDictionary(g => g.Key!, g => g.ToList());
_logger.LogInformation("Iniciando descarga detallada para {Count} municipios y {CircuitCount} circuitos del distrito {DistritoId}...",
municipiosDeLaProvincia.Count, circuitosDeLaProvincia.Count, distritoId);
foreach (var municipio in municipiosDeLaProvincia)
{
var resultados = await _apiService.GetResultadosAsync(authToken, municipio.DistritoId!, municipio.SeccionId!, null, categoriaId);
if (resultados != null)
// 3. Descargamos y guardamos los resultados a nivel de municipio (como antes).
var resultadosMunicipio = await _apiService.GetResultadosAsync(authToken, municipio.DistritoId!, municipio.SeccionId!, null, categoriaId);
if (resultadosMunicipio != null)
{
await GuardarResultadosDeAmbitoAsync(dbContext, municipio.Id, categoriaId, resultados, CancellationToken.None);
await GuardarResultadosDeAmbitoAsync(dbContext, municipio.Id, categoriaId, resultadosMunicipio, CancellationToken.None);
}
// 4. Buscamos y recorremos los circuitos de este municipio.
if (circuitosPorMunicipio.TryGetValue(municipio.SeccionId!, out var circuitos))
{
foreach (var circuito in circuitos)
{
// 5. Llamamos a la API con el circuitoId y guardamos los resultados.
var resultadosCircuito = await _apiService.GetResultadosAsync(authToken, circuito.DistritoId!, circuito.SeccionId!, null, categoriaId, circuito.CircuitoId!);
if (resultadosCircuito != null)
{
await GuardarResultadosDeAmbitoAsync(dbContext, circuito.Id, categoriaId, resultadosCircuito, CancellationToken.None);
}
}
}
}