Feat Se Añade Sondeo Resultados Nivel 50
This commit is contained in:
		| @@ -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}"); | ||||
|   | ||||
| @@ -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); | ||||
|   | ||||
| @@ -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); | ||||
|             } | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user