Feat BancasWidget
This commit is contained in:
		| @@ -160,15 +160,29 @@ public class ResultadosController : ControllerBase | ||||
|     } | ||||
|  | ||||
|  | ||||
|     [HttpGet("bancas/{seccionId}")] | ||||
|     public async Task<IActionResult> GetBancasPorSeccion(string seccionId) | ||||
|     [HttpGet("bancas-por-seccion/{seccionId}/{camara}")] // <-- CAMBIO 1: Modificar la ruta | ||||
|     public async Task<IActionResult> GetBancasPorSeccion(string seccionId, string camara) // <-- CAMBIO 2: Añadir el nuevo parámetro | ||||
|     { | ||||
|         // 1. Buscamos el ámbito usando 'SeccionProvincialId'. | ||||
|         // La API oficial usa este campo para las secciones electorales. | ||||
|         // Además, el worker guarda estas secciones con NivelId = 20, por lo que lo usamos aquí para consistencia. | ||||
|         // Convertimos el string de la cámara a un enum o un valor numérico para la base de datos | ||||
|         // 0 = Diputados, 1 = Senadores. Esto debe coincidir con cómo lo guardas en la DB. | ||||
|         // O puedes usar un enum si lo tienes definido. | ||||
|         int CategoriaId; | ||||
|         if (camara.Equals("diputados", StringComparison.OrdinalIgnoreCase)) | ||||
|         { | ||||
|             CategoriaId = 6; // Asume que 5 es el CategoriaId para Diputados Provinciales | ||||
|         } | ||||
|         else if (camara.Equals("senadores", StringComparison.OrdinalIgnoreCase)) | ||||
|         { | ||||
|             CategoriaId = 5; // Asume que 6 es el CategoriaId para Senadores Provinciales | ||||
|         } | ||||
|         else | ||||
|         { | ||||
|             return BadRequest(new { message = "El tipo de cámara especificado no es válido. Use 'diputados' o 'senadores'." }); | ||||
|         } | ||||
|  | ||||
|         var seccion = await _dbContext.AmbitosGeograficos | ||||
|             .AsNoTracking() | ||||
|             .FirstOrDefaultAsync(a => a.SeccionProvincialId == seccionId && a.NivelId == 20); // Nivel 20 = Sección Electoral Provincial | ||||
|             .FirstOrDefaultAsync(a => a.SeccionProvincialId == seccionId && a.NivelId == 20); | ||||
|  | ||||
|         if (seccion == null) | ||||
|         { | ||||
| @@ -176,14 +190,17 @@ public class ResultadosController : ControllerBase | ||||
|             return NotFound(new { message = $"No se encontró la sección electoral con ID {seccionId}" }); | ||||
|         } | ||||
|  | ||||
|         // 2. Buscamos todas las proyecciones para ese ámbito (usando su clave primaria 'Id') | ||||
|         // --- CAMBIO 3: Filtrar también por el cargo (cámara) --- | ||||
|         var proyecciones = await _dbContext.ProyeccionesBancas | ||||
|             .AsNoTracking() | ||||
|             .Include(p => p.AgrupacionPolitica) | ||||
|             .Where(p => p.AmbitoGeograficoId == seccion.Id) | ||||
|             .Where(p => p.AmbitoGeograficoId == seccion.Id && p.CategoriaId == CategoriaId) // <-- AÑADIDO EL FILTRO | ||||
|             .Select(p => new | ||||
|             { | ||||
|                 AgrupacionId = p.AgrupacionPolitica.Id, // Añadir para el 'key' en React | ||||
|                 AgrupacionNombre = p.AgrupacionPolitica.Nombre, | ||||
|                 NombreCorto = p.AgrupacionPolitica.NombreCorto, // Añadir para el frontend | ||||
|                 Color = p.AgrupacionPolitica.Color, // Añadir para el frontend | ||||
|                 Bancas = p.NroBancas | ||||
|             }) | ||||
|             .OrderByDescending(p => p.Bancas) | ||||
| @@ -191,12 +208,10 @@ public class ResultadosController : ControllerBase | ||||
|  | ||||
|         if (!proyecciones.Any()) | ||||
|         { | ||||
|             // Este caso es posible si aún no hay proyecciones calculadas para esta sección. | ||||
|             _logger.LogWarning("No se encontraron proyecciones de bancas para la sección: {SeccionNombre}", seccion.Nombre); | ||||
|             return NotFound(new { message = $"No se han encontrado proyecciones de bancas para la sección {seccion.Nombre}" }); | ||||
|             _logger.LogWarning("No se encontraron proyecciones de bancas para la sección: {SeccionNombre} y cámara: {Camara}", seccion.Nombre, camara); | ||||
|             return NotFound(new { message = $"No se han encontrado proyecciones de bancas para la sección {seccion.Nombre} ({camara})" }); | ||||
|         } | ||||
|  | ||||
|         // 3. Devolvemos la respuesta | ||||
|         return Ok(new | ||||
|         { | ||||
|             SeccionNombre = seccion.Nombre, | ||||
| @@ -721,4 +736,41 @@ public class ResultadosController : ControllerBase | ||||
|  | ||||
|         return Ok(resultadoFinal); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("secciones-electorales-con-cargos")] | ||||
|     public async Task<IActionResult> GetSeccionesElectoralesConCargos() | ||||
|     { | ||||
|         var secciones = await _dbContext.AmbitosGeograficos | ||||
|             .AsNoTracking() | ||||
|             .Where(a => a.NivelId == 20) // Nivel 20 = Sección Electoral Provincial | ||||
|             .Select(a => new | ||||
|             { | ||||
|                 Id = a.SeccionProvincialId, // Usamos el ID que el frontend espera | ||||
|                 Nombre = a.Nombre, | ||||
|                 // Obtenemos los CategoriaId de las relaciones que tiene esta sección. | ||||
|                 // Esto asume que tienes una tabla que relaciona Ámbitos con Cargos. | ||||
|                 // Por ejemplo, a través de la tabla de Proyecciones o Resultados. | ||||
|                 Cargos = _dbContext.ProyeccionesBancas | ||||
|                             .Where(p => p.AmbitoGeograficoId == a.Id) | ||||
|                             .Select(p => p.CategoriaId) | ||||
|                             .Distinct() | ||||
|                             .ToList() | ||||
|             }) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         // Mapeamos los CategoriaId a los nombres que usa el frontend | ||||
|         var resultado = secciones.Select(s => new | ||||
|         { | ||||
|             s.Id, | ||||
|             s.Nombre, | ||||
|             // Convertimos la lista de IDs de cargo a una lista de strings ("diputados", "senadores") | ||||
|             CamarasDisponibles = s.Cargos.Select(CategoriaId => | ||||
|                 CategoriaId == 6 ? "diputados" : // Asume 5 = Diputados | ||||
|                 CategoriaId == 5 ? "senadores" : // Asume 6 = Senadores | ||||
|                 null | ||||
|             ).Where(c => c != null).ToList() | ||||
|         }); | ||||
|  | ||||
|         return Ok(resultado); | ||||
|     } | ||||
| } | ||||
| @@ -8,32 +8,6 @@ | ||||
|       "Microsoft.AspNetCore": "Warning" | ||||
|     } | ||||
|   }, | ||||
|  | ||||
|   "ComposicionCongreso": { | ||||
|     "Diputados": { | ||||
|       "CamaraNombre": "Cámara de Diputados", | ||||
|       "TotalBancas": 92, | ||||
|       "BancasEnJuego": 46, | ||||
|       "Partidos": [ | ||||
|         { "Id": "501", "Nombre": "CANDIDATURA 501", "BancasTotales": 2, "BancasEnJuego": 1, "Color": "#d62728" }, | ||||
|         { "Id": "513", "Nombre": "CANDIDATURA 513", "BancasTotales": 37, "BancasEnJuego": 19, "Color": "#1f77b4" }, | ||||
|         { "Id": "516", "Nombre": "CANDIDATURA 516", "BancasTotales": 18, "BancasEnJuego": 8, "Color": "#2ca02c" }, | ||||
|         { "Id": "511", "Nombre": "CANDIDATURA 511", "BancasTotales": 22, "BancasEnJuego": 12, "Color": "#ff7f0e" }, | ||||
|         { "Id": "507", "Nombre": "CANDIDATURA 507", "BancasTotales": 13, "BancasEnJuego": 6, "Color": "#9467bd" } | ||||
|       ] | ||||
|     }, | ||||
|     "Senadores": { | ||||
|       "CamaraNombre": "Cámara de Senadores", | ||||
|       "TotalBancas": 46, | ||||
|       "BancasEnJuego": 23, | ||||
|       "Partidos": [ | ||||
|         { "Id": "513_S", "Nombre": "CANDIDATURA 513", "BancasTotales": 21, "BancasEnJuego": 10, "Color": "#1f77b4" }, | ||||
|         { "Id": "516_S", "Nombre": "CANDIDATURA 516", "BancasTotales": 9, "BancasEnJuego": 5, "Color": "#2ca02c" }, | ||||
|         { "Id": "511_S", "Nombre": "CANDIDATURA 511", "BancasTotales": 11, "BancasEnJuego": 6, "Color": "#ff7f0e" }, | ||||
|         { "Id": "507_S", "Nombre": "CANDIDATURA 507", "BancasTotales": 5, "BancasEnJuego": 2, "Color": "#9467bd" } | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
|   "ApiKey": "badb1a38d221c9e23bcf70958840ca7f5a5dc54f2047dadf7ce45b578b5bc3e2", | ||||
|   "Jwt": { | ||||
|     "Key": "badb1a38d221c9e23bcf70958840ca7f5a5dc54f2047dadf7ce45b578b5bc3e2", | ||||
|   | ||||
| @@ -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+32e85b9b9ddc7cd6422bfa52ff3c17fc6eff930b")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+8ce48b3a46c65b51238a04238228d86568680ac2")] | ||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] | ||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["h1yBBcAgq4jIQ1vINVvluRQMeuJlGA3/Zciq/j5c0AM=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","6UbV83RDqihxiPJRSqBBce97kpcbB7parfVbqy/JDrA=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","4a8hgDNqfLAz7U5813iwPnUccUabxTlRH1USsCHCuGA="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","B5JL8yyHqNgMsFpbZP0qsuF4OLsILfK8gQJe8eGu3B0=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","NNlKPM7/7JjN5EwDTVhjwjUKTnDOuh1gXx0T83PZFzk="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["h1yBBcAgq4jIQ1vINVvluRQMeuJlGA3/Zciq/j5c0AM=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","6UbV83RDqihxiPJRSqBBce97kpcbB7parfVbqy/JDrA=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","4a8hgDNqfLAz7U5813iwPnUccUabxTlRH1USsCHCuGA="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","TEsXImnzxFKTIq2f5fiDu7i6Ar/cbecW5MZ3z8Wb/a4=","5WogJu\u002BUPlF\u002BE5mq/ILtDXpVwqwmhHtsEB13nmT5JJk=","B5JL8yyHqNgMsFpbZP0qsuF4OLsILfK8gQJe8eGu3B0=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","NNlKPM7/7JjN5EwDTVhjwjUKTnDOuh1gXx0T83PZFzk="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"O7YawHw32G/Fh2bs+snZgm9O7okI0WYgTQmXM931znY=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["h1yBBcAgq4jIQ1vINVvluRQMeuJlGA3/Zciq/j5c0AM=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"O7YawHw32G/Fh2bs+snZgm9O7okI0WYgTQmXM931znY=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["TyIJk/eQMWjmB5LsDE\u002BZIJC9P9ciVxd7bnzRiTZsGt4=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
		Reference in New Issue
	
	Block a user