Feat Tabla Resumen Nacional
This commit is contained in:
		| @@ -5,7 +5,8 @@ import type { | |||||||
|   ApiResponseTablaDetallada, ProyeccionBancas, MunicipioSimple, |   ApiResponseTablaDetallada, ProyeccionBancas, MunicipioSimple, | ||||||
|   TelegramaData, CatalogoItem, CategoriaResumen, ResultadoTicker, |   TelegramaData, CatalogoItem, CategoriaResumen, ResultadoTicker, | ||||||
|   ApiResponseResultadosPorSeccion, PanelElectoralDto, ResumenProvincia, |   ApiResponseResultadosPorSeccion, PanelElectoralDto, ResumenProvincia, | ||||||
|   CategoriaResumenHome, ResultadoFila, ResultadoSeccion |   CategoriaResumenHome, ResultadoFila, ResultadoSeccion, | ||||||
|  |   ProvinciaResumen | ||||||
| } from './types/types'; | } from './types/types'; | ||||||
|  |  | ||||||
| /** | /** | ||||||
| @@ -348,3 +349,8 @@ export const getTablaSecciones = async (eleccionId: number): Promise<ResultadoSe | |||||||
|   const { data } = await apiClient.get(`/elecciones/${eleccionId}/tabla-secciones`); |   const { data } = await apiClient.get(`/elecciones/${eleccionId}/tabla-secciones`); | ||||||
|   return data; |   return data; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | export const getResumenNacionalPorProvincia = async (eleccionId: number, categoriaId: number): Promise<ProvinciaResumen[]> => { | ||||||
|  |   const response = await apiClient.get(`/elecciones/${eleccionId}/resumen-nacional-por-provincia?categoriaId=${categoriaId}`); | ||||||
|  |   return response.data; | ||||||
|  | }; | ||||||
| @@ -8,6 +8,7 @@ import './DevAppStyle.css' | |||||||
| import { HomeCarouselNacionalWidget } from './nacionales/HomeCarouselNacionalWidget'; | import { HomeCarouselNacionalWidget } from './nacionales/HomeCarouselNacionalWidget'; | ||||||
| import { TablaConurbanoWidget } from './nacionales/TablaConurbanoWidget'; | import { TablaConurbanoWidget } from './nacionales/TablaConurbanoWidget'; | ||||||
| import { TablaSeccionesWidget } from './nacionales/TablaSeccionesWidget'; | import { TablaSeccionesWidget } from './nacionales/TablaSeccionesWidget'; | ||||||
|  | import { ResumenNacionalWidget } from './nacionales/ResumenNacionalWidget'; | ||||||
|  |  | ||||||
| // --- NUEVO COMPONENTE REUTILIZABLE PARA CONTENIDO COLAPSABLE --- | // --- NUEVO COMPONENTE REUTILIZABLE PARA CONTENIDO COLAPSABLE --- | ||||||
| const CollapsibleWidgetWrapper = ({ children }: { children: React.ReactNode }) => { | const CollapsibleWidgetWrapper = ({ children }: { children: React.ReactNode }) => { | ||||||
| @@ -174,6 +175,11 @@ export const DevAppLegislativas = () => { | |||||||
|                     <h2>Widget: Tabla de Resultados por Sección Electoral</h2> |                     <h2>Widget: Tabla de Resultados por Sección Electoral</h2> | ||||||
|                     <TablaSeccionesWidget /> |                     <TablaSeccionesWidget /> | ||||||
|                 </div> |                 </div> | ||||||
|  |  | ||||||
|  |                 <div style={sectionStyle}> | ||||||
|  |                     <h2>Resumen Nacional de Resultados por Provincia</h2> | ||||||
|  |                     <ResumenNacionalWidget /> | ||||||
|  |                 </div> | ||||||
|             </div> |             </div> | ||||||
|         </div> |         </div> | ||||||
|     ); |     ); | ||||||
|   | |||||||
| @@ -0,0 +1,81 @@ | |||||||
|  | /* src/components/widgets/ResumenNacionalWidget.module.css */ | ||||||
|  | .widgetContainer { | ||||||
|  |   font-family: sans-serif; | ||||||
|  |   border: 1px solid #ccc; | ||||||
|  |   border-radius: 8px; | ||||||
|  |   padding: 1.5rem; | ||||||
|  |   max-width: 1000px; | ||||||
|  |   margin: 2rem auto; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .header { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: center; | ||||||
|  |   padding-bottom: 1rem; | ||||||
|  |   margin-bottom: 1rem; | ||||||
|  |   border-bottom: 1px solid #eee; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .header h3 { | ||||||
|  |   margin: 0; | ||||||
|  |   font-size: 1.5rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .categoriaSelector { | ||||||
|  |   min-width: 280px; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .listaProvincias { | ||||||
|  |   list-style: none; | ||||||
|  |   padding: 0; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .provinciaItem { | ||||||
|  |   padding: 1rem 0; | ||||||
|  |   border-bottom: 1px solid #eee; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .provinciaItem:last-child { | ||||||
|  |   border-bottom: none; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .provinciaHeader { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   align-items: baseline; | ||||||
|  |   margin-bottom: 0.5rem; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .provinciaNombre { | ||||||
|  |   font-weight: bold; | ||||||
|  |   font-size: 1.1rem; | ||||||
|  |   text-transform: uppercase; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .provinciaEscrutado { | ||||||
|  |   font-size: 0.8rem; | ||||||
|  |   color: #555; | ||||||
|  |   font-weight: 500; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .resultadosLista { | ||||||
|  |   list-style: none; | ||||||
|  |   padding: 0; | ||||||
|  |   margin: 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .resultadoItem { | ||||||
|  |   display: flex; | ||||||
|  |   justify-content: space-between; | ||||||
|  |   padding: 0.25rem 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .partidoNombre { | ||||||
|  |   color: #333; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | .partidoPorcentaje { | ||||||
|  |   font-weight: bold; | ||||||
|  | } | ||||||
| @@ -0,0 +1,61 @@ | |||||||
|  | // src/components/widgets/ResumenNacionalWidget.tsx | ||||||
|  | import { useState } from 'react'; | ||||||
|  | import { useQuery } from '@tanstack/react-query'; | ||||||
|  | import Select from 'react-select'; | ||||||
|  | import { getResumenNacionalPorProvincia } from '../../../apiService'; | ||||||
|  | import styles from './ResumenNacionalWidget.module.css'; | ||||||
|  |  | ||||||
|  | const ELECCION_ID = 2; // Exclusivo para elecciones nacionales | ||||||
|  | const CATEGORIAS_NACIONALES = [ | ||||||
|  |   { value: 3, label: 'Diputados Nacionales' }, | ||||||
|  |   { value: 2, label: 'Senadores Nacionales' }, | ||||||
|  | ]; | ||||||
|  |  | ||||||
|  | export const ResumenNacionalWidget = () => { | ||||||
|  |   const [categoria, setCategoria] = useState(CATEGORIAS_NACIONALES[0]); | ||||||
|  |  | ||||||
|  |   const { data, isLoading, error } = useQuery({ | ||||||
|  |     queryKey: ['resumenNacional', ELECCION_ID, categoria.value], | ||||||
|  |     queryFn: () => getResumenNacionalPorProvincia(ELECCION_ID, categoria.value), | ||||||
|  |     refetchInterval: 60000, | ||||||
|  |   }); | ||||||
|  |  | ||||||
|  |   const formatPercent = (num: number) => `${num.toFixed(2)}%`; | ||||||
|  |  | ||||||
|  |   return ( | ||||||
|  |     <div className={styles.widgetContainer}> | ||||||
|  |       <div className={styles.header}> | ||||||
|  |         <h3>{categoria.label}</h3> | ||||||
|  |         <Select | ||||||
|  |           className={styles.categoriaSelector} | ||||||
|  |           options={CATEGORIAS_NACIONALES} | ||||||
|  |           value={categoria} | ||||||
|  |           onChange={(opt) => setCategoria(opt!)} | ||||||
|  |           isSearchable={false} | ||||||
|  |         /> | ||||||
|  |       </div> | ||||||
|  |       {isLoading && <p>Cargando resumen nacional...</p>} | ||||||
|  |       {error && <p style={{ color: 'red' }}>Error al cargar los datos.</p>} | ||||||
|  |       {data && ( | ||||||
|  |         <ul className={styles.listaProvincias}> | ||||||
|  |           {data.map((provincia) => ( | ||||||
|  |             <li key={provincia.provinciaId} className={styles.provinciaItem}> | ||||||
|  |               <div className={styles.provinciaHeader}> | ||||||
|  |                 <span className={styles.provinciaNombre}>{provincia.provinciaNombre}</span> | ||||||
|  |                 <span className={styles.provinciaEscrutado}>ESCR. {formatPercent(provincia.porcentajeEscrutado)}</span> | ||||||
|  |               </div> | ||||||
|  |               <ul className={styles.resultadosLista}> | ||||||
|  |                 {provincia.resultados.map((partido, index) => ( | ||||||
|  |                   <li key={index} className={styles.resultadoItem}> | ||||||
|  |                     <span className={styles.partidoNombre}>{partido.nombre}</span> | ||||||
|  |                     <span className={styles.partidoPorcentaje}>{formatPercent(partido.porcentaje)}</span> | ||||||
|  |                   </li> | ||||||
|  |                 ))} | ||||||
|  |               </ul> | ||||||
|  |             </li> | ||||||
|  |           ))} | ||||||
|  |         </ul> | ||||||
|  |       )} | ||||||
|  |     </div> | ||||||
|  |   ); | ||||||
|  | }; | ||||||
| @@ -31,6 +31,7 @@ import { CongresoNacionalWidget } from './features/legislativas/nacionales/Congr | |||||||
| import { HomeCarouselNacionalWidget } from './features/legislativas/nacionales/HomeCarouselNacionalWidget'; | import { HomeCarouselNacionalWidget } from './features/legislativas/nacionales/HomeCarouselNacionalWidget'; | ||||||
| import { TablaConurbanoWidget } from './features/legislativas/nacionales/TablaConurbanoWidget'; | import { TablaConurbanoWidget } from './features/legislativas/nacionales/TablaConurbanoWidget'; | ||||||
| import { TablaSeccionesWidget } from './features/legislativas/nacionales/TablaSeccionesWidget'; | import { TablaSeccionesWidget } from './features/legislativas/nacionales/TablaSeccionesWidget'; | ||||||
|  | import { ResumenNacionalWidget } from './features/legislativas/nacionales/ResumenNacionalWidget'; | ||||||
|  |  | ||||||
| import { DevAppLegislativas } from './features/legislativas/DevAppLegislativas'; | import { DevAppLegislativas } from './features/legislativas/DevAppLegislativas'; | ||||||
|  |  | ||||||
| @@ -66,6 +67,7 @@ const WIDGET_MAP: Record<string, React.ElementType> = { | |||||||
|     'composicion-congreso-nacional': CongresoNacionalWidget, |     'composicion-congreso-nacional': CongresoNacionalWidget, | ||||||
|     'tabla-conurbano': TablaConurbanoWidget, |     'tabla-conurbano': TablaConurbanoWidget, | ||||||
|     'tabla-secciones': TablaSeccionesWidget, |     'tabla-secciones': TablaSeccionesWidget, | ||||||
|  |     'resumen-nacional': ResumenNacionalWidget, | ||||||
| }; | }; | ||||||
|  |  | ||||||
| // Vite establece `import.meta.env.DEV` a `true` cuando ejecutamos 'npm run dev' | // Vite establece `import.meta.env.DEV` a `true` cuando ejecutamos 'npm run dev' | ||||||
|   | |||||||
| @@ -197,3 +197,15 @@ export interface ResultadoSeccion { | |||||||
|   nombre: string; |   nombre: string; | ||||||
|   municipios: ResultadoFila[]; |   municipios: ResultadoFila[]; | ||||||
| } | } | ||||||
|  |  | ||||||
|  | export interface PartidoResumen { | ||||||
|  |   nombre: string; | ||||||
|  |   porcentaje: number; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | export interface ProvinciaResumen { | ||||||
|  |   provinciaId: string; | ||||||
|  |   provinciaNombre: string; | ||||||
|  |   porcentajeEscrutado: number; | ||||||
|  |   resultados: PartidoResumen[]; | ||||||
|  | } | ||||||
| @@ -1871,4 +1871,71 @@ List<CandidatoOverride> overrides, string agrupacionId, int categoriaId, int? am | |||||||
|  |  | ||||||
|         return Ok(resultadosFinales); |         return Ok(resultadosFinales); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     [HttpGet("resumen-nacional-por-provincia")] | ||||||
|  |     public async Task<IActionResult> GetResumenNacionalPorProvincia([FromRoute] int eleccionId, [FromQuery] int categoriaId) | ||||||
|  |     { | ||||||
|  |         // 1. Unir ResumenesVotos con AmbitosGeograficos para obtener la información necesaria de forma eficiente. | ||||||
|  |         var votosProvinciales = await ( | ||||||
|  |             from rv in _dbContext.ResumenesVotos | ||||||
|  |             join ambito in _dbContext.AmbitosGeograficos on rv.AmbitoGeograficoId equals ambito.Id | ||||||
|  |             join agrupacion in _dbContext.AgrupacionesPoliticas on rv.AgrupacionPoliticaId equals agrupacion.Id | ||||||
|  |             where rv.EleccionId == eleccionId && | ||||||
|  |                   rv.CategoriaId == categoriaId && | ||||||
|  |                   ambito.NivelId == 10 // Aseguramos que solo tomamos datos a nivel provincial | ||||||
|  |             select new | ||||||
|  |             { | ||||||
|  |                 ambito.DistritoId, | ||||||
|  |                 ProvinciaNombre = ambito.Nombre, | ||||||
|  |                 AgrupacionNombre = agrupacion.NombreCorto ?? agrupacion.Nombre, | ||||||
|  |                 rv.Votos | ||||||
|  |             } | ||||||
|  |         ).ToListAsync(); | ||||||
|  |  | ||||||
|  |         // 2. Obtener los estados de recuento para todas las provincias en una sola consulta. | ||||||
|  |         var todosLosEstados = await _dbContext.EstadosRecuentosGenerales | ||||||
|  |             .AsNoTracking() | ||||||
|  |             .Include(e => e.AmbitoGeografico) | ||||||
|  |             .Where(e => e.EleccionId == eleccionId && | ||||||
|  |                         e.CategoriaId == categoriaId && | ||||||
|  |                         e.AmbitoGeografico.NivelId == 10 && | ||||||
|  |                         e.AmbitoGeografico.DistritoId != null) | ||||||
|  |             .ToDictionaryAsync(e => e.AmbitoGeografico.DistritoId!); | ||||||
|  |  | ||||||
|  |         // 3. Agrupar los resultados por provincia y procesarlos en memoria. | ||||||
|  |         var resultadoFinal = votosProvinciales | ||||||
|  |             .GroupBy(v => new { v.DistritoId, v.ProvinciaNombre }) | ||||||
|  |             .Select(grupoProvincia => | ||||||
|  |             { | ||||||
|  |                 if (grupoProvincia.Key.DistritoId == null) return null; | ||||||
|  |  | ||||||
|  |                 var totalVotosProvincia = (decimal)grupoProvincia.Sum(p => p.Votos); | ||||||
|  |                 if (totalVotosProvincia == 0) return null; | ||||||
|  |  | ||||||
|  |                 var top3Partidos = grupoProvincia | ||||||
|  |                     .OrderByDescending(p => p.Votos) | ||||||
|  |                     .Take(3) | ||||||
|  |                     .Select(p => new Elecciones.Core.DTOs.ApiResponses.Resumen.PartidoResumenDto | ||||||
|  |                     { | ||||||
|  |                         Nombre = p.AgrupacionNombre, | ||||||
|  |                         Porcentaje = (p.Votos / totalVotosProvincia) * 100 | ||||||
|  |                     }) | ||||||
|  |                     .ToList(); | ||||||
|  |  | ||||||
|  |                 todosLosEstados.TryGetValue(grupoProvincia.Key.DistritoId, out var estado); | ||||||
|  |  | ||||||
|  |                 return new Elecciones.Core.DTOs.ApiResponses.Resumen.ProvinciaResumenDto | ||||||
|  |                 { | ||||||
|  |                     ProvinciaId = grupoProvincia.Key.DistritoId, | ||||||
|  |                     ProvinciaNombre = grupoProvincia.Key.ProvinciaNombre, | ||||||
|  |                     PorcentajeEscrutado = estado?.MesasTotalizadasPorcentaje ?? 0, | ||||||
|  |                     Resultados = top3Partidos | ||||||
|  |                 }; | ||||||
|  |             }) | ||||||
|  |             .Where(r => r != null) // Filtramos las provincias que no tuvieron votos o DistritoId nulo. | ||||||
|  |             .OrderBy(p => p!.ProvinciaNombre) | ||||||
|  |             .ToList(); | ||||||
|  |  | ||||||
|  |         return Ok(resultadoFinal); | ||||||
|  |     } | ||||||
| } | } | ||||||
| @@ -14,7 +14,7 @@ using System.Reflection; | |||||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")] | [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")] | ||||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3c364ef373330eaa052fa0d2aad92e71d0bfd7df")] | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+248171146d637f758fd8b14a6a2ef9fcb0bcd3b5")] | ||||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] | [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] | ||||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] | [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] | ||||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||||
|   | |||||||
| @@ -1 +1 @@ | |||||||
| {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","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=","J\u002Bfv/j3QyIW9bxolc46wDka8641F622/QgIllt0Re80=","Y/o0rakw9VYzEfz9M659qW77P9kvz\u002B2gTe1Lv3zgUDE=","8QWUReqP8upfOnmA5lMNgBxAfYJ1z3zv/WYBUXBEiog=","1L7p1HQI/Uoosqm7RyBuYjKbRFTycFgJEtHPSdlXWhU=","ZxPpBx5gkHuilHLcg/vcjvaXswvTqiUM0YaAEwbNSLI=","zSbNtRd32h6wCMWjU5ecl5a3ECd\u002BVBstFC3etkdk4s0=","urIQ/RlknPjR8\u002BeAcCsDIPiRjQGFfUdIC\u002BoT3wYB2dU=","0GIIj19uQyjDIXFgf3aZC3MWTTr0ockrC95FYCZEyN4=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","YscOvhINdry\u002BI95UO\u002BBCycn6KSJEZQzHtH6Q7oRYqCI="],"CachedAssets":{},"CachedCopyCandidates":{}} | {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","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=","J\u002Bfv/j3QyIW9bxolc46wDka8641F622/QgIllt0Re80=","Y/o0rakw9VYzEfz9M659qW77P9kvz\u002B2gTe1Lv3zgUDE=","8QWUReqP8upfOnmA5lMNgBxAfYJ1z3zv/WYBUXBEiog=","1L7p1HQI/Uoosqm7RyBuYjKbRFTycFgJEtHPSdlXWhU=","ZxPpBx5gkHuilHLcg/vcjvaXswvTqiUM0YaAEwbNSLI=","zSbNtRd32h6wCMWjU5ecl5a3ECd\u002BVBstFC3etkdk4s0=","urIQ/RlknPjR8\u002BeAcCsDIPiRjQGFfUdIC\u002BoT3wYB2dU=","QgvJ\u002BjH2t7prbQ/Cu9eYOIBqysMeDcsXR6lggWr0auI=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","xGsYFCt4z/3oybSKe/TfOuJ3mQW6fLJVS9hZfmpKuPY="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||||
| @@ -1 +1 @@ | |||||||
| {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","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=","J\u002Bfv/j3QyIW9bxolc46wDka8641F622/QgIllt0Re80=","Y/o0rakw9VYzEfz9M659qW77P9kvz\u002B2gTe1Lv3zgUDE=","8QWUReqP8upfOnmA5lMNgBxAfYJ1z3zv/WYBUXBEiog=","1L7p1HQI/Uoosqm7RyBuYjKbRFTycFgJEtHPSdlXWhU=","ZxPpBx5gkHuilHLcg/vcjvaXswvTqiUM0YaAEwbNSLI=","zSbNtRd32h6wCMWjU5ecl5a3ECd\u002BVBstFC3etkdk4s0=","urIQ/RlknPjR8\u002BeAcCsDIPiRjQGFfUdIC\u002BoT3wYB2dU=","0GIIj19uQyjDIXFgf3aZC3MWTTr0ockrC95FYCZEyN4=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","YscOvhINdry\u002BI95UO\u002BBCycn6KSJEZQzHtH6Q7oRYqCI="],"CachedAssets":{},"CachedCopyCandidates":{}} | {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["YB39loxHH43S4MF8aTOiogcIbBAIq5Qj3dlJkIfYVxI=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","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=","J\u002Bfv/j3QyIW9bxolc46wDka8641F622/QgIllt0Re80=","Y/o0rakw9VYzEfz9M659qW77P9kvz\u002B2gTe1Lv3zgUDE=","8QWUReqP8upfOnmA5lMNgBxAfYJ1z3zv/WYBUXBEiog=","1L7p1HQI/Uoosqm7RyBuYjKbRFTycFgJEtHPSdlXWhU=","ZxPpBx5gkHuilHLcg/vcjvaXswvTqiUM0YaAEwbNSLI=","zSbNtRd32h6wCMWjU5ecl5a3ECd\u002BVBstFC3etkdk4s0=","urIQ/RlknPjR8\u002BeAcCsDIPiRjQGFfUdIC\u002BoT3wYB2dU=","QgvJ\u002BjH2t7prbQ/Cu9eYOIBqysMeDcsXR6lggWr0auI=","BY4GeeFiQbYpWuSzb2XIY4JatmLNOZ6dhKs4ZT92nsM=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","xGsYFCt4z/3oybSKe/TfOuJ3mQW6fLJVS9hZfmpKuPY="],"CachedAssets":{},"CachedCopyCandidates":{}} | ||||||
| @@ -0,0 +1,8 @@ | |||||||
|  | // src/Elecciones.Core/DTOs/ApiResponses/Resumen/PartidoResumenDto.cs | ||||||
|  | namespace Elecciones.Core.DTOs.ApiResponses.Resumen; | ||||||
|  |  | ||||||
|  | public class PartidoResumenDto | ||||||
|  | { | ||||||
|  |   public string Nombre { get; set; } = string.Empty; | ||||||
|  |   public decimal Porcentaje { get; set; } | ||||||
|  | } | ||||||
| @@ -0,0 +1,10 @@ | |||||||
|  | // src/Elecciones.Core/DTOs/ApiResponses/Resumen/ProvinciaResumenDto.cs | ||||||
|  | namespace Elecciones.Core.DTOs.ApiResponses.Resumen; | ||||||
|  |  | ||||||
|  | public class ProvinciaResumenDto | ||||||
|  | { | ||||||
|  |   public string ProvinciaId { get; set; } = string.Empty; | ||||||
|  |   public string ProvinciaNombre { get; set; } = string.Empty; | ||||||
|  |   public decimal PorcentajeEscrutado { get; set; } | ||||||
|  |   public List<PartidoResumenDto> Resultados { get; set; } = new(); | ||||||
|  | } | ||||||
| @@ -13,7 +13,7 @@ using System.Reflection; | |||||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")] | [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")] | ||||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3c364ef373330eaa052fa0d2aad92e71d0bfd7df")] | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+248171146d637f758fd8b14a6a2ef9fcb0bcd3b5")] | ||||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")] | [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")] | ||||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")] | [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")] | ||||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ using System.Reflection; | |||||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")] | [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")] | ||||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3c364ef373330eaa052fa0d2aad92e71d0bfd7df")] | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+248171146d637f758fd8b14a6a2ef9fcb0bcd3b5")] | ||||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")] | [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")] | ||||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")] | [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")] | ||||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ using System.Reflection; | |||||||
| [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")] | [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")] | ||||||
| [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] | ||||||
| [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] | ||||||
| [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+3c364ef373330eaa052fa0d2aad92e71d0bfd7df")] | [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+248171146d637f758fd8b14a6a2ef9fcb0bcd3b5")] | ||||||
| [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")] | [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")] | ||||||
| [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")] | [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")] | ||||||
| [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user