From 316f49f25b8be2bcfed57bcab8c5228843045a43 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Tue, 14 Oct 2025 16:00:55 -0300 Subject: [PATCH] =?UTF-8?q?feat(Worker):=20Adaptaci=C3=B3n=20integral=20pa?= =?UTF-8?q?ra=20la=20API=20de=20Elecciones=20Nacionales?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Este commit refactoriza por completo el sistema de recolección de datos para asegurar la compatibilidad con la nueva API nacional, pasando de un modelo de distrito único a uno multi-distrito. Cambios principales: - **Refactorización de `SondearResumenProvincialAsync`:** - Se elimina la dependencia del endpoint obsoleto `/getResumen`. - El método ahora itera sobre todas las provincias (`NivelId=10`) y categorías, utilizando `GetResultadosAsync` para obtener los datos agregados. - **Expansión de `SondearResultadosMunicipalesAsync`:** - Se renombra a `SondearResultadosPorAmbitosAsync` para reflejar su nueva responsabilidad. - La lógica ahora sondea múltiples niveles jerárquicos (`NivelId` 10, 20, 30), capturando resultados detallados para Provincias, Secciones Electorales y Municipios. - **Modificación del Modelo de Datos:** - Se añade la columna `CategoriaId` a la entidad y tabla `ResumenVoto`. - Se crea la migración de base de datos `AddCategoriaIdToResumenVoto` para aplicar el cambio. - **Ajustes de Nulabilidad en API Service:** - Se actualizan las firmas de `GetResultadosAsync` en `IElectoralApiService` y `ElectoralApiService` para permitir que `seccionId` y `municipioId` sean nulables (`string?`), resolviendo errores de compilación CS8625. - **Deshabilitación de Seeders de Ejemplo:** - Se introduce una bandera `generarDatosDeEjemplo` en `Program.cs` de la API, establecida en `false`, para prevenir la ejecución de código de simulación en entornos de producción o pruebas. --- Elecciones-Web/src/Elecciones.Api/Program.cs | 284 +++---- .../net9.0/Elecciones.Api.AssemblyInfo.cs | 2 +- .../Debug/net9.0/rjsmcshtml.dswa.cache.json | 2 +- .../Debug/net9.0/rjsmrazor.dswa.cache.json | 2 +- .../net9.0/Elecciones.Core.AssemblyInfo.cs | 2 +- .../EleccionesDbContext.cs | 10 +- .../Entities/ResumenVoto.cs | 3 + ...11_AddCategoriaIdToResumenVoto.Designer.cs | 732 ++++++++++++++++++ ...51014172711_AddCategoriaIdToResumenVoto.cs | 39 + .../EleccionesDbContextModelSnapshot.cs | 6 + .../Elecciones.Database.AssemblyInfo.cs | 2 +- .../Services/ElectoralApiService.cs | 23 +- .../Services/IElectoralApiService.cs | 3 +- .../Elecciones.Infrastructure.AssemblyInfo.cs | 2 +- .../Elecciones.Worker/CriticalDataWorker.cs | 140 ++-- .../LowPriorityDataWorker.cs | 140 ++-- .../appsettings.Development.json | 2 +- .../net9.0/Elecciones.Worker.AssemblyInfo.cs | 2 +- 18 files changed, 1053 insertions(+), 343 deletions(-) create mode 100644 Elecciones-Web/src/Elecciones.Database/Migrations/20251014172711_AddCategoriaIdToResumenVoto.Designer.cs create mode 100644 Elecciones-Web/src/Elecciones.Database/Migrations/20251014172711_AddCategoriaIdToResumenVoto.cs diff --git a/Elecciones-Web/src/Elecciones.Api/Program.cs b/Elecciones-Web/src/Elecciones.Api/Program.cs index 82e6208..56c58c4 100644 --- a/Elecciones-Web/src/Elecciones.Api/Program.cs +++ b/Elecciones-Web/src/Elecciones.Api/Program.cs @@ -167,6 +167,9 @@ using (var scope = app.Services.CreateScope()) var logger = services.GetRequiredService>(); var hasher = services.GetRequiredService(); + // --- PASO 1: Añadir esta bandera de control --- + bool generarDatosDeEjemplo = false; // <-- Poner en 'false' para deshabilitar + // --- SEEDER 1: DATOS ESTRUCTURALES BÁSICOS (se ejecutan una sola vez si la BD está vacía) --- // Estos son los datos maestros que NUNCA cambian. @@ -218,169 +221,171 @@ using (var scope = app.Services.CreateScope()) await context.SaveChangesAsync(); logger.LogInformation("--> Default configurations verified/seeded."); - - // --- SEEDER 2: DATOS DE EJEMPLO PARA ELECCIÓN NACIONAL (se ejecuta solo si faltan sus votos) --- - const int eleccionNacionalId = 2; - if (!await context.ResultadosVotos.AnyAsync(r => r.EleccionId == eleccionNacionalId)) + // --- PASO 2: Envolver todo el bloque del Seeder 2 en esta condición --- + if (generarDatosDeEjemplo) { - logger.LogInformation("--> No se encontraron datos de votos para la elección nacional ID {EleccionId}. Generando datos de simulación...", eleccionNacionalId); + // --- SEEDER 2: DATOS DE EJEMPLO PARA ELECCIÓN NACIONAL (se ejecuta solo si faltan sus votos) --- + const int eleccionNacionalId = 2; + if (!await context.ResultadosVotos.AnyAsync(r => r.EleccionId == eleccionNacionalId)) + { + logger.LogInformation("--> No se encontraron datos de votos para la elección nacional ID {EleccionId}. Generando datos de simulación...", eleccionNacionalId); - // PASO A: VERIFICAR/CREAR DEPENDENCIAS (Ámbitos, Categorías) - if (!await context.CategoriasElectorales.AnyAsync(c => c.Id == 1)) - context.CategoriasElectorales.Add(new CategoriaElectoral { Id = 1, Nombre = "SENADORES NACIONALES", Orden = 2 }); - if (!await context.CategoriasElectorales.AnyAsync(c => c.Id == 2)) - context.CategoriasElectorales.Add(new CategoriaElectoral { Id = 2, Nombre = "DIPUTADOS NACIONALES", Orden = 3 }); + // PASO A: VERIFICAR/CREAR DEPENDENCIAS (Ámbitos, Categorías) + if (!await context.CategoriasElectorales.AnyAsync(c => c.Id == 1)) + context.CategoriasElectorales.Add(new CategoriaElectoral { Id = 1, Nombre = "SENADORES NACIONALES", Orden = 2 }); + if (!await context.CategoriasElectorales.AnyAsync(c => c.Id == 2)) + context.CategoriasElectorales.Add(new CategoriaElectoral { Id = 2, Nombre = "DIPUTADOS NACIONALES", Orden = 3 }); - var provinciasMaestras = new Dictionary { + var provinciasMaestras = new Dictionary { { "01", "CIUDAD AUTONOMA DE BUENOS AIRES" }, { "02", "BUENOS AIRES" }, { "03", "CATAMARCA" }, { "04", "CORDOBA" }, { "05", "CORRIENTES" }, { "06", "CHACO" }, { "07", "CHUBUT" }, { "08", "ENTRE RIOS" }, { "09", "FORMOSA" }, { "10", "JUJUY" }, { "11", "LA PAMPA" }, { "12", "LA RIOJA" }, { "13", "MENDOZA" }, { "14", "MISIONES" }, { "15", "NEUQUEN" }, { "16", "RIO NEGRO" }, { "17", "SALTA" }, { "18", "SAN JUAN" }, { "19", "SAN LUIS" }, { "20", "SANTA CRUZ" }, { "21", "SANTA FE" }, { "22", "SANTIAGO DEL ESTERO" }, { "23", "TIERRA DEL FUEGO" }, { "24", "TUCUMAN" } }; - foreach (var p in provinciasMaestras) - { - if (!await context.AmbitosGeograficos.AnyAsync(a => a.NivelId == 10 && a.DistritoId == p.Key)) - context.AmbitosGeograficos.Add(new AmbitoGeografico { Nombre = p.Value, NivelId = 10, DistritoId = p.Key }); - } - await context.SaveChangesAsync(); - - var provinciasEnDb = await context.AmbitosGeograficos.AsNoTracking().Where(a => a.NivelId == 10).ToListAsync(); - foreach (var provincia in provinciasEnDb) - { - if (!await context.AmbitosGeograficos.AnyAsync(a => a.NivelId == 30 && a.DistritoId == provincia.DistritoId)) + foreach (var p in provinciasMaestras) { - for (int i = 1; i <= 5; i++) - context.AmbitosGeograficos.Add(new AmbitoGeografico { Nombre = $"{provincia.Nombre} - Depto. {i}", NivelId = 30, DistritoId = provincia.DistritoId }); + if (!await context.AmbitosGeograficos.AnyAsync(a => a.NivelId == 10 && a.DistritoId == p.Key)) + context.AmbitosGeograficos.Add(new AmbitoGeografico { Nombre = p.Value, NivelId = 10, DistritoId = p.Key }); } - } - await context.SaveChangesAsync(); - logger.LogInformation("--> Datos maestros para Elección Nacional (Ámbitos, Categorías) verificados/creados."); + await context.SaveChangesAsync(); - // PASO B: GENERAR DATOS TRANSACCIONALES (Votos, Recuentos, etc.) - var todosLosPartidos = await context.AgrupacionesPoliticas.Take(5).ToListAsync(); - if (!todosLosPartidos.Any()) - { - logger.LogWarning("--> No hay partidos en la BD, no se pueden generar votos de ejemplo."); - return; // Salir si no hay partidos para evitar errores - } - - // (La lógica interna de generación de votos y recuentos que ya tenías y funcionaba) - // ... (el código de generación de `nuevosResultados` y `nuevosEstados` va aquí, sin cambios) - var nuevosResultados = new List(); - var nuevosEstados = new List(); - var rand = new Random(); - var provinciasQueRenuevanSenadores = new HashSet { "01", "06", "08", "15", "16", "17", "22", "23" }; - var categoriaDiputadosNac = await context.CategoriasElectorales.FindAsync(2); - var categoriaSenadoresNac = await context.CategoriasElectorales.FindAsync(1); - - long totalVotosNacionalDip = 0, totalVotosNacionalSen = 0; - int totalMesasNacionalDip = 0, totalMesasNacionalSen = 0; - int totalMesasEscrutadasNacionalDip = 0, totalMesasEscrutadasNacionalSen = 0; - - foreach (var provincia in provinciasEnDb) - { - var municipiosDeProvincia = await context.AmbitosGeograficos.AsNoTracking().Where(a => a.NivelId == 30 && a.DistritoId == provincia.DistritoId).ToListAsync(); - if (!municipiosDeProvincia.Any()) continue; - - var categoriasParaProcesar = new List { categoriaDiputadosNac! }; - if (provinciasQueRenuevanSenadores.Contains(provincia.DistritoId!)) - categoriasParaProcesar.Add(categoriaSenadoresNac!); - - foreach (var categoria in categoriasParaProcesar) + var provinciasEnDb = await context.AmbitosGeograficos.AsNoTracking().Where(a => a.NivelId == 10).ToListAsync(); + foreach (var provincia in provinciasEnDb) { - long totalVotosProvinciaCategoria = 0; - int partidoIndex = rand.Next(todosLosPartidos.Count); - foreach (var municipio in municipiosDeProvincia) + if (!await context.AmbitosGeograficos.AnyAsync(a => a.NivelId == 30 && a.DistritoId == provincia.DistritoId)) { - var partidoGanador = todosLosPartidos[partidoIndex++ % todosLosPartidos.Count]; - var votosGanador = rand.Next(25000, 70000); - nuevosResultados.Add(new ResultadoVoto { EleccionId = eleccionNacionalId, AmbitoGeograficoId = municipio.Id, CategoriaId = categoria.Id, AgrupacionPoliticaId = partidoGanador.Id, CantidadVotos = votosGanador }); - totalVotosProvinciaCategoria += votosGanador; - var otrosPartidos = todosLosPartidos.Where(p => p.Id != partidoGanador.Id).OrderBy(p => rand.Next()).Take(rand.Next(3, todosLosPartidos.Count)); - foreach (var competidor in otrosPartidos) + for (int i = 1; i <= 5; i++) + context.AmbitosGeograficos.Add(new AmbitoGeografico { Nombre = $"{provincia.Nombre} - Depto. {i}", NivelId = 30, DistritoId = provincia.DistritoId }); + } + } + await context.SaveChangesAsync(); + logger.LogInformation("--> Datos maestros para Elección Nacional (Ámbitos, Categorías) verificados/creados."); + + // PASO B: GENERAR DATOS TRANSACCIONALES (Votos, Recuentos, etc.) + var todosLosPartidos = await context.AgrupacionesPoliticas.Take(5).ToListAsync(); + if (!todosLosPartidos.Any()) + { + logger.LogWarning("--> No hay partidos en la BD, no se pueden generar votos de ejemplo."); + return; // Salir si no hay partidos para evitar errores + } + + // (La lógica interna de generación de votos y recuentos que ya tenías y funcionaba) + // ... (el código de generación de `nuevosResultados` y `nuevosEstados` va aquí, sin cambios) + var nuevosResultados = new List(); + var nuevosEstados = new List(); + var rand = new Random(); + var provinciasQueRenuevanSenadores = new HashSet { "01", "06", "08", "15", "16", "17", "22", "23" }; + var categoriaDiputadosNac = await context.CategoriasElectorales.FindAsync(2); + var categoriaSenadoresNac = await context.CategoriasElectorales.FindAsync(1); + + long totalVotosNacionalDip = 0, totalVotosNacionalSen = 0; + int totalMesasNacionalDip = 0, totalMesasNacionalSen = 0; + int totalMesasEscrutadasNacionalDip = 0, totalMesasEscrutadasNacionalSen = 0; + + foreach (var provincia in provinciasEnDb) + { + var municipiosDeProvincia = await context.AmbitosGeograficos.AsNoTracking().Where(a => a.NivelId == 30 && a.DistritoId == provincia.DistritoId).ToListAsync(); + if (!municipiosDeProvincia.Any()) continue; + + var categoriasParaProcesar = new List { categoriaDiputadosNac! }; + if (provinciasQueRenuevanSenadores.Contains(provincia.DistritoId!)) + categoriasParaProcesar.Add(categoriaSenadoresNac!); + + foreach (var categoria in categoriasParaProcesar) + { + long totalVotosProvinciaCategoria = 0; + int partidoIndex = rand.Next(todosLosPartidos.Count); + foreach (var municipio in municipiosDeProvincia) { - var votosCompetidor = rand.Next(1000, 24000); - nuevosResultados.Add(new ResultadoVoto { EleccionId = eleccionNacionalId, AmbitoGeograficoId = municipio.Id, CategoriaId = categoria.Id, AgrupacionPoliticaId = competidor.Id, CantidadVotos = votosCompetidor }); - totalVotosProvinciaCategoria += votosCompetidor; + var partidoGanador = todosLosPartidos[partidoIndex++ % todosLosPartidos.Count]; + var votosGanador = rand.Next(25000, 70000); + nuevosResultados.Add(new ResultadoVoto { EleccionId = eleccionNacionalId, AmbitoGeograficoId = municipio.Id, CategoriaId = categoria.Id, AgrupacionPoliticaId = partidoGanador.Id, CantidadVotos = votosGanador }); + totalVotosProvinciaCategoria += votosGanador; + var otrosPartidos = todosLosPartidos.Where(p => p.Id != partidoGanador.Id).OrderBy(p => rand.Next()).Take(rand.Next(3, todosLosPartidos.Count)); + foreach (var competidor in otrosPartidos) + { + var votosCompetidor = rand.Next(1000, 24000); + nuevosResultados.Add(new ResultadoVoto { EleccionId = eleccionNacionalId, AmbitoGeograficoId = municipio.Id, CategoriaId = categoria.Id, AgrupacionPoliticaId = competidor.Id, CantidadVotos = votosCompetidor }); + totalVotosProvinciaCategoria += votosCompetidor; + } + } + var mesasEsperadasProvincia = municipiosDeProvincia.Count * rand.Next(15, 30); + var mesasTotalizadasProvincia = (int)(mesasEsperadasProvincia * (rand.Next(75, 99) / 100.0)); + var cantidadElectoresProvincia = mesasEsperadasProvincia * 350; + var participacionProvincia = (decimal)(rand.Next(65, 85) / 100.0); + nuevosEstados.Add(new EstadoRecuentoGeneral + { + EleccionId = eleccionNacionalId, + AmbitoGeograficoId = provincia.Id, + CategoriaId = categoria.Id, + FechaTotalizacion = DateTime.UtcNow, + MesasEsperadas = mesasEsperadasProvincia, + MesasTotalizadas = mesasTotalizadasProvincia, + MesasTotalizadasPorcentaje = mesasEsperadasProvincia > 0 ? (decimal)mesasTotalizadasProvincia * 100 / mesasEsperadasProvincia : 0, + CantidadElectores = cantidadElectoresProvincia, + CantidadVotantes = (int)(cantidadElectoresProvincia * participacionProvincia), + ParticipacionPorcentaje = participacionProvincia * 100 + }); + if (categoriaDiputadosNac != null && categoria.Id == categoriaDiputadosNac.Id) + { + totalVotosNacionalDip += totalVotosProvinciaCategoria; totalMesasNacionalDip += mesasEsperadasProvincia; totalMesasEscrutadasNacionalDip += mesasTotalizadasProvincia; + } + else + { + totalVotosNacionalSen += totalVotosProvinciaCategoria; totalMesasNacionalSen += mesasEsperadasProvincia; totalMesasEscrutadasNacionalSen += mesasTotalizadasProvincia; } } - var mesasEsperadasProvincia = municipiosDeProvincia.Count * rand.Next(15, 30); - var mesasTotalizadasProvincia = (int)(mesasEsperadasProvincia * (rand.Next(75, 99) / 100.0)); - var cantidadElectoresProvincia = mesasEsperadasProvincia * 350; - var participacionProvincia = (decimal)(rand.Next(65, 85) / 100.0); + } + var ambitoNacional = await context.AmbitosGeograficos.AsNoTracking().FirstOrDefaultAsync(a => a.NivelId == 0); + if (ambitoNacional != null && categoriaDiputadosNac != null && categoriaSenadoresNac != null) + { + var participacionNacionalDip = (decimal)(rand.Next(70, 88) / 100.0); nuevosEstados.Add(new EstadoRecuentoGeneral { EleccionId = eleccionNacionalId, - AmbitoGeograficoId = provincia.Id, - CategoriaId = categoria.Id, + AmbitoGeograficoId = ambitoNacional.Id, + CategoriaId = categoriaDiputadosNac.Id, FechaTotalizacion = DateTime.UtcNow, - MesasEsperadas = mesasEsperadasProvincia, - MesasTotalizadas = mesasTotalizadasProvincia, - MesasTotalizadasPorcentaje = mesasEsperadasProvincia > 0 ? (decimal)mesasTotalizadasProvincia * 100 / mesasEsperadasProvincia : 0, - CantidadElectores = cantidadElectoresProvincia, - CantidadVotantes = (int)(cantidadElectoresProvincia * participacionProvincia), - ParticipacionPorcentaje = participacionProvincia * 100 + MesasEsperadas = totalMesasNacionalDip, + MesasTotalizadas = totalMesasEscrutadasNacionalDip, + MesasTotalizadasPorcentaje = totalMesasNacionalDip > 0 ? (decimal)totalMesasEscrutadasNacionalDip * 100 / totalMesasNacionalDip : 0, + CantidadElectores = totalMesasNacionalDip * 350, + CantidadVotantes = (int)((totalMesasNacionalDip * 350) * participacionNacionalDip), + ParticipacionPorcentaje = participacionNacionalDip * 100 }); - if (categoriaDiputadosNac != null && categoria.Id == categoriaDiputadosNac.Id) + var participacionNacionalSen = (decimal)(rand.Next(70, 88) / 100.0); + nuevosEstados.Add(new EstadoRecuentoGeneral { - totalVotosNacionalDip += totalVotosProvinciaCategoria; totalMesasNacionalDip += mesasEsperadasProvincia; totalMesasEscrutadasNacionalDip += mesasTotalizadasProvincia; - } - else - { - totalVotosNacionalSen += totalVotosProvinciaCategoria; totalMesasNacionalSen += mesasEsperadasProvincia; totalMesasEscrutadasNacionalSen += mesasTotalizadasProvincia; - } + EleccionId = eleccionNacionalId, + AmbitoGeograficoId = ambitoNacional.Id, + CategoriaId = categoriaSenadoresNac.Id, + FechaTotalizacion = DateTime.UtcNow, + MesasEsperadas = totalMesasNacionalSen, + MesasTotalizadas = totalMesasEscrutadasNacionalSen, + MesasTotalizadasPorcentaje = totalMesasNacionalSen > 0 ? (decimal)totalMesasEscrutadasNacionalSen * 100 / totalMesasNacionalSen : 0, + CantidadElectores = totalMesasNacionalSen * 350, + CantidadVotantes = (int)((totalMesasNacionalSen * 350) * participacionNacionalSen), + ParticipacionPorcentaje = participacionNacionalSen * 100 + }); } - } - var ambitoNacional = await context.AmbitosGeograficos.AsNoTracking().FirstOrDefaultAsync(a => a.NivelId == 0); - if (ambitoNacional != null && categoriaDiputadosNac != null && categoriaSenadoresNac != null) - { - var participacionNacionalDip = (decimal)(rand.Next(70, 88) / 100.0); - nuevosEstados.Add(new EstadoRecuentoGeneral + else { - EleccionId = eleccionNacionalId, - AmbitoGeograficoId = ambitoNacional.Id, - CategoriaId = categoriaDiputadosNac.Id, - FechaTotalizacion = DateTime.UtcNow, - MesasEsperadas = totalMesasNacionalDip, - MesasTotalizadas = totalMesasEscrutadasNacionalDip, - MesasTotalizadasPorcentaje = totalMesasNacionalDip > 0 ? (decimal)totalMesasEscrutadasNacionalDip * 100 / totalMesasNacionalDip : 0, - CantidadElectores = totalMesasNacionalDip * 350, - CantidadVotantes = (int)((totalMesasNacionalDip * 350) * participacionNacionalDip), - ParticipacionPorcentaje = participacionNacionalDip * 100 - }); - var participacionNacionalSen = (decimal)(rand.Next(70, 88) / 100.0); - nuevosEstados.Add(new EstadoRecuentoGeneral + logger.LogWarning("--> No se encontró el ámbito nacional (NivelId == 0) o las categorías electorales nacionales. No se agregaron estados nacionales."); + } + + if (nuevosResultados.Any()) { - EleccionId = eleccionNacionalId, - AmbitoGeograficoId = ambitoNacional.Id, - CategoriaId = categoriaSenadoresNac.Id, - FechaTotalizacion = DateTime.UtcNow, - MesasEsperadas = totalMesasNacionalSen, - MesasTotalizadas = totalMesasEscrutadasNacionalSen, - MesasTotalizadasPorcentaje = totalMesasNacionalSen > 0 ? (decimal)totalMesasEscrutadasNacionalSen * 100 / totalMesasNacionalSen : 0, - CantidadElectores = totalMesasNacionalSen * 350, - CantidadVotantes = (int)((totalMesasNacionalSen * 350) * participacionNacionalSen), - ParticipacionPorcentaje = participacionNacionalSen * 100 - }); - } - else - { - logger.LogWarning("--> No se encontró el ámbito nacional (NivelId == 0) o las categorías electorales nacionales. No se agregaron estados nacionales."); - } + await context.ResultadosVotos.AddRangeAsync(nuevosResultados); + await context.EstadosRecuentosGenerales.AddRangeAsync(nuevosEstados); + await context.SaveChangesAsync(); + logger.LogInformation("--> Se generaron {Votos} registros de votos y {Estados} de estados de recuento.", nuevosResultados.Count, nuevosEstados.Count); + } - if (nuevosResultados.Any()) - { - await context.ResultadosVotos.AddRangeAsync(nuevosResultados); - await context.EstadosRecuentosGenerales.AddRangeAsync(nuevosEstados); - await context.SaveChangesAsync(); - logger.LogInformation("--> Se generaron {Votos} registros de votos y {Estados} de estados de recuento.", nuevosResultados.Count, nuevosEstados.Count); - } - - // PASO C: GENERAR BANCAS PREVIAS Y PROYECCIONES - if (!await context.BancasPrevias.AnyAsync(b => b.EleccionId == eleccionNacionalId)) - { - var bancasPrevias = new List { + // PASO C: GENERAR BANCAS PREVIAS Y PROYECCIONES + if (!await context.BancasPrevias.AnyAsync(b => b.EleccionId == eleccionNacionalId)) + { + var bancasPrevias = new List { new() { EleccionId = eleccionNacionalId, Camara = TipoCamara.Diputados, AgrupacionPoliticaId = todosLosPartidos[0].Id, Cantidad = 40 }, new() { EleccionId = eleccionNacionalId, Camara = TipoCamara.Diputados, AgrupacionPoliticaId = todosLosPartidos[1].Id, Cantidad = 35 }, new() { EleccionId = eleccionNacionalId, Camara = TipoCamara.Diputados, AgrupacionPoliticaId = todosLosPartidos[2].Id, Cantidad = 30 }, @@ -392,9 +397,10 @@ using (var scope = app.Services.CreateScope()) new() { EleccionId = eleccionNacionalId, Camara = TipoCamara.Senadores, AgrupacionPoliticaId = todosLosPartidos[3].Id, Cantidad = 4 }, new() { EleccionId = eleccionNacionalId, Camara = TipoCamara.Senadores, AgrupacionPoliticaId = todosLosPartidos[4].Id, Cantidad = 3 }, }; - await context.BancasPrevias.AddRangeAsync(bancasPrevias); - await context.SaveChangesAsync(); - logger.LogInformation("--> Seeded Bancas Previas para la Elección Nacional."); + await context.BancasPrevias.AddRangeAsync(bancasPrevias); + await context.SaveChangesAsync(); + logger.LogInformation("--> Seeded Bancas Previas para la Elección Nacional."); + } } } } diff --git a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs index 24f9e0e..54a3692 100644 --- a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs +++ b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/Elecciones.Api.AssemblyInfo.cs @@ -14,7 +14,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a316e5dd0876a581437b08d9980b658cc714da90")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+84f764390766e1d9716a38464ee478f3d0b75f96")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json index edcfd45..5acbb45 100644 --- a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json +++ b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmcshtml.dswa.cache.json @@ -1 +1 @@ -{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","DXx5dQywLo3UsY2zQaUG\u002BbW4ObiYbybxPBWxeJD2bhk=","muVh5sjH3sgdvuz4TbuTwTggX1uDnsWXgoosMKST/r4=","nrP5gSIA5vzgp8v12CAOr943QYLxU4Til6oiCcWSNI8=","yMd45U9BK07I3b3fBQ627PWTYyZ2ZjrmFc5VD\u002BQVx1Q=","xKskvcoJU0RVRN1a5dRqKRM7IP5vmmbraUaPFYjhnCc=","p7BjQw7aSZjfOCqmKm7/kPO9qegEQZBfirMjlOx/I1I=","MI0hVVLYavEhzHq/Z1UbajfrxanA1aET19aOH8G2ImI=","2dY8CqW9fAY8yN0foa\u002BZp2gc0RfPoPmB/tKSj1QoTw0=","79rfGLH4UjfTPvc//\u002BZjnBqdz585pUtYZ0/hwE2iEic=","PUqgvMdfTQkF5lpBVtHv2teQLV5WaEH0xMKTmINe2YQ=","\u002BFI0b4ppdxel/pby/y/xKImHrtdxo2g83OhskdREyIg=","jEESu6\u002BhbDvNMjLt/6OufuK\u002B9cHmzx\u002BTCIn4fWa9nSc=","UaCPJEvR4nVxxGCB5CUnRlJiw4drDW3Q3Nss\u002Bya2cv4=","ZqF13CT3rok/Gzl\u002BMsw3q9X1nf65bwEVD670efE3k\u002Bk=","gH3W7phPzBCY1DAVn4YnP4SA8Uaq73TpctS0yFSvzNM=","u5F4J4\u002BLHUIOCz5ze5NSF42mDeAaAfi\u002BKN3Ay3rKLY8=","GeUUID0ymF5rrBWdX7YHzWA5GiGkNWCNUog4sp4xL3c=","3BxX4I0JXoDqmE8m0BrRZhixBRlHEueS3jAlmUXE/I8=","IlET7uqumshgFxIEvfKRskON\u002BeAKZ7OfD/kCeAwn0PM=","NN2rS\u002B89ZAITWlNODPcF/lHIh3ZNmAHvUX4EjqSkX4s=","OE89N/FsYhRU1Dy5Ne83ehzSwlNc/RcxHrJpHxPHfqY=","QI7IL4TkYEqfUiIEXQiVCaZx4vrM9/wZlvOrhnUd4jQ=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","M5oop6AzAA5LmqkUXPrT16q3xF0Jty6n7nfGWkjXG94="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","DXx5dQywLo3UsY2zQaUG\u002BbW4ObiYbybxPBWxeJD2bhk=","muVh5sjH3sgdvuz4TbuTwTggX1uDnsWXgoosMKST/r4=","nrP5gSIA5vzgp8v12CAOr943QYLxU4Til6oiCcWSNI8=","yMd45U9BK07I3b3fBQ627PWTYyZ2ZjrmFc5VD\u002BQVx1Q=","xKskvcoJU0RVRN1a5dRqKRM7IP5vmmbraUaPFYjhnCc=","p7BjQw7aSZjfOCqmKm7/kPO9qegEQZBfirMjlOx/I1I=","MI0hVVLYavEhzHq/Z1UbajfrxanA1aET19aOH8G2ImI=","2dY8CqW9fAY8yN0foa\u002BZp2gc0RfPoPmB/tKSj1QoTw0=","79rfGLH4UjfTPvc//\u002BZjnBqdz585pUtYZ0/hwE2iEic=","PUqgvMdfTQkF5lpBVtHv2teQLV5WaEH0xMKTmINe2YQ=","\u002BFI0b4ppdxel/pby/y/xKImHrtdxo2g83OhskdREyIg=","jEESu6\u002BhbDvNMjLt/6OufuK\u002B9cHmzx\u002BTCIn4fWa9nSc=","UaCPJEvR4nVxxGCB5CUnRlJiw4drDW3Q3Nss\u002Bya2cv4=","ZqF13CT3rok/Gzl\u002BMsw3q9X1nf65bwEVD670efE3k\u002Bk=","gH3W7phPzBCY1DAVn4YnP4SA8Uaq73TpctS0yFSvzNM=","u5F4J4\u002BLHUIOCz5ze5NSF42mDeAaAfi\u002BKN3Ay3rKLY8=","GeUUID0ymF5rrBWdX7YHzWA5GiGkNWCNUog4sp4xL3c=","3BxX4I0JXoDqmE8m0BrRZhixBRlHEueS3jAlmUXE/I8=","IlET7uqumshgFxIEvfKRskON\u002BeAKZ7OfD/kCeAwn0PM=","NN2rS\u002B89ZAITWlNODPcF/lHIh3ZNmAHvUX4EjqSkX4s=","OE89N/FsYhRU1Dy5Ne83ehzSwlNc/RcxHrJpHxPHfqY=","QI7IL4TkYEqfUiIEXQiVCaZx4vrM9/wZlvOrhnUd4jQ=","UIntj4QoiyGr7bnJN8KK5PGrhQd89m\u002BLfh4T8VKPxAk=","Zf7uND\u002BRw1vwmlJX6vYl9l2j52U48b1N59mSoDoOeFU=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","ViGA16LZjzGiizSwwZApo6OQjv5hBNvl3QW/ISbKUWM="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json index 9b3a45b..6941384 100644 --- a/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json +++ b/Elecciones-Web/src/Elecciones.Api/obj/Debug/net9.0/rjsmrazor.dswa.cache.json @@ -1 +1 @@ -{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","DXx5dQywLo3UsY2zQaUG\u002BbW4ObiYbybxPBWxeJD2bhk=","muVh5sjH3sgdvuz4TbuTwTggX1uDnsWXgoosMKST/r4=","nrP5gSIA5vzgp8v12CAOr943QYLxU4Til6oiCcWSNI8=","yMd45U9BK07I3b3fBQ627PWTYyZ2ZjrmFc5VD\u002BQVx1Q=","xKskvcoJU0RVRN1a5dRqKRM7IP5vmmbraUaPFYjhnCc=","p7BjQw7aSZjfOCqmKm7/kPO9qegEQZBfirMjlOx/I1I=","MI0hVVLYavEhzHq/Z1UbajfrxanA1aET19aOH8G2ImI=","2dY8CqW9fAY8yN0foa\u002BZp2gc0RfPoPmB/tKSj1QoTw0=","79rfGLH4UjfTPvc//\u002BZjnBqdz585pUtYZ0/hwE2iEic=","PUqgvMdfTQkF5lpBVtHv2teQLV5WaEH0xMKTmINe2YQ=","\u002BFI0b4ppdxel/pby/y/xKImHrtdxo2g83OhskdREyIg=","jEESu6\u002BhbDvNMjLt/6OufuK\u002B9cHmzx\u002BTCIn4fWa9nSc=","UaCPJEvR4nVxxGCB5CUnRlJiw4drDW3Q3Nss\u002Bya2cv4=","ZqF13CT3rok/Gzl\u002BMsw3q9X1nf65bwEVD670efE3k\u002Bk=","gH3W7phPzBCY1DAVn4YnP4SA8Uaq73TpctS0yFSvzNM=","u5F4J4\u002BLHUIOCz5ze5NSF42mDeAaAfi\u002BKN3Ay3rKLY8=","GeUUID0ymF5rrBWdX7YHzWA5GiGkNWCNUog4sp4xL3c=","3BxX4I0JXoDqmE8m0BrRZhixBRlHEueS3jAlmUXE/I8=","IlET7uqumshgFxIEvfKRskON\u002BeAKZ7OfD/kCeAwn0PM=","NN2rS\u002B89ZAITWlNODPcF/lHIh3ZNmAHvUX4EjqSkX4s=","OE89N/FsYhRU1Dy5Ne83ehzSwlNc/RcxHrJpHxPHfqY=","QI7IL4TkYEqfUiIEXQiVCaZx4vrM9/wZlvOrhnUd4jQ=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","M5oop6AzAA5LmqkUXPrT16q3xF0Jty6n7nfGWkjXG94="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","dcHQRkttjMjo2dvhL7hA9t4Pg\u002B7OnjZpkFmakT4QR9U=","Of8nTYw5l\u002BgiAJo7z6XYIntG2tUtCFcILzHbTiiXn\u002Bw=","PDy\u002BTiayvNAoXXBEgwC/kCojpgOOMI6RQOIoSXs3LJc=","ePXrkee3hv3wHUr8S7aYmRVvXUTxQf76zApKGv3/l3o=","DXx5dQywLo3UsY2zQaUG\u002BbW4ObiYbybxPBWxeJD2bhk=","muVh5sjH3sgdvuz4TbuTwTggX1uDnsWXgoosMKST/r4=","nrP5gSIA5vzgp8v12CAOr943QYLxU4Til6oiCcWSNI8=","yMd45U9BK07I3b3fBQ627PWTYyZ2ZjrmFc5VD\u002BQVx1Q=","xKskvcoJU0RVRN1a5dRqKRM7IP5vmmbraUaPFYjhnCc=","p7BjQw7aSZjfOCqmKm7/kPO9qegEQZBfirMjlOx/I1I=","MI0hVVLYavEhzHq/Z1UbajfrxanA1aET19aOH8G2ImI=","2dY8CqW9fAY8yN0foa\u002BZp2gc0RfPoPmB/tKSj1QoTw0=","79rfGLH4UjfTPvc//\u002BZjnBqdz585pUtYZ0/hwE2iEic=","PUqgvMdfTQkF5lpBVtHv2teQLV5WaEH0xMKTmINe2YQ=","\u002BFI0b4ppdxel/pby/y/xKImHrtdxo2g83OhskdREyIg=","jEESu6\u002BhbDvNMjLt/6OufuK\u002B9cHmzx\u002BTCIn4fWa9nSc=","UaCPJEvR4nVxxGCB5CUnRlJiw4drDW3Q3Nss\u002Bya2cv4=","ZqF13CT3rok/Gzl\u002BMsw3q9X1nf65bwEVD670efE3k\u002Bk=","gH3W7phPzBCY1DAVn4YnP4SA8Uaq73TpctS0yFSvzNM=","u5F4J4\u002BLHUIOCz5ze5NSF42mDeAaAfi\u002BKN3Ay3rKLY8=","GeUUID0ymF5rrBWdX7YHzWA5GiGkNWCNUog4sp4xL3c=","3BxX4I0JXoDqmE8m0BrRZhixBRlHEueS3jAlmUXE/I8=","IlET7uqumshgFxIEvfKRskON\u002BeAKZ7OfD/kCeAwn0PM=","NN2rS\u002B89ZAITWlNODPcF/lHIh3ZNmAHvUX4EjqSkX4s=","OE89N/FsYhRU1Dy5Ne83ehzSwlNc/RcxHrJpHxPHfqY=","QI7IL4TkYEqfUiIEXQiVCaZx4vrM9/wZlvOrhnUd4jQ=","UIntj4QoiyGr7bnJN8KK5PGrhQd89m\u002BLfh4T8VKPxAk=","Zf7uND\u002BRw1vwmlJX6vYl9l2j52U48b1N59mSoDoOeFU=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","ViGA16LZjzGiizSwwZApo6OQjv5hBNvl3QW/ISbKUWM="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Core/obj/Debug/net9.0/Elecciones.Core.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Core/obj/Debug/net9.0/Elecciones.Core.AssemblyInfo.cs index 99f211f..b472acf 100644 --- a/Elecciones-Web/src/Elecciones.Core/obj/Debug/net9.0/Elecciones.Core.AssemblyInfo.cs +++ b/Elecciones-Web/src/Elecciones.Core/obj/Debug/net9.0/Elecciones.Core.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a316e5dd0876a581437b08d9980b658cc714da90")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+84f764390766e1d9716a38464ee478f3d0b75f96")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/Elecciones-Web/src/Elecciones.Database/EleccionesDbContext.cs b/Elecciones-Web/src/Elecciones.Database/EleccionesDbContext.cs index 00fe383..b5ea11b 100644 --- a/Elecciones-Web/src/Elecciones.Database/EleccionesDbContext.cs +++ b/Elecciones-Web/src/Elecciones.Database/EleccionesDbContext.cs @@ -56,8 +56,14 @@ public class EleccionesDbContext(DbContextOptions options) modelBuilder.Entity() .Property(e => e.PorcentajeVotos).HasPrecision(18, 4); - modelBuilder.Entity() - .Property(e => e.VotosPorcentaje).HasPrecision(5, 2); + modelBuilder.Entity(entity => // Busca o crea este bloque + { + entity.Property(e => e.VotosPorcentaje).HasPrecision(5, 2); + // Esto asegura que no se pueda tener dos entradas para el mismo partido, + // en la misma categoría y en el mismo ámbito. + entity.HasIndex(r => new { r.AmbitoGeograficoId, r.CategoriaId, r.AgrupacionPoliticaId }) + .IsUnique(); + }); modelBuilder.Entity(entity => { diff --git a/Elecciones-Web/src/Elecciones.Database/Entities/ResumenVoto.cs b/Elecciones-Web/src/Elecciones.Database/Entities/ResumenVoto.cs index 5a86ed2..ca17b32 100644 --- a/Elecciones-Web/src/Elecciones.Database/Entities/ResumenVoto.cs +++ b/Elecciones-Web/src/Elecciones.Database/Entities/ResumenVoto.cs @@ -13,6 +13,9 @@ public class ResumenVoto [Required] public int AmbitoGeograficoId { get; set; } + [Required] + public int CategoriaId { get; set; } + [Required] public string AgrupacionPoliticaId { get; set; } = null!; diff --git a/Elecciones-Web/src/Elecciones.Database/Migrations/20251014172711_AddCategoriaIdToResumenVoto.Designer.cs b/Elecciones-Web/src/Elecciones.Database/Migrations/20251014172711_AddCategoriaIdToResumenVoto.Designer.cs new file mode 100644 index 0000000..a8c30a9 --- /dev/null +++ b/Elecciones-Web/src/Elecciones.Database/Migrations/20251014172711_AddCategoriaIdToResumenVoto.Designer.cs @@ -0,0 +1,732 @@ +// +using System; +using Elecciones.Database; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; + +#nullable disable + +namespace Elecciones.Database.Migrations +{ + [DbContext(typeof(EleccionesDbContext))] + [Migration("20251014172711_AddCategoriaIdToResumenVoto")] + partial class AddCategoriaIdToResumenVoto + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .UseCollation("Modern_Spanish_CI_AS") + .HasAnnotation("ProductVersion", "9.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Eleccion", b => + { + b.Property("Id") + .HasColumnType("int"); + + b.Property("DistritoId") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Fecha") + .HasColumnType("date"); + + b.Property("Nivel") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Nombre") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("Elecciones"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.AdminUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("PasswordHash") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("PasswordSalt") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Username") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Id"); + + b.ToTable("AdminUsers"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("Color") + .HasColumnType("nvarchar(max)"); + + b.Property("IdTelegrama") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Nombre") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("NombreCorto") + .HasColumnType("nvarchar(max)"); + + b.Property("OrdenDiputados") + .HasColumnType("int"); + + b.Property("OrdenDiputadosNacionales") + .HasColumnType("int"); + + b.Property("OrdenSenadores") + .HasColumnType("int"); + + b.Property("OrdenSenadoresNacionales") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("AgrupacionesPoliticas"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.AmbitoGeografico", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("CircuitoId") + .HasColumnType("nvarchar(max)"); + + b.Property("DistritoId") + .HasColumnType("nvarchar(max)"); + + b.Property("EstablecimientoId") + .HasColumnType("nvarchar(max)"); + + b.Property("MesaId") + .HasColumnType("nvarchar(max)"); + + b.Property("MunicipioId") + .HasColumnType("nvarchar(max)"); + + b.Property("NivelId") + .HasColumnType("int"); + + b.Property("Nombre") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("SeccionId") + .HasColumnType("nvarchar(max)"); + + b.Property("SeccionProvincialId") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.ToTable("AmbitosGeograficos"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.BancaPrevia", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AgrupacionPoliticaId") + .IsRequired() + .HasColumnType("nvarchar(450)") + .UseCollation("Modern_Spanish_CI_AS"); + + b.Property("Camara") + .HasColumnType("int"); + + b.Property("Cantidad") + .HasColumnType("int"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AgrupacionPoliticaId"); + + b.ToTable("BancasPrevias"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AgrupacionPoliticaId") + .HasColumnType("nvarchar(450)"); + + b.Property("Camara") + .HasColumnType("int"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.Property("NumeroBanca") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AgrupacionPoliticaId"); + + b.ToTable("Bancadas"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.CandidatoOverride", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AgrupacionPoliticaId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("CategoriaId") + .HasColumnType("int"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.Property("NombreCandidato") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("nvarchar(255)"); + + b.HasKey("Id"); + + b.HasIndex("AmbitoGeograficoId"); + + b.HasIndex("CategoriaId"); + + b.HasIndex("AgrupacionPoliticaId", "CategoriaId", "AmbitoGeograficoId") + .IsUnique() + .HasFilter("[AmbitoGeograficoId] IS NOT NULL"); + + b.ToTable("CandidatosOverrides"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b => + { + b.Property("Id") + .HasColumnType("int"); + + b.Property("Nombre") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Orden") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.ToTable("CategoriasElectorales"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.Configuracion", b => + { + b.Property("Clave") + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.Property("Valor") + .IsRequired() + .HasMaxLength(100) + .HasColumnType("nvarchar(100)"); + + b.HasKey("Clave"); + + b.ToTable("Configuraciones"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b => + { + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("CategoriaId") + .HasColumnType("int"); + + b.Property("CantidadElectores") + .HasColumnType("int"); + + b.Property("CantidadVotantes") + .HasColumnType("int"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.Property("FechaTotalizacion") + .HasColumnType("datetime2"); + + b.Property("MesasEsperadas") + .HasColumnType("int"); + + b.Property("MesasTotalizadas") + .HasColumnType("int"); + + b.Property("MesasTotalizadasPorcentaje") + .HasPrecision(5, 2) + .HasColumnType("decimal(5,2)"); + + b.Property("ParticipacionPorcentaje") + .HasPrecision(5, 2) + .HasColumnType("decimal(5,2)"); + + b.Property("VotosEnBlanco") + .HasColumnType("bigint"); + + b.Property("VotosEnBlancoPorcentaje") + .HasPrecision(18, 4) + .HasColumnType("decimal(18,4)"); + + b.Property("VotosNulos") + .HasColumnType("bigint"); + + b.Property("VotosNulosPorcentaje") + .HasPrecision(18, 4) + .HasColumnType("decimal(18,4)"); + + b.Property("VotosRecurridos") + .HasColumnType("bigint"); + + b.Property("VotosRecurridosPorcentaje") + .HasPrecision(18, 4) + .HasColumnType("decimal(18,4)"); + + b.HasKey("AmbitoGeograficoId", "CategoriaId"); + + b.ToTable("EstadosRecuentos"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b => + { + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("CategoriaId") + .HasColumnType("int"); + + b.Property("CantidadElectores") + .HasColumnType("int"); + + b.Property("CantidadVotantes") + .HasColumnType("int"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.Property("FechaTotalizacion") + .HasColumnType("datetime2"); + + b.Property("MesasEsperadas") + .HasColumnType("int"); + + b.Property("MesasTotalizadas") + .HasColumnType("int"); + + b.Property("MesasTotalizadasPorcentaje") + .HasPrecision(5, 2) + .HasColumnType("decimal(5,2)"); + + b.Property("ParticipacionPorcentaje") + .HasPrecision(5, 2) + .HasColumnType("decimal(5,2)"); + + b.HasKey("AmbitoGeograficoId", "CategoriaId"); + + b.HasIndex("CategoriaId"); + + b.ToTable("EstadosRecuentosGenerales"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.LogoAgrupacionCategoria", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AgrupacionPoliticaId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("CategoriaId") + .HasColumnType("int"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.Property("LogoUrl") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("AgrupacionPoliticaId", "CategoriaId", "AmbitoGeograficoId") + .IsUnique() + .HasFilter("[AmbitoGeograficoId] IS NOT NULL"); + + b.ToTable("LogosAgrupacionesCategorias"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.OcupanteBanca", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("BancadaId") + .HasColumnType("int"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.Property("FotoUrl") + .HasColumnType("nvarchar(max)"); + + b.Property("NombreOcupante") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Periodo") + .HasColumnType("nvarchar(max)"); + + b.HasKey("Id"); + + b.HasIndex("BancadaId") + .IsUnique(); + + b.ToTable("OcupantesBancas"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AgrupacionPoliticaId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("CategoriaId") + .HasColumnType("int"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.Property("FechaTotalizacion") + .HasColumnType("datetime2"); + + b.Property("NroBancas") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AgrupacionPoliticaId"); + + b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId") + .IsUnique(); + + b.ToTable("ProyeccionesBancas"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("bigint"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AgrupacionPoliticaId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("CantidadVotos") + .HasColumnType("bigint"); + + b.Property("CategoriaId") + .HasColumnType("int"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.Property("PorcentajeVotos") + .HasPrecision(18, 4) + .HasColumnType("decimal(18,4)"); + + b.HasKey("Id"); + + b.HasIndex("AgrupacionPoliticaId"); + + b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId") + .IsUnique(); + + b.ToTable("ResultadosVotos"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("int"); + + SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property("Id")); + + b.Property("AgrupacionPoliticaId") + .IsRequired() + .HasColumnType("nvarchar(450)"); + + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("CategoriaId") + .HasColumnType("int"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.Property("Votos") + .HasColumnType("bigint"); + + b.Property("VotosPorcentaje") + .HasPrecision(5, 2) + .HasColumnType("decimal(5,2)"); + + b.HasKey("Id"); + + b.HasIndex("AgrupacionPoliticaId"); + + b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId") + .IsUnique(); + + b.ToTable("ResumenesVotos"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.Telegrama", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("ContenidoBase64") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("EleccionId") + .HasColumnType("int"); + + b.Property("FechaEscaneo") + .HasColumnType("datetime2"); + + b.Property("FechaTotalizacion") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Telegramas"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.BancaPrevia", b => + { + b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") + .WithMany() + .HasForeignKey("AgrupacionPoliticaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgrupacionPolitica"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b => + { + b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") + .WithMany() + .HasForeignKey("AgrupacionPoliticaId"); + + b.Navigation("AgrupacionPolitica"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.CandidatoOverride", b => + { + b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") + .WithMany() + .HasForeignKey("AgrupacionPoliticaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") + .WithMany() + .HasForeignKey("AmbitoGeograficoId"); + + b.HasOne("Elecciones.Database.Entities.CategoriaElectoral", "CategoriaElectoral") + .WithMany() + .HasForeignKey("CategoriaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgrupacionPolitica"); + + b.Navigation("AmbitoGeografico"); + + b.Navigation("CategoriaElectoral"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b => + { + b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") + .WithMany() + .HasForeignKey("AmbitoGeograficoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AmbitoGeografico"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b => + { + b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") + .WithMany() + .HasForeignKey("AmbitoGeograficoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Elecciones.Database.Entities.CategoriaElectoral", "CategoriaElectoral") + .WithMany() + .HasForeignKey("CategoriaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AmbitoGeografico"); + + b.Navigation("CategoriaElectoral"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.OcupanteBanca", b => + { + b.HasOne("Elecciones.Database.Entities.Bancada", "Bancada") + .WithOne("Ocupante") + .HasForeignKey("Elecciones.Database.Entities.OcupanteBanca", "BancadaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Bancada"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b => + { + b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") + .WithMany() + .HasForeignKey("AgrupacionPoliticaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") + .WithMany() + .HasForeignKey("AmbitoGeograficoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgrupacionPolitica"); + + b.Navigation("AmbitoGeografico"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b => + { + b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") + .WithMany() + .HasForeignKey("AgrupacionPoliticaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico") + .WithMany() + .HasForeignKey("AmbitoGeograficoId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgrupacionPolitica"); + + b.Navigation("AmbitoGeografico"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b => + { + b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica") + .WithMany() + .HasForeignKey("AgrupacionPoliticaId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("AgrupacionPolitica"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b => + { + b.Navigation("Ocupante"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Elecciones-Web/src/Elecciones.Database/Migrations/20251014172711_AddCategoriaIdToResumenVoto.cs b/Elecciones-Web/src/Elecciones.Database/Migrations/20251014172711_AddCategoriaIdToResumenVoto.cs new file mode 100644 index 0000000..2b16044 --- /dev/null +++ b/Elecciones-Web/src/Elecciones.Database/Migrations/20251014172711_AddCategoriaIdToResumenVoto.cs @@ -0,0 +1,39 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elecciones.Database.Migrations +{ + /// + public partial class AddCategoriaIdToResumenVoto : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "CategoriaId", + table: "ResumenesVotos", + type: "int", + nullable: false, + defaultValue: 0); + + migrationBuilder.CreateIndex( + name: "IX_ResumenesVotos_AmbitoGeograficoId_CategoriaId_AgrupacionPoliticaId", + table: "ResumenesVotos", + columns: new[] { "AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId" }, + unique: true); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_ResumenesVotos_AmbitoGeograficoId_CategoriaId_AgrupacionPoliticaId", + table: "ResumenesVotos"); + + migrationBuilder.DropColumn( + name: "CategoriaId", + table: "ResumenesVotos"); + } + } +} diff --git a/Elecciones-Web/src/Elecciones.Database/Migrations/EleccionesDbContextModelSnapshot.cs b/Elecciones-Web/src/Elecciones.Database/Migrations/EleccionesDbContextModelSnapshot.cs index 343833a..ab0026f 100644 --- a/Elecciones-Web/src/Elecciones.Database/Migrations/EleccionesDbContextModelSnapshot.cs +++ b/Elecciones-Web/src/Elecciones.Database/Migrations/EleccionesDbContextModelSnapshot.cs @@ -535,6 +535,9 @@ namespace Elecciones.Database.Migrations b.Property("AmbitoGeograficoId") .HasColumnType("int"); + b.Property("CategoriaId") + .HasColumnType("int"); + b.Property("EleccionId") .HasColumnType("int"); @@ -549,6 +552,9 @@ namespace Elecciones.Database.Migrations b.HasIndex("AgrupacionPoliticaId"); + b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId") + .IsUnique(); + b.ToTable("ResumenesVotos"); }); diff --git a/Elecciones-Web/src/Elecciones.Database/obj/Debug/net9.0/Elecciones.Database.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Database/obj/Debug/net9.0/Elecciones.Database.AssemblyInfo.cs index ff966d1..d725733 100644 --- a/Elecciones-Web/src/Elecciones.Database/obj/Debug/net9.0/Elecciones.Database.AssemblyInfo.cs +++ b/Elecciones-Web/src/Elecciones.Database/obj/Debug/net9.0/Elecciones.Database.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a316e5dd0876a581437b08d9980b658cc714da90")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+84f764390766e1d9716a38464ee478f3d0b75f96")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/Elecciones-Web/src/Elecciones.Infrastructure/Services/ElectoralApiService.cs b/Elecciones-Web/src/Elecciones.Infrastructure/Services/ElectoralApiService.cs index 30a75e4..8163414 100644 --- a/Elecciones-Web/src/Elecciones.Infrastructure/Services/ElectoralApiService.cs +++ b/Elecciones-Web/src/Elecciones.Infrastructure/Services/ElectoralApiService.cs @@ -92,7 +92,7 @@ public class ElectoralApiService : IElectoralApiService return null;*/ } - public async Task GetResultadosAsync(string authToken, string distritoId, string seccionId, string? municipioId, int categoriaId) + public async Task GetResultadosAsync(string authToken, string distritoId, string? seccionId, string? municipioId, int categoriaId) { using RateLimitLease lease = await _rateLimiter.AcquireAsync(1); if (!lease.IsAcquired) return null; @@ -256,27 +256,6 @@ public class ElectoralApiService : IElectoralApiService } } - public async Task GetResumenAsync(string authToken, string distritoId) - { - // "Pedir una ficha". Este método ahora devuelve un "lease" (permiso). - // Si no hay fichas, esperará aquí automáticamente hasta que se rellene el cubo. - /* - using RateLimitLease lease = await _rateLimiter.AcquireAsync(1); - - // Si se nos concede el permiso para proceder... - if (lease.IsAcquired) - {*/ - var client = _httpClientFactory.CreateClient("ElectoralApiClient"); - var requestUri = $"/api/resultados/getResumen?distritoId={distritoId}"; - var request = new HttpRequestMessage(HttpMethod.Get, requestUri); - request.Headers.Add("Authorization", $"Bearer {authToken}"); - var response = await client.SendAsync(request); - return response.IsSuccessStatusCode ? await response.Content.ReadFromJsonAsync() : null; - /* } - // Si no se pudo obtener un permiso (ej. la cola está llena), devolvemos null. - return null;*/ - } - public async Task GetEstadoRecuentoGeneralAsync(string authToken, string distritoId, int categoriaId) { // "Pedir una ficha". Este método ahora devuelve un "lease" (permiso). diff --git a/Elecciones-Web/src/Elecciones.Infrastructure/Services/IElectoralApiService.cs b/Elecciones-Web/src/Elecciones.Infrastructure/Services/IElectoralApiService.cs index 01b345a..130b240 100644 --- a/Elecciones-Web/src/Elecciones.Infrastructure/Services/IElectoralApiService.cs +++ b/Elecciones-Web/src/Elecciones.Infrastructure/Services/IElectoralApiService.cs @@ -11,11 +11,10 @@ public interface IElectoralApiService // Métodos para catálogos Task GetCatalogoAmbitosAsync(string authToken, int categoriaId); Task?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId); - Task GetResultadosAsync(string authToken, string distritoId, string seccionId, string? municipioId, int categoriaId); + Task GetResultadosAsync(string authToken, string distritoId, string? seccionId, string? municipioId, int categoriaId); Task GetBancasAsync(string authToken, string distritoId, string? seccionProvincialId, int categoriaId); Task?> GetTelegramasTotalizadosAsync(string authToken, string distritoId, string seccionId, int? categoriaId = null); Task GetTelegramaFileAsync(string authToken, string mesaId); - Task GetResumenAsync(string authToken, string distritoId); Task GetEstadoRecuentoGeneralAsync(string authToken, string distritoId, int categoriaId); Task?> GetCategoriasAsync(string authToken); } \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Infrastructure/obj/Debug/net9.0/Elecciones.Infrastructure.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Infrastructure/obj/Debug/net9.0/Elecciones.Infrastructure.AssemblyInfo.cs index d3e03c9..0a20d29 100644 --- a/Elecciones-Web/src/Elecciones.Infrastructure/obj/Debug/net9.0/Elecciones.Infrastructure.AssemblyInfo.cs +++ b/Elecciones-Web/src/Elecciones.Infrastructure/obj/Debug/net9.0/Elecciones.Infrastructure.AssemblyInfo.cs @@ -13,7 +13,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+a316e5dd0876a581437b08d9980b658cc714da90")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+84f764390766e1d9716a38464ee478f3d0b75f96")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/Elecciones-Web/src/Elecciones.Worker/CriticalDataWorker.cs b/Elecciones-Web/src/Elecciones.Worker/CriticalDataWorker.cs index 6058104..4b60c2f 100644 --- a/Elecciones-Web/src/Elecciones.Worker/CriticalDataWorker.cs +++ b/Elecciones-Web/src/Elecciones.Worker/CriticalDataWorker.cs @@ -473,119 +473,89 @@ public class CriticalDataWorker : BackgroundService } /// - /// Obtiene y actualiza el resumen de votos y el estado del recuento a nivel provincial. - /// Esta versión actualizada guarda tanto los votos por agrupación (en ResumenesVotos) - /// como el estado general del recuento, incluyendo la fecha de totalización (en EstadosRecuentosGenerales), - /// asegurando que toda la operación sea atómica mediante una transacción de base de datos. + /// Obtiene y actualiza el resumen de votos y el estado del recuento a nivel provincial para CADA categoría. + /// Este método itera sobre todas las provincias y categorías, obteniendo sus resultados consolidados + /// y guardándolos en las tablas 'ResumenesVotos' y 'EstadosRecuentosGenerales'. /// - /// El token de autenticación válido para la sesión. - /// El token de cancelación para detener la operación. private async Task SondearResumenProvincialAsync(string authToken, CancellationToken stoppingToken) { try { - // Creamos un scope de DbContext para esta operación. + _logger.LogInformation("Iniciando sondeo de Resúmenes Provinciales..."); + using var scope = _serviceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService(); - // Obtenemos el registro de la Provincia (NivelId 10). - var provincia = await dbContext.AmbitosGeograficos + var provinciasASondear = await dbContext.AmbitosGeograficos .AsNoTracking() - .FirstOrDefaultAsync(a => a.NivelId == 10, stoppingToken); + .Where(a => a.NivelId == 10 && a.DistritoId != null) + .ToListAsync(stoppingToken); - // Si no encontramos el ámbito de la provincia, no podemos continuar. - if (provincia == null) + var todasLasCategorias = await dbContext.CategoriasElectorales + .AsNoTracking() + .ToListAsync(stoppingToken); + + if (!provinciasASondear.Any() || !todasLasCategorias.Any()) { - _logger.LogWarning("No se encontró el ámbito 'Provincia' (NivelId 10) para el sondeo de resumen."); + _logger.LogWarning("No se encontraron Provincias o Categorías para sondear resúmenes."); return; } - // Llamamos a la API para obtener el resumen de datos provincial. - var resumenDto = await _apiService.GetResumenAsync(authToken, provincia.DistritoId!); - - // Solo procedemos si la API devolvió una respuesta válida y no nula. - if (resumenDto != null) + foreach (var provincia in provinciasASondear) { - // Iniciamos una transacción explícita. Esto garantiza que todas las operaciones de base de datos - // dentro de este bloque (el DELETE, los INSERTs y los UPDATEs) se completen con éxito, - // o si algo falla, se reviertan todas, manteniendo la consistencia de los datos. - await using var transaction = await dbContext.Database.BeginTransactionAsync(stoppingToken); + if (stoppingToken.IsCancellationRequested) break; - // --- 1. ACTUALIZAR LA TABLA 'ResumenesVotos' --- - - // Verificamos si la respuesta contiene una lista de votos positivos. - if (resumenDto.ValoresTotalizadosPositivos is { Count: > 0 } nuevosVotos) - { - // Estrategia "Borrar y Reemplazar": vaciamos la tabla antes de insertar los nuevos datos. - await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM ResumenesVotos", stoppingToken); - - // Añadimos cada nuevo registro de voto al DbContext. - foreach (var voto in nuevosVotos) - { - dbContext.ResumenesVotos.Add(new ResumenVoto - { - AmbitoGeograficoId = provincia.Id, - AgrupacionPoliticaId = voto.IdAgrupacion, - Votos = voto.Votos, - VotosPorcentaje = voto.VotosPorcentaje - }); - } - } - - // --- 2. ACTUALIZAR LA TABLA 'EstadosRecuentosGenerales' --- - - // El endpoint de Resumen no especifica una categoría, por lo que aplicamos sus datos de estado de recuento - // a todas las categorías que tenemos en nuestra base de datos. - var todasLasCategorias = await dbContext.CategoriasElectorales.AsNoTracking().ToListAsync(stoppingToken); foreach (var categoria in todasLasCategorias) { - // Buscamos el registro existente usando la clave primaria compuesta. - var registroDb = await dbContext.EstadosRecuentosGenerales.FindAsync(new object[] { provincia.Id, categoria.Id }, stoppingToken); + if (stoppingToken.IsCancellationRequested) break; - // Si no existe, lo creamos. - if (registroDb == null) + // Usamos GetResultados sin seccionId/municipioId para obtener el resumen del distrito. + var resultadosDto = await _apiService.GetResultadosAsync(authToken, provincia.DistritoId!, null, null, categoria.Id); + + if (resultadosDto?.ValoresTotalizadosPositivos is { Count: > 0 } nuevosVotos) { - registroDb = new EstadoRecuentoGeneral { AmbitoGeograficoId = provincia.Id, CategoriaId = categoria.Id }; - dbContext.EstadosRecuentosGenerales.Add(registroDb); + // Usamos una transacción para asegurar que el borrado y la inserción sean atómicos. + await using var transaction = await dbContext.Database.BeginTransactionAsync(stoppingToken); + + // A. Borrar los resúmenes viejos SOLO para esta provincia y categoría. + await dbContext.ResumenesVotos + .Where(rv => rv.AmbitoGeograficoId == provincia.Id && rv.CategoriaId == categoria.Id) + .ExecuteDeleteAsync(stoppingToken); + + // B. Añadir los nuevos resúmenes. + foreach (var voto in nuevosVotos) + { + dbContext.ResumenesVotos.Add(new ResumenVoto + { + AmbitoGeograficoId = provincia.Id, + CategoriaId = categoria.Id, + AgrupacionPoliticaId = voto.IdAgrupacion, + Votos = voto.Votos, + VotosPorcentaje = voto.VotosPorcentaje + }); + } + + // C. Guardar los cambios en la tabla ResumenesVotos. + await dbContext.SaveChangesAsync(stoppingToken); + + // No es necesario actualizar EstadosRecuentosGenerales aquí, + // ya que el método SondearEstadoRecuentoGeneralAsync se encarga de eso + // de forma más específica y eficiente. + + await transaction.CommitAsync(stoppingToken); } + } // Fin bucle categorías + } // Fin bucle provincias - // Parseamos la fecha de forma segura para evitar errores con cadenas vacías o nulas. - if (DateTime.TryParse(resumenDto.FechaTotalizacion, out var parsedDate)) - { - registroDb.FechaTotalizacion = parsedDate.ToUniversalTime(); - } - - // Mapeamos el resto de los datos del estado del recuento. - registroDb.MesasEsperadas = resumenDto.EstadoRecuento.MesasEsperadas; - registroDb.MesasTotalizadas = resumenDto.EstadoRecuento.MesasTotalizadas; - registroDb.MesasTotalizadasPorcentaje = resumenDto.EstadoRecuento.MesasTotalizadasPorcentaje; - registroDb.CantidadElectores = resumenDto.EstadoRecuento.CantidadElectores; - registroDb.CantidadVotantes = resumenDto.EstadoRecuento.CantidadVotantes; - registroDb.ParticipacionPorcentaje = resumenDto.EstadoRecuento.ParticipacionPorcentaje; - } - - // 3. CONFIRMAR Y GUARDAR - // Guardamos todos los cambios preparados (DELETEs, INSERTs, UPDATEs) en la base de datos. - await dbContext.SaveChangesAsync(stoppingToken); - // Confirmamos la transacción para hacer los cambios permanentes. - await transaction.CommitAsync(stoppingToken); - - _logger.LogInformation("Sondeo de Resumen Provincial completado. Las tablas han sido actualizadas."); - } - else - { - // Si la API no devolvió datos (ej. devuelve null), no hacemos nada en la BD. - _logger.LogInformation("Sondeo de Resumen Provincial completado. No se recibieron datos nuevos."); - } + _logger.LogInformation("Sondeo de Resúmenes Provinciales completado."); } catch (OperationCanceledException) { - _logger.LogInformation("Sondeo de resumen provincial cancelado."); + _logger.LogInformation("Sondeo de resúmenes provinciales cancelado."); } catch (Exception ex) { - // Capturamos cualquier otro error inesperado para que el worker no se detenga. - _logger.LogError(ex, "Ocurrió un error CRÍTICO en el sondeo de Resumen Provincial."); + _logger.LogError(ex, "Ocurrió un error CRÍTICO en el sondeo de Resúmenes Provinciales."); } } diff --git a/Elecciones-Web/src/Elecciones.Worker/LowPriorityDataWorker.cs b/Elecciones-Web/src/Elecciones.Worker/LowPriorityDataWorker.cs index 4d8be21..f7efd21 100644 --- a/Elecciones-Web/src/Elecciones.Worker/LowPriorityDataWorker.cs +++ b/Elecciones-Web/src/Elecciones.Worker/LowPriorityDataWorker.cs @@ -195,119 +195,89 @@ public class LowPriorityDataWorker : BackgroundService } /// - /// Obtiene y actualiza el resumen de votos y el estado del recuento a nivel provincial. - /// Esta versión actualizada guarda tanto los votos por agrupación (en ResumenesVotos) - /// como el estado general del recuento, incluyendo la fecha de totalización (en EstadosRecuentosGenerales), - /// asegurando que toda la operación sea atómica mediante una transacción de base de datos. + /// Obtiene y actualiza el resumen de votos y el estado del recuento a nivel provincial para CADA categoría. + /// Este método itera sobre todas las provincias y categorías, obteniendo sus resultados consolidados + /// y guardándolos en las tablas 'ResumenesVotos' y 'EstadosRecuentosGenerales'. /// - /// El token de autenticación válido para la sesión. - /// El token de cancelación para detener la operación. private async Task SondearResumenProvincialAsync(string authToken, CancellationToken stoppingToken) { try { - // Creamos un scope de DbContext para esta operación. + _logger.LogInformation("Iniciando sondeo de Resúmenes Provinciales..."); + using var scope = _serviceProvider.CreateScope(); var dbContext = scope.ServiceProvider.GetRequiredService(); - // Obtenemos el registro de la Provincia (NivelId 10). - var provincia = await dbContext.AmbitosGeograficos + var provinciasASondear = await dbContext.AmbitosGeograficos .AsNoTracking() - .FirstOrDefaultAsync(a => a.NivelId == 10, stoppingToken); + .Where(a => a.NivelId == 10 && a.DistritoId != null) + .ToListAsync(stoppingToken); - // Si no encontramos el ámbito de la provincia, no podemos continuar. - if (provincia == null) + var todasLasCategorias = await dbContext.CategoriasElectorales + .AsNoTracking() + .ToListAsync(stoppingToken); + + if (!provinciasASondear.Any() || !todasLasCategorias.Any()) { - _logger.LogWarning("No se encontró el ámbito 'Provincia' (NivelId 10) para el sondeo de resumen."); + _logger.LogWarning("No se encontraron Provincias o Categorías para sondear resúmenes."); return; } - // Llamamos a la API para obtener el resumen de datos provincial. - var resumenDto = await _apiService.GetResumenAsync(authToken, provincia.DistritoId!); - - // Solo procedemos si la API devolvió una respuesta válida y no nula. - if (resumenDto != null) + foreach (var provincia in provinciasASondear) { - // Iniciamos una transacción explícita. Esto garantiza que todas las operaciones de base de datos - // dentro de este bloque (el DELETE, los INSERTs y los UPDATEs) se completen con éxito, - // o si algo falla, se reviertan todas, manteniendo la consistencia de los datos. - await using var transaction = await dbContext.Database.BeginTransactionAsync(stoppingToken); + if (stoppingToken.IsCancellationRequested) break; - // --- 1. ACTUALIZAR LA TABLA 'ResumenesVotos' --- - - // Verificamos si la respuesta contiene una lista de votos positivos. - if (resumenDto.ValoresTotalizadosPositivos is { Count: > 0 } nuevosVotos) - { - // Estrategia "Borrar y Reemplazar": vaciamos la tabla antes de insertar los nuevos datos. - await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM ResumenesVotos", stoppingToken); - - // Añadimos cada nuevo registro de voto al DbContext. - foreach (var voto in nuevosVotos) - { - dbContext.ResumenesVotos.Add(new ResumenVoto - { - AmbitoGeograficoId = provincia.Id, - AgrupacionPoliticaId = voto.IdAgrupacion, - Votos = voto.Votos, - VotosPorcentaje = voto.VotosPorcentaje - }); - } - } - - // --- 2. ACTUALIZAR LA TABLA 'EstadosRecuentosGenerales' --- - - // El endpoint de Resumen no especifica una categoría, por lo que aplicamos sus datos de estado de recuento - // a todas las categorías que tenemos en nuestra base de datos. - var todasLasCategorias = await dbContext.CategoriasElectorales.AsNoTracking().ToListAsync(stoppingToken); foreach (var categoria in todasLasCategorias) { - // Buscamos el registro existente usando la clave primaria compuesta. - var registroDb = await dbContext.EstadosRecuentosGenerales.FindAsync(new object[] { provincia.Id, categoria.Id }, stoppingToken); + if (stoppingToken.IsCancellationRequested) break; - // Si no existe, lo creamos. - if (registroDb == null) + // Usamos GetResultados sin seccionId/municipioId para obtener el resumen del distrito. + var resultadosDto = await _apiService.GetResultadosAsync(authToken, provincia.DistritoId!, null, null, categoria.Id); + + if (resultadosDto?.ValoresTotalizadosPositivos is { Count: > 0 } nuevosVotos) { - registroDb = new EstadoRecuentoGeneral { AmbitoGeograficoId = provincia.Id, CategoriaId = categoria.Id }; - dbContext.EstadosRecuentosGenerales.Add(registroDb); + // Usamos una transacción para asegurar que el borrado y la inserción sean atómicos. + await using var transaction = await dbContext.Database.BeginTransactionAsync(stoppingToken); + + // A. Borrar los resúmenes viejos SOLO para esta provincia y categoría. + await dbContext.ResumenesVotos + .Where(rv => rv.AmbitoGeograficoId == provincia.Id && rv.CategoriaId == categoria.Id) + .ExecuteDeleteAsync(stoppingToken); + + // B. Añadir los nuevos resúmenes. + foreach (var voto in nuevosVotos) + { + dbContext.ResumenesVotos.Add(new ResumenVoto + { + AmbitoGeograficoId = provincia.Id, + CategoriaId = categoria.Id, + AgrupacionPoliticaId = voto.IdAgrupacion, + Votos = voto.Votos, + VotosPorcentaje = voto.VotosPorcentaje + }); + } + + // C. Guardar los cambios en la tabla ResumenesVotos. + await dbContext.SaveChangesAsync(stoppingToken); + + // No es necesario actualizar EstadosRecuentosGenerales aquí, + // ya que el método SondearEstadoRecuentoGeneralAsync se encarga de eso + // de forma más específica y eficiente. + + await transaction.CommitAsync(stoppingToken); } + } // Fin bucle categorías + } // Fin bucle provincias - // Parseamos la fecha de forma segura para evitar errores con cadenas vacías o nulas. - if (DateTime.TryParse(resumenDto.FechaTotalizacion, out var parsedDate)) - { - registroDb.FechaTotalizacion = parsedDate.ToUniversalTime(); - } - - // Mapeamos el resto de los datos del estado del recuento. - registroDb.MesasEsperadas = resumenDto.EstadoRecuento.MesasEsperadas; - registroDb.MesasTotalizadas = resumenDto.EstadoRecuento.MesasTotalizadas; - registroDb.MesasTotalizadasPorcentaje = resumenDto.EstadoRecuento.MesasTotalizadasPorcentaje; - registroDb.CantidadElectores = resumenDto.EstadoRecuento.CantidadElectores; - registroDb.CantidadVotantes = resumenDto.EstadoRecuento.CantidadVotantes; - registroDb.ParticipacionPorcentaje = resumenDto.EstadoRecuento.ParticipacionPorcentaje; - } - - // 3. CONFIRMAR Y GUARDAR - // Guardamos todos los cambios preparados (DELETEs, INSERTs, UPDATEs) en la base de datos. - await dbContext.SaveChangesAsync(stoppingToken); - // Confirmamos la transacción para hacer los cambios permanentes. - await transaction.CommitAsync(stoppingToken); - - _logger.LogInformation("Sondeo de Resumen Provincial completado. Las tablas han sido actualizadas."); - } - else - { - // Si la API no devolvió datos (ej. devuelve null), no hacemos nada en la BD. - _logger.LogInformation("Sondeo de Resumen Provincial completado. No se recibieron datos nuevos."); - } + _logger.LogInformation("Sondeo de Resúmenes Provinciales completado."); } catch (OperationCanceledException) { - _logger.LogInformation("Sondeo de resumen provincial cancelado."); + _logger.LogInformation("Sondeo de resúmenes provinciales cancelado."); } catch (Exception ex) { - // Capturamos cualquier otro error inesperado para que el worker no se detenga. - _logger.LogError(ex, "Ocurrió un error CRÍTICO en el sondeo de Resumen Provincial."); + _logger.LogError(ex, "Ocurrió un error CRÍTICO en el sondeo de Resúmenes Provinciales."); } } diff --git a/Elecciones-Web/src/Elecciones.Worker/appsettings.Development.json b/Elecciones-Web/src/Elecciones.Worker/appsettings.Development.json index 0bc8ea4..5277cb6 100644 --- a/Elecciones-Web/src/Elecciones.Worker/appsettings.Development.json +++ b/Elecciones-Web/src/Elecciones.Worker/appsettings.Development.json @@ -6,7 +6,7 @@ } }, "ElectoralApi": { - "BaseUrl": "https://api.eleccionesbonaerenses.gba.gob.ar", + "BaseUrl": "https://api.resultados.gob.ar", "Username": "30500094156@elecciones2025.onmicrosoft.com", "Password": "PTP847elec" }, diff --git a/Elecciones-Web/src/Elecciones.Worker/obj/Debug/net9.0/Elecciones.Worker.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Worker/obj/Debug/net9.0/Elecciones.Worker.AssemblyInfo.cs index 69189f4..f73d138 100644 --- a/Elecciones-Web/src/Elecciones.Worker/obj/Debug/net9.0/Elecciones.Worker.AssemblyInfo.cs +++ b/Elecciones-Web/src/Elecciones.Worker/obj/Debug/net9.0/Elecciones.Worker.AssemblyInfo.cs @@ -14,7 +14,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Worker")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+ce4fc52d4ab234dc5c25703d8945a3f79dccebc4")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+84f764390766e1d9716a38464ee478f3d0b75f96")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Worker")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Worker")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]