diff --git a/Elecciones-Web/src/Elecciones.Infrastructure/Services/ElectoralApiService.cs b/Elecciones-Web/src/Elecciones.Infrastructure/Services/ElectoralApiService.cs index 79f242e..041794c 100644 --- a/Elecciones-Web/src/Elecciones.Infrastructure/Services/ElectoralApiService.cs +++ b/Elecciones-Web/src/Elecciones.Infrastructure/Services/ElectoralApiService.cs @@ -40,7 +40,7 @@ public class ElectoralApiService : IElectoralApiService : null; } - public async Task?> GetCatalogoAmbitosAsync(string authToken, int categoriaId) + public async Task GetCatalogoAmbitosAsync(string authToken, int categoriaId) { var client = _httpClientFactory.CreateClient("ElectoralApiClient"); var request = new HttpRequestMessage(HttpMethod.Get, $"/api/catalogo/getCatalogo?categoriaId={categoriaId}"); @@ -48,7 +48,7 @@ public class ElectoralApiService : IElectoralApiService var response = await client.SendAsync(request); return response.IsSuccessStatusCode - ? await response.Content.ReadFromJsonAsync>() + ? await response.Content.ReadFromJsonAsync() : null; } diff --git a/Elecciones-Web/src/Elecciones.Infrastructure/Services/IElectoralApiService.cs b/Elecciones-Web/src/Elecciones.Infrastructure/Services/IElectoralApiService.cs index ea06127..658bb39 100644 --- a/Elecciones-Web/src/Elecciones.Infrastructure/Services/IElectoralApiService.cs +++ b/Elecciones-Web/src/Elecciones.Infrastructure/Services/IElectoralApiService.cs @@ -10,10 +10,8 @@ public interface IElectoralApiService Task GetAuthTokenAsync(); // Métodos para catálogos - Task?> GetCatalogoAmbitosAsync(string authToken, int categoriaId); + Task GetCatalogoAmbitosAsync(string authToken, int categoriaId); Task?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId); - - // Métodos para resultados y datos dinámicos Task GetResultadosAsync(string authToken, string distritoId, string seccionId, string municipioId); Task GetBancasAsync(string authToken, string distritoId, string seccionId); Task?> GetTelegramasTotalizadosAsync(string authToken, string distritoId, string seccionId); diff --git a/Elecciones-Web/src/Elecciones.Worker/Worker.cs b/Elecciones-Web/src/Elecciones.Worker/Worker.cs index 8981d9e..0449b3f 100644 --- a/Elecciones-Web/src/Elecciones.Worker/Worker.cs +++ b/Elecciones-Web/src/Elecciones.Worker/Worker.cs @@ -170,11 +170,11 @@ public class Worker : BackgroundService using var scope = _serviceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService(); - // --- 1. OBTENEMOS LA LISTA COMPLETA DE CATEGORÍAS DISPONIBLES --- + // --- 1. SINCRONIZAR CATEGORÍAS --- var categoriasApi = await _apiService.GetCategoriasAsync(_authToken); if (categoriasApi is null || !categoriasApi.Any()) { - _logger.LogWarning("No se recibieron datos del catálogo de Categorías. No se puede continuar."); + _logger.LogWarning("No se recibieron datos del catálogo de Categorías. No se puede continuar con la sincronización."); return; } @@ -186,17 +186,18 @@ public class Worker : BackgroundService _logger.LogInformation("Se procesarán {count} categorías electorales.", distinctCategorias.Count); - // --- 2. GUARDAMOS/ACTUALIZAMOS LAS CATEGORÍAS EN LA BD --- var categoriasEnDb = await dbContext.CategoriasElectorales.ToDictionaryAsync(c => c.Id, c => c, stoppingToken); foreach (var categoriaDto in distinctCategorias) { if (categoriasEnDb.TryGetValue(categoriaDto.CategoriaId, out var categoriaExistente)) { + // Actualizar por si cambia el nombre o el orden categoriaExistente.Nombre = categoriaDto.Nombre; categoriaExistente.Orden = categoriaDto.Orden; } else { + // Añadir nueva categoría dbContext.CategoriasElectorales.Add(new CategoriaElectoral { Id = categoriaDto.CategoriaId, @@ -206,26 +207,81 @@ public class Worker : BackgroundService } } - // --- 3. ITERAMOS SOBRE CADA CATEGORÍA PARA DESCARGAR EL RESTO DE CATÁLOGOS --- + // --- 2. ITERAR PARA SINCRONIZAR ÁMBITOS Y AGRUPACIONES --- foreach (var categoria in distinctCategorias) { if (stoppingToken.IsCancellationRequested) break; _logger.LogInformation("--- Sincronizando Ámbitos y Agrupaciones para la categoría: {Nombre} (ID: {Id}) ---", categoria.Nombre, categoria.CategoriaId); - var catalogoAmbitosApi = await _apiService.GetCatalogoAmbitosAsync(_authToken, categoria.CategoriaId); - if (catalogoAmbitosApi != null && catalogoAmbitosApi.Any()) + var catalogoDto = await _apiService.GetCatalogoAmbitosAsync(_authToken, categoria.CategoriaId); + if (catalogoDto != null) { - // La lógica para procesar ámbitos y agrupaciones irá aquí... - // Por ahora, se saltará debido a los errores 400 de la API. - _logger.LogInformation("Catálogo de Ámbitos para la categoría {Id} obtenido con éxito.", categoria.CategoriaId); + // SINCRONIZAR ÁMBITOS + // Usamos una clave compuesta para identificar unívocamente cada ámbito geográfico + var ambitosEnDb = await dbContext.AmbitosGeograficos.ToDictionaryAsync(a => (a.DistritoId, a.SeccionId, a.MunicipioId), a => a, stoppingToken); + foreach (var ambitoDto in catalogoDto.Ambitos) + { + var claveUnica = (ambitoDto.CodigoAmbitos.DistritoId, ambitoDto.CodigoAmbitos.SeccionId, ambitoDto.CodigoAmbitos.MunicipioId); + if (ambitosEnDb.TryGetValue(claveUnica, out var ambitoExistente)) + { + // Actualizar datos descriptivos + ambitoExistente.Nombre = ambitoDto.Nombre; + ambitoExistente.NivelId = ambitoDto.NivelId; + } + else + { + // Añadir nuevo ámbito + dbContext.AmbitosGeograficos.Add(new AmbitoGeografico + { + Nombre = ambitoDto.Nombre, + NivelId = ambitoDto.NivelId, + DistritoId = ambitoDto.CodigoAmbitos.DistritoId, + SeccionId = ambitoDto.CodigoAmbitos.SeccionId, + MunicipioId = ambitoDto.CodigoAmbitos.MunicipioId, + SeccionProvincialId = ambitoDto.CodigoAmbitos.SeccionProvincialId + }); + } + } + _logger.LogInformation("Sincronización de Ámbitos Geográficos completada para la categoría actual."); + + // SINCRONIZAR AGRUPACIONES + var provincia = catalogoDto.Ambitos.FirstOrDefault(a => a.NivelId == 10); + if (provincia != null && provincia.CodigoAmbitos.DistritoId != null) + { + var agrupacionesApi = await _apiService.GetAgrupacionesAsync(_authToken, provincia.CodigoAmbitos.DistritoId, categoria.CategoriaId); + if (agrupacionesApi != null && agrupacionesApi.Any()) + { + var agrupacionesEnDb = await dbContext.AgrupacionesPoliticas.ToDictionaryAsync(a => a.Id, a => a, stoppingToken); + foreach (var agrupacionDto in agrupacionesApi) + { + if (agrupacionesEnDb.TryGetValue(agrupacionDto.IdAgrupacion, out var agrupacionExistente)) + { + // Actualizar datos descriptivos + agrupacionExistente.Nombre = agrupacionDto.NombreAgrupacion; + agrupacionExistente.IdTelegrama = agrupacionDto.IdAgrupacionTelegrama; + } + else + { + // Añadir nueva agrupación + dbContext.AgrupacionesPoliticas.Add(new AgrupacionPolitica + { + Id = agrupacionDto.IdAgrupacion, + IdTelegrama = agrupacionDto.IdAgrupacionTelegrama, + Nombre = agrupacionDto.NombreAgrupacion + }); + } + } + _logger.LogInformation("Sincronización de Agrupaciones Políticas completada para la categoría actual."); + } + } } else { - _logger.LogWarning("No se recibieron datos del catálogo de Ámbitos para la categoría {Id} (Respuesta: 400 Bad Request).", categoria.CategoriaId); + _logger.LogWarning("No se recibieron datos del catálogo de Ámbitos para la categoría {Id}.", categoria.CategoriaId); } } - // --- 4. GUARDADO FINAL --- + // --- 3. GUARDADO FINAL --- int cambiosGuardados = await dbContext.SaveChangesAsync(stoppingToken); _logger.LogInformation("{count} cambios totales en los catálogos han sido guardados en la base de datos.", cambiosGuardados); _logger.LogInformation("Sincronización de catálogos maestros finalizada.");