Feat Widgets 1540
This commit is contained in:
		| @@ -22,13 +22,11 @@ public class ResultadosController : ControllerBase | ||||
|         _configuration = configuration; | ||||
|     } | ||||
|  | ||||
|     [HttpGet("partido/{seccionId}")] | ||||
|     [HttpGet("partido/{seccionId}")] // 'seccionId' es el ID del municipio | ||||
|     public async Task<IActionResult> GetResultadosPorPartido(string seccionId) | ||||
|     { | ||||
|         // 1. Buscamos el ámbito geográfico correspondiente al PARTIDO (Nivel 30) | ||||
|         var ambito = await _dbContext.AmbitosGeograficos | ||||
|             .AsNoTracking() | ||||
|             // CAMBIO CLAVE: Buscamos por SeccionId y NivelId para ser precisos | ||||
|             .FirstOrDefaultAsync(a => a.SeccionId == seccionId && a.NivelId == 30); | ||||
|  | ||||
|         if (ambito == null) | ||||
| @@ -36,14 +34,12 @@ public class ResultadosController : ControllerBase | ||||
|             return NotFound(new { message = $"No se encontró el partido con ID {seccionId}" }); | ||||
|         } | ||||
|  | ||||
|         // 2. Buscamos el estado del recuento para ese ámbito | ||||
|         var estadoRecuento = await _dbContext.EstadosRecuentos | ||||
|             .AsNoTracking() | ||||
|             .FirstOrDefaultAsync(e => e.AmbitoGeograficoId == ambito.Id); | ||||
|  | ||||
|         if (estadoRecuento == null) | ||||
|         { | ||||
|             // Devolvemos una respuesta vacía pero válida para el frontend | ||||
|             return Ok(new MunicipioResultadosDto | ||||
|             { | ||||
|                 MunicipioNombre = ambito.Nombre, | ||||
| @@ -55,28 +51,57 @@ public class ResultadosController : ControllerBase | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         // 3. Buscamos todos los votos para ese ámbito | ||||
|         // 1. Obtenemos los IDs de las agrupaciones que tienen resultados en este municipio | ||||
|         var agrupacionIds = await _dbContext.ResultadosVotos | ||||
|             .Where(rv => rv.AmbitoGeograficoId == ambito.Id) | ||||
|             .Select(rv => rv.AgrupacionPoliticaId) | ||||
|             .Distinct() | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         // 2. Buscamos TODOS los logos relevantes en una sola consulta: | ||||
|         //    - Los que son para la categoría Concejales (7) | ||||
|         //    - Y pertenecen a los partidos que compiten aquí | ||||
|         //    - Y son genéricos (sin ámbito) O específicos para ESTE municipio | ||||
|         var logosRelevantes = await _dbContext.LogosAgrupacionesCategorias | ||||
|             .AsNoTracking() | ||||
|             .Where(l => l.CategoriaId == 7 && | ||||
|                         agrupacionIds.Contains(l.AgrupacionPoliticaId) && | ||||
|                         (l.AmbitoGeograficoId == null || l.AmbitoGeograficoId == ambito.Id)) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         var resultadosVotos = await _dbContext.ResultadosVotos | ||||
|             .AsNoTracking() | ||||
|             .Include(rv => rv.AgrupacionPolitica) | ||||
|             .Where(rv => rv.AmbitoGeograficoId == ambito.Id) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         // 4. Calculamos el total de votos positivos | ||||
|         long totalVotosPositivos = resultadosVotos.Sum(r => r.CantidadVotos); | ||||
|  | ||||
|         // 5. Mapeamos al DTO de respuesta | ||||
|         var respuestaDto = new MunicipioResultadosDto | ||||
|         { | ||||
|             MunicipioNombre = ambito.Nombre, | ||||
|             UltimaActualizacion = estadoRecuento.FechaTotalizacion, | ||||
|             PorcentajeEscrutado = estadoRecuento.MesasTotalizadasPorcentaje, | ||||
|             PorcentajeParticipacion = estadoRecuento.ParticipacionPorcentaje, | ||||
|             Resultados = resultadosVotos.Select(rv => new AgrupacionResultadoDto | ||||
|             Resultados = resultadosVotos.Select(rv => | ||||
|             { | ||||
|                 Nombre = rv.AgrupacionPolitica.Nombre, | ||||
|                 Votos = rv.CantidadVotos, | ||||
|                 Porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos * 100.0m / totalVotosPositivos) : 0 | ||||
|                 // --- LÓGICA DE FALLBACK --- | ||||
|                 var logoUrl = | ||||
|                     // 1. Buscamos primero el logo específico para este municipio. | ||||
|                     logosRelevantes.FirstOrDefault(l => l.AgrupacionPoliticaId == rv.AgrupacionPoliticaId && l.AmbitoGeograficoId == ambito.Id)?.LogoUrl | ||||
|                     // 2. Si no lo encontramos, buscamos el logo genérico (sin ámbito). | ||||
|                     ?? logosRelevantes.FirstOrDefault(l => l.AgrupacionPoliticaId == rv.AgrupacionPoliticaId && l.AmbitoGeograficoId == null)?.LogoUrl; | ||||
|  | ||||
|                 return new AgrupacionResultadoDto | ||||
|                 { | ||||
|                     Id = rv.AgrupacionPolitica.Id, | ||||
|                     Nombre = rv.AgrupacionPolitica.Nombre, | ||||
|                     NombreCorto = rv.AgrupacionPolitica.NombreCorto, | ||||
|                     Color = rv.AgrupacionPolitica.Color, | ||||
|                     LogoUrl = logoUrl, // Asignamos el logo encontrado | ||||
|                     Votos = rv.CantidadVotos, | ||||
|                     Porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos * 100.0m / totalVotosPositivos) : 0 | ||||
|                 }; | ||||
|             }).OrderByDescending(r => r.Votos).ToList(), | ||||
|             VotosAdicionales = new VotosAdicionalesDto | ||||
|             { | ||||
| @@ -95,15 +120,10 @@ public class ResultadosController : ControllerBase | ||||
|         var provincia = await _dbContext.AmbitosGeograficos.AsNoTracking() | ||||
|             .FirstOrDefaultAsync(a => a.DistritoId == distritoId && a.NivelId == 10); | ||||
|  | ||||
|         var todosLosResumenes = await _dbContext.ResumenesVotos.AsNoTracking() | ||||
|             .Include(r => r.AgrupacionPolitica) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         // OBTENER TODOS LOS LOGOS EN UNA SOLA CONSULTA | ||||
|         var logosLookup = (await _dbContext.LogosAgrupacionesCategorias.AsNoTracking().ToListAsync()) | ||||
|             .ToLookup(l => $"{l.AgrupacionPoliticaId}-{l.CategoriaId}"); | ||||
|  | ||||
|         if (provincia == null) return NotFound($"No se encontró la provincia con distritoId {distritoId}"); | ||||
|         if (provincia == null) | ||||
|         { | ||||
|             return NotFound($"No se encontró la provincia con distritoId {distritoId}"); | ||||
|         } | ||||
|  | ||||
|         var estadosPorCategoria = await _dbContext.EstadosRecuentosGenerales.AsNoTracking() | ||||
|             .Include(e => e.CategoriaElectoral) | ||||
| @@ -113,43 +133,50 @@ public class ResultadosController : ControllerBase | ||||
|         var resultadosPorMunicipio = await _dbContext.ResultadosVotos | ||||
|             .AsNoTracking() | ||||
|             .Include(r => r.AgrupacionPolitica) | ||||
|             .Where(r => r.AmbitoGeografico.NivelId == 30) | ||||
|             .Where(r => r.AmbitoGeografico.NivelId == 30) // Nivel 30 = Municipio | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         var logos = await _dbContext.LogosAgrupacionesCategorias.AsNoTracking().ToListAsync(); | ||||
|  | ||||
|         var resultadosAgrupados = resultadosPorMunicipio | ||||
|             .GroupBy(r => r.CategoriaId) | ||||
|             .Select(g => new | ||||
|             { | ||||
|                 CategoriaId = g.Key, | ||||
|                 CategoriaNombre = estadosPorCategoria.ContainsKey(g.Key) ? estadosPorCategoria[g.Key].CategoriaElectoral.Nombre : "Desconocido", | ||||
|                 EstadoRecuento = estadosPorCategoria.GetValueOrDefault(g.Key), | ||||
|                 TotalVotosCategoria = g.Sum(r => r.CantidadVotos), | ||||
|                 // Agrupamos por el ID de la agrupación, no por el objeto | ||||
|                 Resultados = g.GroupBy(r => r.AgrupacionPoliticaId) | ||||
|                               .Select(partidoGroup => new | ||||
|                               { | ||||
|                                   // El objeto Agrupacion lo tomamos del primer elemento del grupo | ||||
|                                   Agrupacion = partidoGroup.First().AgrupacionPolitica, | ||||
|                                   Votos = partidoGroup.Sum(r => r.CantidadVotos) | ||||
|                               }) | ||||
|                               .ToList() | ||||
|                 Resultados = g | ||||
|                     .GroupBy(r => r.AgrupacionPolitica) | ||||
|                     .Select(partidoGroup => new | ||||
|                     { | ||||
|                         Agrupacion = partidoGroup.Key, | ||||
|                         Votos = partidoGroup.Sum(r => r.CantidadVotos) | ||||
|                     }) | ||||
|                     .OrderByDescending(r => r.Votos) | ||||
|                     .ToList() | ||||
|             }) | ||||
|             .Select(g => new | ||||
|             { | ||||
|                 g.CategoriaId, | ||||
|                 CategoriaNombre = estadosPorCategoria.ContainsKey(g.CategoriaId) ? estadosPorCategoria[g.CategoriaId].CategoriaElectoral.Nombre : "Desconocido", | ||||
|                 EstadoRecuento = estadosPorCategoria.GetValueOrDefault(g.CategoriaId), | ||||
|                 Resultados = g.Resultados | ||||
|                               .Select(r => new | ||||
|                               { | ||||
|                                   r.Agrupacion.Id, | ||||
|                                   r.Agrupacion.Nombre, | ||||
|                                   r.Agrupacion.NombreCorto, | ||||
|                                   r.Agrupacion.Color, | ||||
|                                   LogoUrl = logosLookup[$"{r.Agrupacion.Id}-{g.CategoriaId}"].FirstOrDefault()?.LogoUrl, | ||||
|                                   r.Votos, | ||||
|                                   VotosPorcentaje = g.TotalVotosCategoria > 0 ? ((decimal)r.Votos * 100 / g.TotalVotosCategoria) : 0 | ||||
|                               }) | ||||
|                               .OrderByDescending(r => r.Votos) | ||||
|                               .ToList() | ||||
|                 g.CategoriaNombre, | ||||
|                 g.EstadoRecuento, | ||||
|                 Resultados = g.Resultados.Select(r => | ||||
|                 { | ||||
|                     var logoUrl = logos.FirstOrDefault(l => l.AgrupacionPoliticaId == r.Agrupacion.Id && l.CategoriaId == g.CategoriaId && l.AmbitoGeograficoId != null)?.LogoUrl | ||||
|                                ?? logos.FirstOrDefault(l => l.AgrupacionPoliticaId == r.Agrupacion.Id && l.CategoriaId == g.CategoriaId && l.AmbitoGeograficoId == null)?.LogoUrl; | ||||
|  | ||||
|                     return new | ||||
|                     { | ||||
|                         Id = r.Agrupacion.Id, | ||||
|                         r.Agrupacion.Nombre, | ||||
|                         r.Agrupacion.NombreCorto, | ||||
|                         r.Agrupacion.Color, | ||||
|                         LogoUrl = logoUrl, | ||||
|                         r.Votos, | ||||
|                         Porcentaje = g.TotalVotosCategoria > 0 ? ((decimal)r.Votos * 100 / g.TotalVotosCategoria) : 0 | ||||
|                     }; | ||||
|                 }).ToList() | ||||
|             }) | ||||
|             .OrderBy(c => c.CategoriaId) | ||||
|             .ToList(); | ||||
| @@ -238,10 +265,21 @@ public class ResultadosController : ControllerBase | ||||
|     [HttpGet("municipio/{ambitoId}")] | ||||
|     public async Task<IActionResult> GetResultadosPorMunicipio(int ambitoId, [FromQuery] int categoriaId) | ||||
|     { | ||||
|         _logger.LogInformation("Buscando resultados para AmbitoGeograficoId: {AmbitoId}, CategoriaId: {CategoriaId}", ambitoId, categoriaId); | ||||
|  | ||||
|         // Validamos que el ámbito exista | ||||
|         var ambito = await _dbContext.AmbitosGeograficos.AsNoTracking() | ||||
|             .FirstOrDefaultAsync(a => a.Id == ambitoId && a.NivelId == 30); | ||||
|         if (ambito == null) return NotFound($"No se encontró el municipio con ID {ambitoId}"); | ||||
|         if (ambito == null) | ||||
|         { | ||||
|             _logger.LogWarning("No se encontró el municipio con ID: {AmbitoId}", ambitoId); | ||||
|             return NotFound($"No se encontró el municipio con ID {ambitoId}"); | ||||
|         } | ||||
|  | ||||
|         // Obtenemos el estado del recuento para el ámbito | ||||
|         var estadoRecuento = await _dbContext.EstadosRecuentos | ||||
|             .AsNoTracking() | ||||
|             .FirstOrDefaultAsync(e => e.AmbitoGeograficoId == ambito.Id); | ||||
|  | ||||
|         // Obtenemos los votos para ESE municipio y ESA categoría | ||||
|         var resultadosVotos = await _dbContext.ResultadosVotos | ||||
| @@ -253,18 +291,35 @@ public class ResultadosController : ControllerBase | ||||
|         // Calculamos el total de votos solo para esta selección | ||||
|         var totalVotosPositivos = (decimal)resultadosVotos.Sum(r => r.CantidadVotos); | ||||
|  | ||||
|         // Mapeamos a la respuesta final que espera el frontend | ||||
|         var respuesta = resultadosVotos | ||||
|         // Mapeamos los resultados de los partidos | ||||
|         var resultadosPartidosDto = resultadosVotos | ||||
|             .OrderByDescending(r => r.CantidadVotos) | ||||
|             .Select(rv => new | ||||
|             .Select(rv => new AgrupacionResultadoDto // Assuming AgrupacionResultadoDto is the correct DTO for individual party results | ||||
|             { | ||||
|                 id = rv.AgrupacionPolitica.Id, | ||||
|                 nombre = rv.AgrupacionPolitica.NombreCorto ?? rv.AgrupacionPolitica.Nombre, | ||||
|                 votos = rv.CantidadVotos, | ||||
|                 porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos / totalVotosPositivos) * 100 : 0 | ||||
|                 Id = rv.AgrupacionPolitica.Id, | ||||
|                 Nombre = rv.AgrupacionPolitica.NombreCorto ?? rv.AgrupacionPolitica.Nombre, | ||||
|                 Color = rv.AgrupacionPolitica.Color, | ||||
|                 Votos = rv.CantidadVotos, | ||||
|                 Porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos / totalVotosPositivos) * 100 : 0 | ||||
|             }).ToList(); | ||||
|  | ||||
|         return Ok(respuesta); | ||||
|         // Construimos la respuesta completa del DTO | ||||
|         var respuestaDto = new MunicipioResultadosDto | ||||
|         { | ||||
|             MunicipioNombre = ambito.Nombre, | ||||
|             UltimaActualizacion = estadoRecuento?.FechaTotalizacion ?? DateTime.UtcNow, // Use null-conditional operator | ||||
|             PorcentajeEscrutado = estadoRecuento?.MesasTotalizadasPorcentaje ?? 0, | ||||
|             PorcentajeParticipacion = estadoRecuento?.ParticipacionPorcentaje ?? 0, | ||||
|             Resultados = resultadosPartidosDto, | ||||
|             VotosAdicionales = new VotosAdicionalesDto // Assuming default constructor is fine | ||||
|             { | ||||
|                 EnBlanco = estadoRecuento?.VotosEnBlanco ?? 0, | ||||
|                 Nulos = estadoRecuento?.VotosNulos ?? 0, | ||||
|                 Recurridos = estadoRecuento?.VotosRecurridos ?? 0 | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         return Ok(respuestaDto); | ||||
|     } | ||||
|  | ||||
|     [HttpGet("composicion-congreso")] | ||||
| @@ -504,59 +559,59 @@ public class ResultadosController : ControllerBase | ||||
|     } | ||||
|  | ||||
|     [HttpGet("concejales/{seccionId}")] | ||||
| public async Task<IActionResult> GetResultadosConcejalesPorSeccion(string seccionId) | ||||
| { | ||||
|     var municipiosDeLaSeccion = await _dbContext.AmbitosGeograficos | ||||
|         .AsNoTracking() | ||||
|         .Where(a => a.NivelId == 30 && a.SeccionProvincialId == seccionId) | ||||
|         .Select(a => a.Id) | ||||
|         .ToListAsync(); | ||||
|  | ||||
|     if (!municipiosDeLaSeccion.Any()) | ||||
|     public async Task<IActionResult> GetResultadosConcejalesPorSeccion(string seccionId) | ||||
|     { | ||||
|         return Ok(new List<object>()); | ||||
|         var municipiosDeLaSeccion = await _dbContext.AmbitosGeograficos | ||||
|             .AsNoTracking() | ||||
|             .Where(a => a.NivelId == 30 && a.SeccionProvincialId == seccionId) | ||||
|             .Select(a => a.Id) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         if (!municipiosDeLaSeccion.Any()) | ||||
|         { | ||||
|             return Ok(new List<object>()); | ||||
|         } | ||||
|  | ||||
|         var resultadosMunicipales = await _dbContext.ResultadosVotos | ||||
|             .AsNoTracking() | ||||
|             .Include(r => r.AgrupacionPolitica) | ||||
|             .Where(r => r.CategoriaId == 7 && municipiosDeLaSeccion.Contains(r.AmbitoGeograficoId)) | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         var logosConcejales = await _dbContext.LogosAgrupacionesCategorias | ||||
|             .AsNoTracking() | ||||
|             .Where(l => l.CategoriaId == 7) | ||||
|             .ToDictionaryAsync(l => l.AgrupacionPoliticaId); | ||||
|  | ||||
|         var totalVotosSeccion = (decimal)resultadosMunicipales.Sum(r => r.CantidadVotos); | ||||
|  | ||||
|         var resultadosFinales = resultadosMunicipales | ||||
|             // 1. Agrupamos por el ID del partido para evitar duplicados. | ||||
|             .GroupBy(r => r.AgrupacionPoliticaId) | ||||
|             .Select(g => new | ||||
|             { | ||||
|                 // 2. Obtenemos la entidad completa del primer elemento del grupo. | ||||
|                 Agrupacion = g.First().AgrupacionPolitica, | ||||
|                 Votos = g.Sum(r => r.CantidadVotos) | ||||
|             }) | ||||
|             .OrderByDescending(r => r.Votos) | ||||
|             .Select(r => new | ||||
|             { | ||||
|                 Id = r.Agrupacion.Id, // Aseguramos que el Id esté en el objeto final | ||||
|                 r.Agrupacion.Nombre, | ||||
|                 r.Agrupacion.NombreCorto, | ||||
|                 r.Agrupacion.Color, | ||||
|                 LogoUrl = logosConcejales.GetValueOrDefault(r.Agrupacion.Id)?.LogoUrl, | ||||
|                 Votos = r.Votos, | ||||
|                 // --- CORRECCIÓN CLAVE --- | ||||
|                 // 3. Usamos el nombre de propiedad correcto que el frontend espera: 'votosPorcentaje' | ||||
|                 VotosPorcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0 | ||||
|             }) | ||||
|             .ToList(); | ||||
|  | ||||
|         return Ok(resultadosFinales); | ||||
|     } | ||||
|  | ||||
|     var resultadosMunicipales = await _dbContext.ResultadosVotos | ||||
|         .AsNoTracking() | ||||
|         .Include(r => r.AgrupacionPolitica) | ||||
|         .Where(r => r.CategoriaId == 7 && municipiosDeLaSeccion.Contains(r.AmbitoGeograficoId)) | ||||
|         .ToListAsync(); | ||||
|  | ||||
|     var logosConcejales = await _dbContext.LogosAgrupacionesCategorias | ||||
|         .AsNoTracking() | ||||
|         .Where(l => l.CategoriaId == 7) | ||||
|         .ToDictionaryAsync(l => l.AgrupacionPoliticaId); | ||||
|  | ||||
|     var totalVotosSeccion = (decimal)resultadosMunicipales.Sum(r => r.CantidadVotos); | ||||
|  | ||||
|     var resultadosFinales = resultadosMunicipales | ||||
|         // 1. Agrupamos por el ID del partido para evitar duplicados. | ||||
|         .GroupBy(r => r.AgrupacionPoliticaId)  | ||||
|         .Select(g => new | ||||
|         { | ||||
|             // 2. Obtenemos la entidad completa del primer elemento del grupo. | ||||
|             Agrupacion = g.First().AgrupacionPolitica, | ||||
|             Votos = g.Sum(r => r.CantidadVotos) | ||||
|         }) | ||||
|         .OrderByDescending(r => r.Votos) | ||||
|         .Select(r => new | ||||
|         { | ||||
|             Id = r.Agrupacion.Id, // Aseguramos que el Id esté en el objeto final | ||||
|             r.Agrupacion.Nombre, | ||||
|             r.Agrupacion.NombreCorto, | ||||
|             r.Agrupacion.Color, | ||||
|             LogoUrl = logosConcejales.GetValueOrDefault(r.Agrupacion.Id)?.LogoUrl, | ||||
|             Votos = r.Votos, | ||||
|             // --- CORRECCIÓN CLAVE --- | ||||
|             // 3. Usamos el nombre de propiedad correcto que el frontend espera: 'votosPorcentaje' | ||||
|             VotosPorcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0 | ||||
|         }) | ||||
|         .ToList(); | ||||
|  | ||||
|     return Ok(resultadosFinales); | ||||
| } | ||||
|  | ||||
|     [HttpGet("mapa-por-seccion")] | ||||
|     public async Task<IActionResult> GetResultadosMapaPorSeccion([FromQuery] int categoriaId) | ||||
|     { | ||||
| @@ -616,12 +671,13 @@ public async Task<IActionResult> GetResultadosConcejalesPorSeccion(string seccio | ||||
|             .ToListAsync(); | ||||
|  | ||||
|         var totalVotosSeccion = (decimal)resultadosMunicipales.Sum(r => r.CantidadVotos); | ||||
|  | ||||
|         var resultadosFinales = resultadosMunicipales | ||||
|             // 1. Agrupamos por el ID del partido, que es un valor único y estable | ||||
|             // 1. Agrupamos por el ID del partido para evitar duplicados. | ||||
|             .GroupBy(r => r.AgrupacionPoliticaId) | ||||
|             .Select(g => new | ||||
|             { | ||||
|                 // 2. Obtenemos el objeto Agrupacion del primer elemento del grupo | ||||
|                 // 2. Tomamos la entidad completa del primer elemento del grupo. | ||||
|                 Agrupacion = g.First().AgrupacionPolitica, | ||||
|                 Votos = g.Sum(r => r.CantidadVotos) | ||||
|             }) | ||||
| @@ -631,7 +687,9 @@ public async Task<IActionResult> GetResultadosConcejalesPorSeccion(string seccio | ||||
|                 id = r.Agrupacion.Id, | ||||
|                 nombre = r.Agrupacion.NombreCorto ?? r.Agrupacion.Nombre, | ||||
|                 votos = r.Votos, | ||||
|                 porcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0 | ||||
|                 porcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0, | ||||
|                 // 3. Añadimos el color a la respuesta. | ||||
|                 color = r.Agrupacion.Color | ||||
|             }) | ||||
|             .ToList(); | ||||
|  | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| @Elecciones.Api_HostAddress = http://localhost:5217 | ||||
|  | ||||
| GET {{Elecciones.Api_HostAddress}}/weatherforecast/ | ||||
| Accept: application/json | ||||
|  | ||||
| ### | ||||
|   | ||||
| @@ -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+12860f24067a7de29ec937e18f314f2f24059f47")] | ||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+271a86b63211dff88fb7188d1db7b390e6c53efb")] | ||||
| [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":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","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=","eeoSVF\u002BzWQgGKOM9hSCzmc0CNSUCyP/f6aJxLHiJ4A8=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","nt6JdXgYN0sYJ/7di0B2aSGDokBPJnFqtwyBcMkycYI="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","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=","PmrFmFQepAv9NhtsO0l45PPk3BWugccwJ3ysTKcw7bM=","6CAjHexjcmVc1caYyfNvMfhJRU6qtmi57Siv1ysirg0=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","\u002BgTea2HWyPcSQvQyVe0ghcDwqBGkKZIDd2\u002BlGKdxL2U="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| @@ -1 +1 @@ | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","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=","eeoSVF\u002BzWQgGKOM9hSCzmc0CNSUCyP/f6aJxLHiJ4A8=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","nt6JdXgYN0sYJ/7di0B2aSGDokBPJnFqtwyBcMkycYI="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","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=","PmrFmFQepAv9NhtsO0l45PPk3BWugccwJ3ysTKcw7bM=","6CAjHexjcmVc1caYyfNvMfhJRU6qtmi57Siv1ysirg0=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","\u002BgTea2HWyPcSQvQyVe0ghcDwqBGkKZIDd2\u002BlGKdxL2U="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||
		Reference in New Issue
	
	Block a user