diff --git a/Elecciones-Web/src/Elecciones.Worker/LowPriorityDataWorker.cs b/Elecciones-Web/src/Elecciones.Worker/LowPriorityDataWorker.cs index 3582405..68429bd 100644 --- a/Elecciones-Web/src/Elecciones.Worker/LowPriorityDataWorker.cs +++ b/Elecciones-Web/src/Elecciones.Worker/LowPriorityDataWorker.cs @@ -196,8 +196,7 @@ public class LowPriorityDataWorker : BackgroundService /// /// Descarga y sincroniza los catálogos base (Categorías, Ámbitos, Agrupaciones) /// desde la API a la base de datos local. Se ejecuta una sola vez al iniciar el worker. - /// Utiliza una estrategia de guardado en lotes para manejar grandes volúmenes de datos - /// sin sobrecargar la base de datos. + /// La sincronización de agrupaciones ahora itera por cada provincia para obtener listas completas. /// /// El token de cancelación para detener la operación. private async Task SincronizarCatalogosMaestrosAsync(CancellationToken stoppingToken) @@ -215,7 +214,7 @@ public class LowPriorityDataWorker : BackgroundService using var scope = _serviceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService(); - // 1. SINCRONIZAR CATEGORÍAS + // --- PASO 1: SINCRONIZAR CATEGORÍAS --- var categoriasApi = await _apiService.GetCategoriasAsync(authToken); if (categoriasApi is null || !categoriasApi.Any()) { @@ -234,38 +233,7 @@ public class LowPriorityDataWorker : BackgroundService await dbContext.SaveChangesAsync(stoppingToken); _logger.LogInformation("Catálogo de Categorías Electorales sincronizado."); - // 2. SINCRONIZAR AGRUPACIONES POLÍTICAS - _logger.LogInformation("Iniciando sincronización de Agrupaciones Políticas..."); - var agrupacionesEnDb = await dbContext.AgrupacionesPoliticas.ToDictionaryAsync(a => a.Id, a => a, stoppingToken); - foreach (var categoria in distinctCategorias) - { - if (stoppingToken.IsCancellationRequested) break; - - // Se pasa 'null' como distritoId para obtener todas las agrupaciones de la categoría. - var agrupacionesApi = await _apiService.GetAgrupacionesAsync(authToken, null, categoria.CategoriaId); - - if (agrupacionesApi != null) - { - foreach (var agrupacionDto in agrupacionesApi) - { - if (!agrupacionesEnDb.ContainsKey(agrupacionDto.IdAgrupacion)) - { - var nuevaAgrupacion = new AgrupacionPolitica - { - Id = agrupacionDto.IdAgrupacion, - IdTelegrama = agrupacionDto.IdAgrupacionTelegrama, - Nombre = agrupacionDto.NombreAgrupacion - }; - dbContext.AgrupacionesPoliticas.Add(nuevaAgrupacion); - agrupacionesEnDb.Add(nuevaAgrupacion.Id, nuevaAgrupacion); // Añadir al diccionario para evitar duplicados en el mismo ciclo - } - } - } - } - int agrupacionesGuardadas = await dbContext.SaveChangesAsync(stoppingToken); - _logger.LogInformation("Catálogo de Agrupaciones Políticas sincronizado. Se guardaron {count} nuevos registros.", agrupacionesGuardadas); - - // 3. SINCRONIZAR ÁMBITOS GEOGRÁFICOS + // --- PASO 2: SINCRONIZAR ÁMBITOS GEOGRÁFICOS --- _logger.LogInformation("Iniciando sincronización de Ámbitos Geográficos..."); var ambitosEnDbKeys = new HashSet( await dbContext.AmbitosGeograficos.Select(a => $"{a.NivelId}|{a.DistritoId}|{a.SeccionProvincialId}|{a.SeccionId}|{a.MunicipioId}|{a.CircuitoId}|{a.EstablecimientoId}|{a.MesaId}").ToListAsync(stoppingToken) @@ -281,7 +249,7 @@ public class LowPriorityDataWorker : BackgroundService foreach (var ambitoDto in catalogoDto.Ambitos) { string claveUnica = $"{ambitoDto.NivelId}|{ambitoDto.CodigoAmbitos.DistritoId}|{ambitoDto.CodigoAmbitos.SeccionProvincialId}|{ambitoDto.CodigoAmbitos.SeccionId}|{ambitoDto.CodigoAmbitos.MunicipioId}|{ambitoDto.CodigoAmbitos.CircuitoId}|{ambitoDto.CodigoAmbitos.EstablecimientoId}|{ambitoDto.CodigoAmbitos.MesaId}"; - if (ambitosEnDbKeys.Add(claveUnica)) // HashSet.Add devuelve true si el elemento no existía + if (ambitosEnDbKeys.Add(claveUnica)) { string nombreCorregido = ambitoDto.Nombre; if (ambitoDto.CodigoAmbitos.DistritoId == "01" && ambitoDto.NivelId == 30 && int.TryParse(ambitoDto.Nombre, out int numeroComuna)) @@ -307,10 +275,68 @@ public class LowPriorityDataWorker : BackgroundService { int ambitosGuardados = await dbContext.SaveChangesAsync(stoppingToken); totalNuevosAmbitos += ambitosGuardados; - _logger.LogInformation("Guardados {count} nuevos ámbitos para la categoría '{catNombre}'.", ambitosGuardados, categoria.Nombre); } } _logger.LogInformation("Catálogo de Ámbitos Geográficos sincronizado. Se guardaron {count} nuevos registros en total.", totalNuevosAmbitos); + + _logger.LogInformation("Iniciando sincronización de Agrupaciones Políticas por provincia y categoría..."); + + // Obtenemos todas las provincias (Nivel 10) que ya sincronizamos. + var provincias = await dbContext.AmbitosGeograficos + .AsNoTracking() + .Where(a => a.NivelId == 10 && a.DistritoId != null) + .ToListAsync(stoppingToken); + + // Definimos las constantes para las categorías y las provincias que renuevan senadores. + const int catDiputadosNac = 3; + const int catSenadoresNac = 2; + var provinciasQueRenuevanSenadores = new HashSet { "01", "06", "08", "15", "16", "17", "22", "24" }; + + var agrupacionesEnDb = await dbContext.AgrupacionesPoliticas.ToDictionaryAsync(a => a.Id, a => a, stoppingToken); + + // Iteramos sobre cada provincia. + foreach (var provincia in provincias) + { + if (stoppingToken.IsCancellationRequested) break; + + // Determinamos qué categorías consultar para esta provincia. + var categoriasParaSondear = new List { catDiputadosNac }; // Todas las provincias eligen diputados. + if (provinciasQueRenuevanSenadores.Contains(provincia.DistritoId!)) + { + categoriasParaSondear.Add(catSenadoresNac); // Solo algunas eligen senadores. + } + + // Iteramos sobre las categorías aplicables para la provincia actual. + foreach (var categoriaId in categoriasParaSondear) + { + _logger.LogDebug("Consultando agrupaciones para {Provincia} ({DistritoId}), Categoría: {CategoriaId}", provincia.Nombre, provincia.DistritoId, categoriaId); + var agrupacionesApi = await _apiService.GetAgrupacionesAsync(authToken, provincia.DistritoId, categoriaId); + + if (agrupacionesApi != null) + { + foreach (var agrupacionDto in agrupacionesApi) + { + // Si la agrupación no está en nuestro diccionario, la añadimos. + if (!agrupacionesEnDb.ContainsKey(agrupacionDto.IdAgrupacion)) + { + var nuevaAgrupacion = new AgrupacionPolitica + { + Id = agrupacionDto.IdAgrupacion, + IdTelegrama = agrupacionDto.IdAgrupacionTelegrama, + Nombre = agrupacionDto.NombreAgrupacion + }; + dbContext.AgrupacionesPoliticas.Add(nuevaAgrupacion); + // La añadimos también al diccionario para no intentar agregarla de nuevo en este ciclo. + agrupacionesEnDb.Add(nuevaAgrupacion.Id, nuevaAgrupacion); + } + } + } + } + } + // Guardamos todos los cambios de agrupaciones al final, en una sola transacción. + int agrupacionesGuardadas = await dbContext.SaveChangesAsync(stoppingToken); + _logger.LogInformation("Catálogo de Agrupaciones Políticas sincronizado. Se guardaron {count} nuevos registros.", agrupacionesGuardadas); + _logger.LogInformation("Sincronización de catálogos maestros finalizada."); } catch (Exception ex)