From 931d0f4e910e07ded9452c21eceea0fafddd7471 Mon Sep 17 00:00:00 2001 From: dmolinari Date: Sat, 16 Aug 2025 13:05:44 -0300 Subject: [PATCH] =?UTF-8?q?Fix=20Campos=20a=C3=B1adidos?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../net9.0/Elecciones.Api.AssemblyInfo.cs | 2 +- .../Debug/net9.0/rjsmcshtml.dswa.cache.json | 2 +- .../Debug/net9.0/rjsmrazor.dswa.cache.json | 2 +- .../src/Elecciones.Core/DTOs/BancaDto.cs | 27 +- .../Elecciones.Core/DTOs/CodigoAmbitoDto.cs | 11 +- .../src/Elecciones.Core/DTOs/VotosOtrosDto.cs | 11 +- .../Elecciones.Core/DTOs/VotosPositivosDto.cs | 8 +- .../net9.0/Elecciones.Core.AssemblyInfo.cs | 2 +- .../Entities/EstadoRecuento.cs | 5 +- .../Entities/ResultadoVoto.cs | 5 +- ...5_AddPercentageFieldsToResults.Designer.cs | 344 ++++++++++++++++++ ...0816155525_AddPercentageFieldsToResults.cs | 62 ++++ .../EleccionesDbContextModelSnapshot.cs | 12 + .../Elecciones.Database.AssemblyInfo.cs | 2 +- .../Elecciones.Infrastructure.AssemblyInfo.cs | 2 +- .../src/Elecciones.Worker/Worker.cs | 94 ++--- .../net9.0/Elecciones.Worker.AssemblyInfo.cs | 2 +- ....Worker.csproj.EntityFrameworkCore.targets | 28 ++ docker-compose.yml | 4 + 19 files changed, 546 insertions(+), 79 deletions(-) create mode 100644 Elecciones-Web/src/Elecciones.Database/Migrations/20250816155525_AddPercentageFieldsToResults.Designer.cs create mode 100644 Elecciones-Web/src/Elecciones.Database/Migrations/20250816155525_AddPercentageFieldsToResults.cs create mode 100644 Elecciones-Web/src/Elecciones.Worker/obj/Elecciones.Worker.csproj.EntityFrameworkCore.targets 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 c17e362..3d345a0 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+75ff9d5593b957c5ae0d08223a689a95181172d5")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+69ddf2b2d24d4968c618c6fd9f38c1143625cdcd")] [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 b1b6929..099cadb 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":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","/FHWuH7ftxc5u992j4YhVijd0fBiiQLWe\u002BV0ZlveX5c="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","jLJZbvuuUsGPkZf3QtwRFQTqJiXdNIIW3av7i2nQ\u002B30=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","BwAWLB3mTJ9blXh5ZTZOjcrdnzPEd9wZsoNfmceZfb8="],"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 11862fb..2cef5ef 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":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","/FHWuH7ftxc5u992j4YhVijd0fBiiQLWe\u002BV0ZlveX5c="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","jLJZbvuuUsGPkZf3QtwRFQTqJiXdNIIW3av7i2nQ\u002B30=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","BwAWLB3mTJ9blXh5ZTZOjcrdnzPEd9wZsoNfmceZfb8="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Core/DTOs/BancaDto.cs b/Elecciones-Web/src/Elecciones.Core/DTOs/BancaDto.cs index 2fc2a0e..907bc33 100644 --- a/Elecciones-Web/src/Elecciones.Core/DTOs/BancaDto.cs +++ b/Elecciones-Web/src/Elecciones.Core/DTOs/BancaDto.cs @@ -1,20 +1,27 @@ -// src/Elecciones.Core/DTOs/BancaDto.cs +// Archivo: Elecciones.Core/DTOs/BancaDto.cs using System.Text.Json.Serialization; namespace Elecciones.Core.DTOs; public class BancaDto { - [JsonPropertyName("idAgrupacion")] - public string IdAgrupacion { get; set; } = null!; - [JsonPropertyName("nombreAgrupacion")] - public string NombreAgrupacion { get; set; } = null!; + [JsonPropertyName("idAgrupacion")] + public string IdAgrupacion { get; set; } = null!; + + [JsonPropertyName("nombreAgrupacion")] + public string NombreAgrupacion { get; set; } = null!; - [JsonPropertyName("nroBancas")] - public int NroBancas { get; set; } + [JsonPropertyName("idAgrupacionTelegrama")] + public string? IdAgrupacionTelegrama { get; set; } - public class RepartoBancasDto - { + [JsonPropertyName("nroBancas")] + public int NroBancas { get; set; } +} + +public class RepartoBancasDto +{ + [JsonPropertyName("fechaTotalizacion")] + public string? FechaTotalizacion { get; set; } + [JsonPropertyName("repartoBancas")] public List RepartoBancas { get; set; } = []; - } } \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Core/DTOs/CodigoAmbitoDto.cs b/Elecciones-Web/src/Elecciones.Core/DTOs/CodigoAmbitoDto.cs index ce9aa5a..5886b4d 100644 --- a/Elecciones-Web/src/Elecciones.Core/DTOs/CodigoAmbitoDto.cs +++ b/Elecciones-Web/src/Elecciones.Core/DTOs/CodigoAmbitoDto.cs @@ -1,4 +1,3 @@ -// src/Elecciones.Core/DTOs/CodigoAmbitoDto.cs using System.Text.Json.Serialization; namespace Elecciones.Core.DTOs; @@ -8,7 +7,6 @@ public class CodigoAmbitoDto [JsonPropertyName("distritoId")] public string DistritoId { get; set; } = null!; - // Hacemos que los demás IDs acepten nulos para ser más flexibles [JsonPropertyName("seccionProvincialId")] public string? SeccionProvincialId { get; set; } @@ -17,4 +15,13 @@ public class CodigoAmbitoDto [JsonPropertyName("municipioId")] public string? MunicipioId { get; set; } + + [JsonPropertyName("circuitoId")] + public string? CircuitoId { get; set; } + + [JsonPropertyName("establecimientoId")] + public string? EstablecimientoId { get; set; } + + [JsonPropertyName("mesaId")] + public string? MesaId { get; set; } } \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Core/DTOs/VotosOtrosDto.cs b/Elecciones-Web/src/Elecciones.Core/DTOs/VotosOtrosDto.cs index 7a89c27..f3e97bd 100644 --- a/Elecciones-Web/src/Elecciones.Core/DTOs/VotosOtrosDto.cs +++ b/Elecciones-Web/src/Elecciones.Core/DTOs/VotosOtrosDto.cs @@ -1,4 +1,4 @@ -// src/Elecciones.Core/DTOs/VotosOtrosDto.cs +// Archivo: Elecciones.Core/DTOs/VotosOtrosDto.cs using System.Text.Json.Serialization; namespace Elecciones.Core.DTOs; @@ -7,10 +7,19 @@ public class VotosOtrosDto { [JsonPropertyName("votosNulos")] public long VotosNulos { get; set; } + + [JsonPropertyName("votosNulosPorcentaje")] + public decimal VotosNulosPorcentaje { get; set; } [JsonPropertyName("votosEnBlanco")] public long VotosEnBlanco { get; set; } + + [JsonPropertyName("votosEnBlancoPorcentaje")] + public decimal VotosEnBlancoPorcentaje { get; set; } [JsonPropertyName("votosRecurridosComandoImpugnados")] public long VotosRecurridos { get; set; } + + [JsonPropertyName("votosRecurridosComandoImpugnadosPorcentaje")] + public decimal VotosRecurridosPorcentaje { get; set; } } \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Core/DTOs/VotosPositivosDto.cs b/Elecciones-Web/src/Elecciones.Core/DTOs/VotosPositivosDto.cs index 5635828..3de79d0 100644 --- a/Elecciones-Web/src/Elecciones.Core/DTOs/VotosPositivosDto.cs +++ b/Elecciones-Web/src/Elecciones.Core/DTOs/VotosPositivosDto.cs @@ -1,4 +1,4 @@ -// src/Elecciones.Core/DTOs/VotosPositivosDto.cs +// Archivo: Elecciones.Core/DTOs/VotosPositivosDto.cs using System.Text.Json.Serialization; namespace Elecciones.Core.DTOs; @@ -10,7 +10,13 @@ public class VotosPositivosDto [JsonPropertyName("nombreAgrupacion")] public string NombreAgrupacion { get; set; } = null!; + + [JsonPropertyName("idAgrupacionTelegrama")] + public string? IdAgrupacionTelegrama { get; set; } [JsonPropertyName("votos")] public long Votos { get; set; } + + [JsonPropertyName("votosPorcentaje")] + public decimal VotosPorcentaje { get; set; } } \ 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 677a49a..4532c1d 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+75ff9d5593b957c5ae0d08223a689a95181172d5")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+69ddf2b2d24d4968c618c6fd9f38c1143625cdcd")] [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/Entities/EstadoRecuento.cs b/Elecciones-Web/src/Elecciones.Database/Entities/EstadoRecuento.cs index 5cb8737..eb01633 100644 --- a/Elecciones-Web/src/Elecciones.Database/Entities/EstadoRecuento.cs +++ b/Elecciones-Web/src/Elecciones.Database/Entities/EstadoRecuento.cs @@ -1,4 +1,4 @@ -// src/Elecciones.Database/Entities/EstadoRecuento.cs +// Archivo: Elecciones.Database/Entities/EstadoRecuento.cs using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations; @@ -21,4 +21,7 @@ public class EstadoRecuento public long VotosNulos { get; set; } public long VotosEnBlanco { get; set; } public long VotosRecurridos { get; set; } + public decimal VotosNulosPorcentaje { get; set; } + public decimal VotosEnBlancoPorcentaje { get; set; } + public decimal VotosRecurridosPorcentaje { get; set; } } \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Database/Entities/ResultadoVoto.cs b/Elecciones-Web/src/Elecciones.Database/Entities/ResultadoVoto.cs index d28a52c..eb7022a 100644 --- a/Elecciones-Web/src/Elecciones.Database/Entities/ResultadoVoto.cs +++ b/Elecciones-Web/src/Elecciones.Database/Entities/ResultadoVoto.cs @@ -1,4 +1,4 @@ -// src/Elecciones.Database/Entities/ResultadoVoto.cs +// Archivo: Elecciones.Database/Entities/ResultadoVoto.cs using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; @@ -10,7 +10,6 @@ public class ResultadoVoto [DatabaseGenerated(DatabaseGeneratedOption.Identity)] public long Id { get; set; } - // Relaciones public int AmbitoGeograficoId { get; set; } [ForeignKey("AmbitoGeograficoId")] public AmbitoGeografico AmbitoGeografico { get; set; } = null!; @@ -21,4 +20,6 @@ public class ResultadoVoto // Datos public long CantidadVotos { get; set; } + + public decimal PorcentajeVotos { get; set; } } \ No newline at end of file diff --git a/Elecciones-Web/src/Elecciones.Database/Migrations/20250816155525_AddPercentageFieldsToResults.Designer.cs b/Elecciones-Web/src/Elecciones.Database/Migrations/20250816155525_AddPercentageFieldsToResults.Designer.cs new file mode 100644 index 0000000..fb81f57 --- /dev/null +++ b/Elecciones-Web/src/Elecciones.Database/Migrations/20250816155525_AddPercentageFieldsToResults.Designer.cs @@ -0,0 +1,344 @@ +// +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("20250816155525_AddPercentageFieldsToResults")] + partial class AddPercentageFieldsToResults + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "9.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b => + { + b.Property("Id") + .HasColumnType("nvarchar(450)"); + + b.Property("IdTelegrama") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + b.Property("Nombre") + .IsRequired() + .HasColumnType("nvarchar(max)"); + + 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.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.EstadoRecuento", b => + { + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("CantidadElectores") + .HasColumnType("int"); + + b.Property("CantidadVotantes") + .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") + .HasColumnType("decimal(18,2)"); + + b.Property("VotosNulos") + .HasColumnType("bigint"); + + b.Property("VotosNulosPorcentaje") + .HasColumnType("decimal(18,2)"); + + b.Property("VotosRecurridos") + .HasColumnType("bigint"); + + b.Property("VotosRecurridosPorcentaje") + .HasColumnType("decimal(18,2)"); + + b.HasKey("AmbitoGeograficoId"); + + b.ToTable("EstadosRecuentos"); + }); + + modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b => + { + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("CantidadElectores") + .HasColumnType("int"); + + b.Property("CantidadVotantes") + .HasColumnType("int"); + + 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"); + + b.ToTable("EstadosRecuentosGenerales"); + }); + + 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("NroBancas") + .HasColumnType("int"); + + b.HasKey("Id"); + + b.HasIndex("AgrupacionPoliticaId"); + + b.HasIndex("AmbitoGeograficoId"); + + 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("PorcentajeVotos") + .HasColumnType("decimal(18,2)"); + + b.HasKey("Id"); + + b.HasIndex("AgrupacionPoliticaId"); + + b.HasIndex("AmbitoGeograficoId", "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(max)"); + + b.Property("AmbitoGeograficoId") + .HasColumnType("int"); + + b.Property("Votos") + .HasColumnType("bigint"); + + b.Property("VotosPorcentaje") + .HasPrecision(5, 2) + .HasColumnType("decimal(5,2)"); + + b.HasKey("Id"); + + 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("FechaEscaneo") + .HasColumnType("datetime2"); + + b.Property("FechaTotalizacion") + .HasColumnType("datetime2"); + + b.HasKey("Id"); + + b.ToTable("Telegramas"); + }); + + 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.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"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Elecciones-Web/src/Elecciones.Database/Migrations/20250816155525_AddPercentageFieldsToResults.cs b/Elecciones-Web/src/Elecciones.Database/Migrations/20250816155525_AddPercentageFieldsToResults.cs new file mode 100644 index 0000000..fc351ac --- /dev/null +++ b/Elecciones-Web/src/Elecciones.Database/Migrations/20250816155525_AddPercentageFieldsToResults.cs @@ -0,0 +1,62 @@ +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Elecciones.Database.Migrations +{ + /// + public partial class AddPercentageFieldsToResults : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.AddColumn( + name: "PorcentajeVotos", + table: "ResultadosVotos", + type: "decimal(18,2)", + nullable: false, + defaultValue: 0m); + + migrationBuilder.AddColumn( + name: "VotosEnBlancoPorcentaje", + table: "EstadosRecuentos", + type: "decimal(18,2)", + nullable: false, + defaultValue: 0m); + + migrationBuilder.AddColumn( + name: "VotosNulosPorcentaje", + table: "EstadosRecuentos", + type: "decimal(18,2)", + nullable: false, + defaultValue: 0m); + + migrationBuilder.AddColumn( + name: "VotosRecurridosPorcentaje", + table: "EstadosRecuentos", + type: "decimal(18,2)", + nullable: false, + defaultValue: 0m); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropColumn( + name: "PorcentajeVotos", + table: "ResultadosVotos"); + + migrationBuilder.DropColumn( + name: "VotosEnBlancoPorcentaje", + table: "EstadosRecuentos"); + + migrationBuilder.DropColumn( + name: "VotosNulosPorcentaje", + table: "EstadosRecuentos"); + + migrationBuilder.DropColumn( + name: "VotosRecurridosPorcentaje", + table: "EstadosRecuentos"); + } + } +} diff --git a/Elecciones-Web/src/Elecciones.Database/Migrations/EleccionesDbContextModelSnapshot.cs b/Elecciones-Web/src/Elecciones.Database/Migrations/EleccionesDbContextModelSnapshot.cs index ddf3f36..85d673d 100644 --- a/Elecciones-Web/src/Elecciones.Database/Migrations/EleccionesDbContextModelSnapshot.cs +++ b/Elecciones-Web/src/Elecciones.Database/Migrations/EleccionesDbContextModelSnapshot.cs @@ -129,12 +129,21 @@ namespace Elecciones.Database.Migrations b.Property("VotosEnBlanco") .HasColumnType("bigint"); + b.Property("VotosEnBlancoPorcentaje") + .HasColumnType("decimal(18,2)"); + b.Property("VotosNulos") .HasColumnType("bigint"); + b.Property("VotosNulosPorcentaje") + .HasColumnType("decimal(18,2)"); + b.Property("VotosRecurridos") .HasColumnType("bigint"); + b.Property("VotosRecurridosPorcentaje") + .HasColumnType("decimal(18,2)"); + b.HasKey("AmbitoGeograficoId"); b.ToTable("EstadosRecuentos"); @@ -215,6 +224,9 @@ namespace Elecciones.Database.Migrations b.Property("CantidadVotos") .HasColumnType("bigint"); + b.Property("PorcentajeVotos") + .HasColumnType("decimal(18,2)"); + b.HasKey("Id"); b.HasIndex("AgrupacionPoliticaId"); 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 2abc522..47ff514 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+75ff9d5593b957c5ae0d08223a689a95181172d5")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+69ddf2b2d24d4968c618c6fd9f38c1143625cdcd")] [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/obj/Debug/net9.0/Elecciones.Infrastructure.AssemblyInfo.cs b/Elecciones-Web/src/Elecciones.Infrastructure/obj/Debug/net9.0/Elecciones.Infrastructure.AssemblyInfo.cs index 55f9a1d..a18c32c 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+527839dd6deeb2314e8edc9f7f83edc264a0ea61")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+69ddf2b2d24d4968c618c6fd9f38c1143625cdcd")] [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/Worker.cs b/Elecciones-Web/src/Elecciones.Worker/Worker.cs index 0449b3f..b33bf6a 100644 --- a/Elecciones-Web/src/Elecciones.Worker/Worker.cs +++ b/Elecciones-Web/src/Elecciones.Worker/Worker.cs @@ -174,116 +174,100 @@ public class Worker : BackgroundService 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 con la sincronización."); + _logger.LogWarning("No se recibieron datos del catálogo de Categorías."); return; } - var distinctCategorias = categoriasApi - .GroupBy(c => c.CategoriaId) - .Select(g => g.First()) - .OrderBy(c => c.Orden) - .ToList(); - + var distinctCategorias = categoriasApi.GroupBy(c => c.CategoriaId).Select(g => g.First()).OrderBy(c => c.Orden).ToList(); _logger.LogInformation("Se procesarán {count} categorías electorales.", distinctCategorias.Count); 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)) + if (!categoriasEnDb.ContainsKey(categoriaDto.CategoriaId)) { - // 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, - Nombre = categoriaDto.Nombre, - Orden = categoriaDto.Orden - }); + dbContext.CategoriasElectorales.Add(new CategoriaElectoral { Id = categoriaDto.CategoriaId, Nombre = categoriaDto.Nombre, Orden = categoriaDto.Orden }); } } + // Guardamos las categorías primero para asegurar que existan para los siguientes pasos + await dbContext.SaveChangesAsync(stoppingToken); + + + // --- 2. SINCRONIZAR ÁMBITOS Y AGRUPACIONES --- + // Cargamos los catálogos existentes en memoria UNA SOLA VEZ para eficiencia. + var ambitosEnDb = await dbContext.AmbitosGeograficos.ToDictionaryAsync( + a => (a.DistritoId, a.SeccionId, a.MunicipioId, a.CircuitoId, a.EstablecimientoId), + a => a, stoppingToken); + + var agrupacionesEnDb = await dbContext.AgrupacionesPoliticas.ToDictionaryAsync(a => a.Id, a => a, stoppingToken); - // --- 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); + _logger.LogInformation("--- Sincronizando datos para la categoría: {Nombre} (ID: {Id}) ---", categoria.Nombre, categoria.CategoriaId); var catalogoDto = await _apiService.GetCatalogoAmbitosAsync(_authToken, categoria.CategoriaId); if (catalogoDto != null) { // 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)) + // CLAVE ÚNICA CORREGIDA Y MÁS COMPLETA + var claveUnica = ( + ambitoDto.CodigoAmbitos.DistritoId, + ambitoDto.CodigoAmbitos.SeccionId, + ambitoDto.CodigoAmbitos.MunicipioId, + ambitoDto.CodigoAmbitos.CircuitoId, + ambitoDto.CodigoAmbitos.EstablecimientoId + ); + + if (!ambitosEnDb.ContainsKey(claveUnica)) { - // Actualizar datos descriptivos - ambitoExistente.Nombre = ambitoDto.Nombre; - ambitoExistente.NivelId = ambitoDto.NivelId; - } - else - { - // Añadir nuevo ámbito - dbContext.AmbitosGeograficos.Add(new AmbitoGeografico + var nuevoAmbito = new AmbitoGeografico { Nombre = ambitoDto.Nombre, NivelId = ambitoDto.NivelId, DistritoId = ambitoDto.CodigoAmbitos.DistritoId, SeccionId = ambitoDto.CodigoAmbitos.SeccionId, MunicipioId = ambitoDto.CodigoAmbitos.MunicipioId, + CircuitoId = ambitoDto.CodigoAmbitos.CircuitoId, + EstablecimientoId = ambitoDto.CodigoAmbitos.EstablecimientoId, SeccionProvincialId = ambitoDto.CodigoAmbitos.SeccionProvincialId - }); + }; + dbContext.AmbitosGeograficos.Add(nuevoAmbito); + ambitosEnDb.Add(claveUnica, nuevoAmbito); // Añadimos al diccionario en memoria para evitar duplicados en el mismo ciclo } } - _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) + if (provincia != null && !string.IsNullOrEmpty(provincia.CodigoAmbitos.DistritoId)) { 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)) + if (!agrupacionesEnDb.ContainsKey(agrupacionDto.IdAgrupacion)) { - // Actualizar datos descriptivos - agrupacionExistente.Nombre = agrupacionDto.NombreAgrupacion; - agrupacionExistente.IdTelegrama = agrupacionDto.IdAgrupacionTelegrama; - } - else - { - // Añadir nueva agrupación - dbContext.AgrupacionesPoliticas.Add(new AgrupacionPolitica + var nuevaAgrupacion = new AgrupacionPolitica { Id = agrupacionDto.IdAgrupacion, IdTelegrama = agrupacionDto.IdAgrupacionTelegrama, Nombre = agrupacionDto.NombreAgrupacion - }); + }; + dbContext.AgrupacionesPoliticas.Add(nuevaAgrupacion); + agrupacionesEnDb.Add(nuevaAgrupacion.Id, nuevaAgrupacion); } } - _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}.", categoria.CategoriaId); - } } // --- 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("{count} nuevos registros de catálogo han sido guardados en la base de datos.", cambiosGuardados); _logger.LogInformation("Sincronización de catálogos maestros finalizada."); } catch (Exception ex) 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 4b1189a..90b45be 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+75ff9d5593b957c5ae0d08223a689a95181172d5")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+69ddf2b2d24d4968c618c6fd9f38c1143625cdcd")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Worker")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Worker")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/Elecciones-Web/src/Elecciones.Worker/obj/Elecciones.Worker.csproj.EntityFrameworkCore.targets b/Elecciones-Web/src/Elecciones.Worker/obj/Elecciones.Worker.csproj.EntityFrameworkCore.targets new file mode 100644 index 0000000..7d6485d --- /dev/null +++ b/Elecciones-Web/src/Elecciones.Worker/obj/Elecciones.Worker.csproj.EntityFrameworkCore.targets @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docker-compose.yml b/docker-compose.yml index 03f730c..6f081bb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -24,6 +24,10 @@ services: - ./.env networks: - shared-net # Solo necesita acceso a la DB y a la API electoral (internet). + volumes: + # Mapea el directorio /app/logs de dentro del contenedor + # a un directorio llamado 'logs-worker' en la raíz de tu proyecto en la máquina local. + - ./logs-worker:/app/logs # No se exponen puertos. # Servicio del Frontend (servido por Nginx)