Feat: Implementar API de resultados y widget de prueba dinámico con selector

API (Backend):
Se crea el endpoint GET /api/resultados/municipio/{id} para servir los resultados detallados de un municipio específico.
Se añade el endpoint GET /api/catalogos/municipios para poblar selectores en el frontend.
Se incluye un endpoint simulado GET /api/resultados/provincia/{id} para facilitar el desarrollo futuro del frontend.
Worker (Servicio de Ingesta):
La lógica de sondeo se ha hecho dinámica. Ahora consulta todos los municipios presentes en la base de datos en lugar de uno solo.
El servicio falso (FakeElectoralApiService) se ha mejorado para generar datos aleatorios para cualquier municipio solicitado.
Frontend (React):
Se crea el componente <MunicipioSelector /> que se carga con datos desde la nueva API de catálogos.
Se integra el selector en la página principal, permitiendo al usuario elegir un municipio.
El componente <MunicipioWidget /> ahora recibe el ID del municipio como una prop y muestra los datos del municipio seleccionado, actualizándose en tiempo real.
Configuración:
Se ajusta la política de CORS en la API para permitir peticiones desde el servidor de desarrollo de Vite (localhost:5173), solucionando errores de conexión en el entorno local.
This commit is contained in:
2025-08-14 15:27:45 -03:00
parent b90baadeed
commit 1d58023113
70 changed files with 5563 additions and 89 deletions

24
Elecciones-Web/frontend/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1,69 @@
# React + TypeScript + Vite
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
## Expanding the ESLint configuration
If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
```js
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Remove tseslint.configs.recommended and replace with this
...tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
...tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
...tseslint.configs.stylisticTypeChecked,
// Other configs...
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
```
You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs['recommended-typescript'],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
```

View File

@@ -0,0 +1,23 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { globalIgnores } from 'eslint/config'
export default tseslint.config([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs['recommended-latest'],
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])

View File

@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>

3661
Elecciones-Web/frontend/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,30 @@
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
},
"dependencies": {
"axios": "^1.11.0",
"react": "^19.1.1",
"react-dom": "^19.1.1"
},
"devDependencies": {
"@eslint/js": "^9.33.0",
"@types/react": "^19.1.10",
"@types/react-dom": "^19.1.7",
"@vitejs/plugin-react": "^5.0.0",
"eslint": "^9.33.0",
"eslint-plugin-react-hooks": "^5.2.0",
"eslint-plugin-react-refresh": "^0.4.20",
"globals": "^16.3.0",
"typescript": "~5.8.3",
"typescript-eslint": "^8.39.1",
"vite": "^7.1.2"
}
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="31.88" height="32" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 257"><defs><linearGradient id="IconifyId1813088fe1fbc01fb466" x1="-.828%" x2="57.636%" y1="7.652%" y2="78.411%"><stop offset="0%" stop-color="#41D1FF"></stop><stop offset="100%" stop-color="#BD34FE"></stop></linearGradient><linearGradient id="IconifyId1813088fe1fbc01fb467" x1="43.376%" x2="50.316%" y1="2.242%" y2="89.03%"><stop offset="0%" stop-color="#FFEA83"></stop><stop offset="8.333%" stop-color="#FFDD35"></stop><stop offset="100%" stop-color="#FFA800"></stop></linearGradient></defs><path fill="url(#IconifyId1813088fe1fbc01fb466)" d="M255.153 37.938L134.897 252.976c-2.483 4.44-8.862 4.466-11.382.048L.875 37.958c-2.746-4.814 1.371-10.646 6.827-9.67l120.385 21.517a6.537 6.537 0 0 0 2.322-.004l117.867-21.483c5.438-.991 9.574 4.796 6.877 9.62Z"></path><path fill="url(#IconifyId1813088fe1fbc01fb467)" d="M185.432.063L96.44 17.501a3.268 3.268 0 0 0-2.634 3.014l-5.474 92.456a3.268 3.268 0 0 0 3.997 3.378l24.777-5.718c2.318-.535 4.413 1.507 3.936 3.838l-7.361 36.047c-.495 2.426 1.782 4.5 4.151 3.78l15.304-4.649c2.372-.72 4.652 1.36 4.15 3.788l-11.698 56.621c-.732 3.542 3.979 5.473 5.943 2.437l1.313-2.028l72.516-144.72c1.215-2.423-.88-5.186-3.54-4.672l-25.505 4.922c-2.396.462-4.435-1.77-3.759-4.114l16.646-57.705c.677-2.35-1.37-4.583-3.769-4.113Z"></path></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@@ -0,0 +1,42 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
}
.logo {
height: 6em;
padding: 1.5em;
will-change: filter;
transition: filter 300ms;
}
.logo:hover {
filter: drop-shadow(0 0 2em #646cffaa);
}
.logo.react:hover {
filter: drop-shadow(0 0 2em #61dafbaa);
}
@keyframes logo-spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
@media (prefers-reduced-motion: no-preference) {
a:nth-of-type(2) .logo {
animation: logo-spin infinite 20s linear;
}
}
.card {
padding: 2em;
}
.read-the-docs {
color: #888;
}

View File

@@ -0,0 +1,30 @@
// src/App.tsx
import { useState } from 'react';
import { MunicipioWidget } from './components/MunicipioWidget';
import { MunicipioSelector } from './components/MunicipioSelector';
import './App.css';
function App() {
const [selectedMunicipioId, setSelectedMunicipioId] = useState<string | null>(null);
return (
<>
<h1>Elecciones 2025 - Resultados en Vivo</h1>
{/* Aquí podrías poner el widget del Resumen Provincial */}
<hr />
<h2>Consulta por Municipio</h2>
<MunicipioSelector onMunicipioChange={setSelectedMunicipioId} />
{selectedMunicipioId && (
<div style={{ marginTop: '20px' }}>
<MunicipioWidget municipioId={selectedMunicipioId} />
</div>
)}
</>
);
}
export default App;

View File

@@ -0,0 +1,37 @@
// src/components/MunicipioSelector.tsx
import { useState, useEffect } from 'react';
import { getMunicipios, type MunicipioSimple } from '../services/api';
interface Props {
onMunicipioChange: (municipioId: string) => void;
}
export const MunicipioSelector = ({ onMunicipioChange }: Props) => {
const [municipios, setMunicipios] = useState<MunicipioSimple[]>([]);
const [loading, setLoading] = useState(true);
useEffect(() => {
const loadMunicipios = async () => {
try {
const data = await getMunicipios();
setMunicipios(data);
} catch (error) {
console.error("Error al cargar municipios", error);
} finally {
setLoading(false);
}
};
loadMunicipios();
}, []);
if (loading) return <p>Cargando municipios...</p>;
return (
<select onChange={(e) => onMunicipioChange(e.target.value)} defaultValue="">
<option value="" disabled>Seleccione un municipio</option>
{municipios.map(m => (
<option key={m.id} value={m.id}>{m.nombre}</option>
))}
</select>
);
};

View File

@@ -0,0 +1,69 @@
// src/components/MunicipioWidget.tsx
import { useState, useEffect } from 'react';
import { getResultadosPorMunicipio, type MunicipioResultados } from '../services/api';
interface Props {
municipioId: string;
}
export const MunicipioWidget = ({ municipioId }: Props) => {
const [data, setData] = useState<MunicipioResultados | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const resultados = await getResultadosPorMunicipio(municipioId);
setData(resultados);
setError(null);
} catch (err) {
setError('No se pudieron cargar los datos.');
console.error(err);
} finally {
setLoading(false);
}
};
// Hacemos la primera llamada inmediatamente
fetchData();
// Creamos un intervalo para refrescar los datos cada 10 segundos
const intervalId = setInterval(fetchData, 10000);
// ¡Importante! Limpiamos el intervalo cuando el componente se desmonta
return () => clearInterval(intervalId);
}, [municipioId]); // El efecto se volverá a ejecutar si el municipioId cambia
if (loading && !data) return <div>Cargando resultados...</div>;
if (error) return <div style={{ color: 'red' }}>{error}</div>;
if (!data) return <div>No hay datos disponibles.</div>;
return (
<div style={{ fontFamily: 'sans-serif', border: '1px solid #ccc', padding: '16px', borderRadius: '8px' }}>
<h2>{data.municipioNombre}</h2>
<p>Escrutado: {data.porcentajeEscrutado.toFixed(2)}% | Participación: {data.porcentajeParticipacion.toFixed(2)}%</p>
<hr />
<table style={{ width: '100%', borderCollapse: 'collapse' }}>
<thead>
<tr>
<th style={{ textAlign: 'left' }}>Agrupación</th>
<th style={{ textAlign: 'right' }}>Votos</th>
<th style={{ textAlign: 'right' }}>%</th>
</tr>
</thead>
<tbody>
{data.resultados.map((partido) => (
<tr key={partido.nombre}>
<td>{partido.nombre}</td>
<td style={{ textAlign: 'right' }}>{partido.votos.toLocaleString('es-AR')}</td>
<td style={{ textAlign: 'right' }}>{partido.porcentaje.toFixed(2)}%</td>
</tr>
))}
</tbody>
</table>
<p style={{fontSize: '0.8em', color: '#666'}}>Última actualización: {new Date(data.ultimaActualizacion).toLocaleTimeString('es-AR')}</p>
</div>
);
};

View File

@@ -0,0 +1,68 @@
:root {
font-family: system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}

View File

@@ -0,0 +1,10 @@
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)

View File

@@ -0,0 +1,56 @@
// src/services/api.ts
import axios from 'axios';
// Creamos una instancia de Axios.
// OJO: Usamos el puerto del PROXY (8600) que configuramos en docker-compose.yml
// No usamos el puerto de la API de .NET directamente.
const apiClient = axios.create({
baseURL: 'http://localhost:5217/api'
});
// Definimos las interfaces de TypeScript que coinciden con los DTOs de nuestra API.
export interface AgrupacionResultado {
nombre: string;
votos: number;
porcentaje: number;
}
export interface VotosAdicionales {
enBlanco: number;
nulos: number;
recurridos: number;
}
export interface MunicipioResultados {
municipioNombre: string;
ultimaActualizacion: string; // La fecha viene como string
porcentajeEscrutado: number;
porcentajeParticipacion: number;
resultados: AgrupacionResultado[];
votosAdicionales: VotosAdicionales;
}
export interface MunicipioSimple {
id: string;
nombre: string;
}
export interface ResumenProvincial extends Omit<MunicipioResultados, 'municipioNombre'> {
provinciaNombre: string;
}
export const getMunicipios = async (): Promise<MunicipioSimple[]> => {
const response = await apiClient.get<MunicipioSimple[]>('/catalogos/municipios');
return response.data;
};
export const getResumenProvincial = async (distritoId: string): Promise<ResumenProvincial> => {
const response = await apiClient.get<ResumenProvincial>(`/resultados/provincia/${distritoId}`);
return response.data;
}
// Función para obtener los resultados de un municipio
export const getResultadosPorMunicipio = async (municipioId: string): Promise<MunicipioResultados> => {
const response = await apiClient.get<MunicipioResultados>(`/resultados/municipio/${municipioId}`);
return response.data;
};

View File

@@ -0,0 +1 @@
/// <reference types="vite/client" />

View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
"target": "ES2022",
"useDefineForClassFields": true,
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["src"]
}

View File

@@ -0,0 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

View File

@@ -0,0 +1,25 @@
{
"compilerOptions": {
"tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
"target": "ES2023",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"erasableSyntaxOnly": true,
"noFallthroughCasesInSwitch": true,
"noUncheckedSideEffectImports": true
},
"include": ["vite.config.ts"]
}

View File

@@ -0,0 +1,7 @@
import { defineConfig } from 'vite'
import react from '@vitejs/plugin-react'
// https://vite.dev/config/
export default defineConfig({
plugins: [react()],
})

View File

@@ -0,0 +1,38 @@
using Elecciones.Core.DTOs.ApiResponses;
using Elecciones.Database;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;
namespace Elecciones.Api.Controllers;
[ApiController]
[Route("api/[controller]")]
public class CatalogosController : ControllerBase
{
private readonly EleccionesDbContext _dbContext;
public CatalogosController(EleccionesDbContext dbContext)
{
_dbContext = dbContext;
}
[HttpGet("municipios")]
public async Task<IActionResult> GetMunicipios()
{
// El NivelId 5 corresponde a "Municipio" según los datos que hemos visto.
var municipios = await _dbContext.AmbitosGeograficos
.AsNoTracking()
.Where(a => a.NivelId == 5 && a.MunicipioId != null)
.Select(a => new MunicipioSimpleDto
{
Id = a.MunicipioId!,
Nombre = a.Nombre
})
.OrderBy(m => m.Nombre)
.ToListAsync();
return Ok(municipios);
}
}

View File

@@ -0,0 +1,116 @@
// src/Elecciones.Api/Controllers/ResultadosController.cs
using Elecciones.Core.DTOs.ApiResponses;
using Elecciones.Database;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Threading.Tasks;
namespace Elecciones.Api.Controllers;
[ApiController]
[Route("api/[controller]")]
public class ResultadosController : ControllerBase
{
private readonly EleccionesDbContext _dbContext;
private readonly ILogger<ResultadosController> _logger;
public ResultadosController(EleccionesDbContext dbContext, ILogger<ResultadosController> logger)
{
_dbContext = dbContext;
_logger = logger;
}
[HttpGet("municipio/{municipioId}")]
public async Task<IActionResult> GetResultadosPorMunicipio(string municipioId)
{
// 1. Buscamos el ámbito geográfico correspondiente al municipio
var ambito = await _dbContext.AmbitosGeograficos
.AsNoTracking()
.FirstOrDefaultAsync(a => a.MunicipioId == municipioId);
if (ambito == null)
{
return NotFound(new { message = $"No se encontró el municipio con ID {municipioId}" });
}
// 2. Buscamos el estado del recuento para ese ámbito
var estadoRecuento = await _dbContext.EstadosRecuentos
.AsNoTracking()
.FirstOrDefaultAsync(e => e.AmbitoGeograficoId == ambito.Id);
if (estadoRecuento == null)
{
return NotFound(new { message = $"No se han encontrado resultados para el municipio {ambito.Nombre}" });
}
// 3. Buscamos todos los votos para ese ámbito, incluyendo el nombre de la agrupación
var resultadosVotos = await _dbContext.ResultadosVotos
.AsNoTracking()
.Include(rv => rv.AgrupacionPolitica) // ¡Crucial para obtener el nombre del partido!
.Where(rv => rv.AmbitoGeograficoId == ambito.Id)
.ToListAsync();
// 4. Calculamos el total de votos positivos para el porcentaje
long totalVotosPositivos = resultadosVotos.Sum(r => r.CantidadVotos);
// 5. Mapeamos todo a nuestro DTO de respuesta
var respuestaDto = new MunicipioResultadosDto
{
MunicipioNombre = ambito.Nombre,
UltimaActualizacion = estadoRecuento.FechaTotalizacion,
PorcentajeEscrutado = estadoRecuento.MesasTotalizadas * 100.0m / (estadoRecuento.MesasEsperadas > 0 ? estadoRecuento.MesasEsperadas : 1),
PorcentajeParticipacion = estadoRecuento.ParticipacionPorcentaje,
Resultados = resultadosVotos.Select(rv => new AgrupacionResultadoDto
{
Nombre = rv.AgrupacionPolitica.Nombre,
Votos = rv.CantidadVotos,
Porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos * 100.0m / totalVotosPositivos) : 0
}).OrderByDescending(r => r.Votos).ToList(),
VotosAdicionales = new VotosAdicionalesDto
{
EnBlanco = estadoRecuento.VotosEnBlanco,
Nulos = estadoRecuento.VotosNulos,
Recurridos = estadoRecuento.VotosRecurridos
}
};
// Devolvemos el resultado
return Ok(respuestaDto);
}
[HttpGet("provincia/{distritoId}")]
public async Task<IActionResult> GetResultadosProvinciales(string distritoId)
{
// TODO: Esta lógica debe ser reemplazada para leer datos reales de la BD
// cuando el worker comience a ingestar los totales a nivel provincial.
// Por ahora, devolvemos datos simulados para permitir el desarrollo del frontend.
var ambito = await _dbContext.AmbitosGeograficos.AsNoTracking()
.FirstOrDefaultAsync(a => a.DistritoId == distritoId && a.NivelId == 10);
if (ambito == null)
{
return NotFound(new { message = "No se encontró la provincia" });
}
// Simulación
var random = new Random();
var respuestaSimulada = new ResumenProvincialDto
{
ProvinciaNombre = ambito.Nombre,
UltimaActualizacion = DateTime.UtcNow,
PorcentajeEscrutado = 78.45m,
PorcentajeParticipacion = 65.12m,
Resultados =
[
new() { Nombre = "ALIANZA POR EL FUTURO", Votos = 2500000 + random.Next(1, 1000), Porcentaje = 45.12m },
new() { Nombre = "FRENTE DE AVANZADA", Votos = 2100000 + random.Next(1, 1000), Porcentaje = 38.78m },
new() { Nombre = "UNION POPULAR", Votos = 800000 + random.Next(1, 1000), Porcentaje = 14.10m },
],
VotosAdicionales = new VotosAdicionalesDto { EnBlanco = 150000, Nulos = 80000, Recurridos = 1200 }
};
return Ok(await Task.FromResult(respuestaSimulada));
}
}

View File

@@ -18,7 +18,7 @@ builder.Services.AddCors(options =>
{ {
options.AddDefaultPolicy(policy => options.AddDefaultPolicy(policy =>
{ {
policy.WithOrigins("http://localhost:8600", "http://www.eldia.com", "http://elecciones2025.eldia.com") // Añade aquí los dominios que necesites policy.WithOrigins("http://localhost:5173", "http://localhost:8600", "http://www.eldia.com", "http://elecciones2025.eldia.com") // Añade aquí los dominios que necesites
.AllowAnyHeader() .AllowAnyHeader()
.AllowAnyMethod(); .AllowAnyMethod();
}); });

View File

@@ -540,6 +540,18 @@
} }
} }
}, },
"Microsoft.Extensions.Configuration/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Primitives": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Configuration.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Configuration.Abstractions/9.0.8": { "Microsoft.Extensions.Configuration.Abstractions/9.0.8": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Primitives": "9.0.8" "Microsoft.Extensions.Primitives": "9.0.8"
@@ -551,6 +563,17 @@
} }
} }
}, },
"Microsoft.Extensions.Configuration.Binder/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Configuration.Binder.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.DependencyInjection/9.0.8": { "Microsoft.Extensions.DependencyInjection/9.0.8": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8" "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8"
@@ -578,6 +601,47 @@
} }
} }
}, },
"Microsoft.Extensions.Diagnostics/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration": "9.0.8",
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.8",
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Diagnostics.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Diagnostics.Abstractions/9.0.8": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Http/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Diagnostics": "9.0.8",
"Microsoft.Extensions.Logging": "9.0.8",
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Http.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Logging/9.0.8": { "Microsoft.Extensions.Logging/9.0.8": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.8", "Microsoft.Extensions.DependencyInjection": "9.0.8",
@@ -614,6 +678,21 @@
} }
} }
}, },
"Microsoft.Extensions.Options.ConfigurationExtensions/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Configuration.Binder": "9.0.8",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8",
"Microsoft.Extensions.Primitives": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Primitives/9.0.8": { "Microsoft.Extensions.Primitives/9.0.8": {
"runtime": { "runtime": {
"lib/net9.0/Microsoft.Extensions.Primitives.dll": { "lib/net9.0/Microsoft.Extensions.Primitives.dll": {
@@ -1090,7 +1169,9 @@
}, },
"Elecciones.Infrastructure/1.0.0": { "Elecciones.Infrastructure/1.0.0": {
"dependencies": { "dependencies": {
"Elecciones.Core": "1.0.0" "Elecciones.Core": "1.0.0",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Http": "9.0.8"
}, },
"runtime": { "runtime": {
"Elecciones.Infrastructure.dll": { "Elecciones.Infrastructure.dll": {
@@ -1289,6 +1370,13 @@
"path": "microsoft.extensions.caching.memory/9.0.8", "path": "microsoft.extensions.caching.memory/9.0.8",
"hashPath": "microsoft.extensions.caching.memory.9.0.8.nupkg.sha512" "hashPath": "microsoft.extensions.caching.memory.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Configuration/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-6m+8Xgmf8UWL0p/oGqBM+0KbHE5/ePXbV1hKXgC59zEv0aa0DW5oiiyxDbK5kH5j4gIvyD5uWL0+HadKBJngvQ==",
"path": "microsoft.extensions.configuration/9.0.8",
"hashPath": "microsoft.extensions.configuration.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Abstractions/9.0.8": { "Microsoft.Extensions.Configuration.Abstractions/9.0.8": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
@@ -1296,6 +1384,13 @@
"path": "microsoft.extensions.configuration.abstractions/9.0.8", "path": "microsoft.extensions.configuration.abstractions/9.0.8",
"hashPath": "microsoft.extensions.configuration.abstractions.9.0.8.nupkg.sha512" "hashPath": "microsoft.extensions.configuration.abstractions.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Configuration.Binder/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-0vK9DnYrYChdiH3yRZWkkp4x4LbrfkWEdBc5HOsQ8t/0CLOWKXKkkhOE8A1shlex0hGydbGrhObeypxz/QTm+w==",
"path": "microsoft.extensions.configuration.binder/9.0.8",
"hashPath": "microsoft.extensions.configuration.binder.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection/9.0.8": { "Microsoft.Extensions.DependencyInjection/9.0.8": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
@@ -1317,6 +1412,27 @@
"path": "microsoft.extensions.dependencymodel/9.0.8", "path": "microsoft.extensions.dependencymodel/9.0.8",
"hashPath": "microsoft.extensions.dependencymodel.9.0.8.nupkg.sha512" "hashPath": "microsoft.extensions.dependencymodel.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Diagnostics/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BKkLCFXzJvNmdngeYBf72VXoZqTJSb1orvjdzDLaGobicoGFBPW8ug2ru1nnEewMEwJzMgnsjHQY8EaKWmVhKg==",
"path": "microsoft.extensions.diagnostics/9.0.8",
"hashPath": "microsoft.extensions.diagnostics.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Diagnostics.Abstractions/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UDY7blv4DCyIJ/8CkNrQKLaAZFypXQavRZ2DWf/2zi1mxYYKKw2t8AOCBWxNntyPZHPGhtEmL3snFM98ADZqTw==",
"path": "microsoft.extensions.diagnostics.abstractions/9.0.8",
"hashPath": "microsoft.extensions.diagnostics.abstractions.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Http/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-jDj+4aDByk47oESlDDTtk6LWzlXlmoCsjCn6ihd+i9OntN885aPLszUII5+w0B/7wYSZcS3KdjqLAIhKLSiBXQ==",
"path": "microsoft.extensions.http/9.0.8",
"hashPath": "microsoft.extensions.http.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Logging/9.0.8": { "Microsoft.Extensions.Logging/9.0.8": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
@@ -1338,6 +1454,13 @@
"path": "microsoft.extensions.options/9.0.8", "path": "microsoft.extensions.options/9.0.8",
"hashPath": "microsoft.extensions.options.9.0.8.nupkg.sha512" "hashPath": "microsoft.extensions.options.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Options.ConfigurationExtensions/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-eW2s6n06x0w6w4nsX+SvpgsFYkl+Y0CttYAt6DKUXeqprX+hzNqjSfOh637fwNJBg7wRBrOIRHe49gKiTgJxzQ==",
"path": "microsoft.extensions.options.configurationextensions/9.0.8",
"hashPath": "microsoft.extensions.options.configurationextensions.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Primitives/9.0.8": { "Microsoft.Extensions.Primitives/9.0.8": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,

View File

@@ -13,7 +13,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+d9bcfd70865a12c229e6a761639094b45de862bd")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b90baadeedb870b5b1c9eeeb7022a0d211b61bec")]
[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")]

View File

@@ -167,3 +167,9 @@ E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\obj\Debug\net9.0\refint\Ele
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\obj\Debug\net9.0\Elecciones.Api.pdb E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\obj\Debug\net9.0\Elecciones.Api.pdb
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\obj\Debug\net9.0\Elecciones.Api.genruntimeconfig.cache E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\obj\Debug\net9.0\Elecciones.Api.genruntimeconfig.cache
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\obj\Debug\net9.0\ref\Elecciones.Api.dll E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\obj\Debug\net9.0\ref\Elecciones.Api.dll
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Configuration.dll
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Configuration.Binder.dll
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Diagnostics.dll
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Diagnostics.Abstractions.dll
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Http.dll
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll

View File

@@ -1 +1 @@
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","AE1TAk4qas82IfXTyRHo\u002BfMlnTE4e7B1AJrEn9ZhBwo=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","lxebrAqmCStl1yDKQUlHmeuz9HkimDnS\u002B/df3f1dyII="],"CachedAssets":{},"CachedCopyCandidates":{}} {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","AE1TAk4qas82IfXTyRHo\u002BfMlnTE4e7B1AJrEn9ZhBwo=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","r5wfLIFTEo2\u002Bd7Tsx44bFIb0SPNdPvg4KbBRNmbWVFA="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -1 +1 @@
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","AE1TAk4qas82IfXTyRHo\u002BfMlnTE4e7B1AJrEn9ZhBwo=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","lxebrAqmCStl1yDKQUlHmeuz9HkimDnS\u002B/df3f1dyII="],"CachedAssets":{},"CachedCopyCandidates":{}} {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["mhE0FuBM0BOF9SNOE0rY9setCw2ye3UUh7cEPjhgDdY=","AE1TAk4qas82IfXTyRHo\u002BfMlnTE4e7B1AJrEn9ZhBwo=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","r5wfLIFTEo2\u002Bd7Tsx44bFIb0SPNdPvg4KbBRNmbWVFA="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -290,6 +290,16 @@
"frameworks": { "frameworks": {
"net9.0": { "net9.0": {
"targetAlias": "net9.0", "targetAlias": "net9.0",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": {
"target": "Package",
"version": "[9.0.8, )"
},
"Microsoft.Extensions.Http": {
"target": "Package",
"version": "[9.0.8, )"
}
},
"imports": [ "imports": [
"net461", "net461",
"net462", "net462",

View File

@@ -5,6 +5,7 @@
<Import Project="$(NuGetPackageRoot)microsoft.extensions.apidescription.server\9.0.0\build\Microsoft.Extensions.ApiDescription.Server.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.apidescription.server\9.0.0\build\Microsoft.Extensions.ApiDescription.Server.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.extensions.apidescription.server\9.0.0\build\Microsoft.Extensions.ApiDescription.Server.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.apidescription.server\9.0.0\build\Microsoft.Extensions.ApiDescription.Server.targets')" />
<Import Project="$(NuGetPackageRoot)mono.texttemplating\3.0.0\buildTransitive\Mono.TextTemplating.targets" Condition="Exists('$(NuGetPackageRoot)mono.texttemplating\3.0.0\buildTransitive\Mono.TextTemplating.targets')" /> <Import Project="$(NuGetPackageRoot)mono.texttemplating\3.0.0\buildTransitive\Mono.TextTemplating.targets" Condition="Exists('$(NuGetPackageRoot)mono.texttemplating\3.0.0\buildTransitive\Mono.TextTemplating.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.8\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.8\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.codeanalysis.analyzers\3.3.4\buildTransitive\Microsoft.CodeAnalysis.Analyzers.targets')" />
</ImportGroup> </ImportGroup>

View File

@@ -1,6 +0,0 @@
namespace Elecciones.Core;
public class Class1
{
}

View File

@@ -0,0 +1,16 @@
// src/Elecciones.Core/DTOs/AgrupacionDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class AgrupacionDto
{
[JsonPropertyName("idAgrupacion")]
public string IdAgrupacion { get; set; } = null!;
[JsonPropertyName("idAgrupacionTelegrama")]
public string IdAgrupacionTelegrama { get; set; } = null!;
[JsonPropertyName("nombreAgrupacion")]
public string NombreAgrupacion { get; set; } = null!;
}

View File

@@ -0,0 +1,16 @@
// src/Elecciones.Core/DTOs/AmbitoDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class AmbitoDto
{
[JsonPropertyName("nivelld")]
public int NivelId { get; set; }
[JsonPropertyName("nombre")]
public string Nombre { get; set; } = null!;
[JsonPropertyName("codigoAmbitos")]
public CodigoAmbitoDto CodigoAmbitos { get; set; } = null!;
}

View File

@@ -0,0 +1,9 @@
// src/Elecciones.Core/DTOs/ApiResponses/AgrupacionResultadoDto.cs
namespace Elecciones.Core.DTOs.ApiResponses;
public class AgrupacionResultadoDto
{
public string Nombre { get; set; } = null!;
public long Votos { get; set; }
public decimal Porcentaje { get; set; }
}

View File

@@ -0,0 +1,14 @@
// src/Elecciones.Core/DTOs/ApiResponses/MunicipioResultadosDto.cs
namespace Elecciones.Core.DTOs.ApiResponses;
public class MunicipioResultadosDto
{
public string MunicipioNombre { get; set; } = null!;
public DateTime UltimaActualizacion { get; set; }
public decimal PorcentajeEscrutado { get; set; }
public decimal PorcentajeParticipacion { get; set; }
public List<AgrupacionResultadoDto> Resultados { get; set; } = [];
public VotosAdicionalesDto VotosAdicionales { get; set; } = null!;
}

View File

@@ -0,0 +1,7 @@
namespace Elecciones.Core.DTOs.ApiResponses;
public class MunicipioSimpleDto
{
public string Id { get; set; } = null!;
public string Nombre { get; set; } = null!;
}

View File

@@ -0,0 +1,11 @@
namespace Elecciones.Core.DTOs.ApiResponses;
public class ResumenProvincialDto
{
public string ProvinciaNombre { get; set; } = null!;
public DateTime UltimaActualizacion { get; set; }
public decimal PorcentajeEscrutado { get; set; }
public decimal PorcentajeParticipacion { get; set; }
public List<AgrupacionResultadoDto> Resultados { get; set; } = [];
public VotosAdicionalesDto VotosAdicionales { get; set; } = null!;
}

View File

@@ -0,0 +1,9 @@
// src/Elecciones.Core/DTOs/ApiResponses/VotosAdicionalesDto.cs
namespace Elecciones.Core.DTOs.ApiResponses;
public class VotosAdicionalesDto
{
public long EnBlanco { get; set; }
public long Nulos { get; set; }
public long Recurridos { get; set; }
}

View File

@@ -0,0 +1,19 @@
// src/Elecciones.Core/DTOs/CatalogoDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class CatalogoDto
{
[JsonPropertyName("version")]
public int Version { get; set; }
[JsonPropertyName("categoriald")]
public int CategoriaId { get; set; }
[JsonPropertyName("ambitos")]
public List<AmbitoDto> Ambitos { get; set; } = [];
[JsonPropertyName("niveles")]
public List<NivelDto> Niveles { get; set; } = [];
}

View File

@@ -0,0 +1,20 @@
// src/Elecciones.Core/DTOs/CodigoAmbitoDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class CodigoAmbitoDto
{
[JsonPropertyName("distritold")]
public string DistritoId { get; set; } = null!;
// Hacemos que los demás IDs acepten nulos para ser más flexibles
[JsonPropertyName("seccionProvincialld")]
public string? SeccionProvincialId { get; set; }
[JsonPropertyName("seccionld")]
public string? SeccionId { get; set; }
[JsonPropertyName("municipiold")]
public string? MunicipioId { get; set; }
}

View File

@@ -0,0 +1,19 @@
// src/Elecciones.Core/DTOs/EstadoRecuentoDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class EstadoRecuentoDto
{
[JsonPropertyName("mesasEsperadas")]
public int MesasEsperadas { get; set; }
[JsonPropertyName("mesasTotalizadas")]
public int MesasTotalizadas { get; set; }
[JsonPropertyName("cantidadElectores")]
public int CantidadElectores { get; set; }
[JsonPropertyName("participacionPorcentaje")]
public decimal ParticipacionPorcentaje { get; set; }
}

View File

@@ -0,0 +1,13 @@
// src/Elecciones.Core/DTOs/NivelDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class NivelDto
{
[JsonPropertyName("nivelld")]
public int NivelId { get; set; }
[JsonPropertyName("nombre")]
public string Nombre { get; set; } = null!;
}

View File

@@ -0,0 +1,19 @@
// src/Elecciones.Core/DTOs/ResultadosDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class ResultadosDto
{
[JsonPropertyName("fechaTotalizacion")]
public string FechaTotalizacion { get; set; } = null!;
[JsonPropertyName("estadoRecuento")]
public EstadoRecuentoDto EstadoRecuento { get; set; } = null!;
[JsonPropertyName("valoresTotalizadosPositivos")]
public List<VotosPositivosDto> ValoresTotalizadosPositivos { get; set; } = [];
[JsonPropertyName("valoresTotalizadosOtros")]
public VotosOtrosDto? ValoresTotalizadosOtros { get; set; }
}

View File

@@ -0,0 +1,13 @@
// src/Elecciones.Core/DTOs/TokenData.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class TokenData
{
[JsonPropertyName("access_token")]
public string AccessToken { get; set; } = null!;
[JsonPropertyName("expires_in")]
public int ExpiresIn { get; set; }
}

View File

@@ -0,0 +1,19 @@
// src/Elecciones.Core/DTOs/TokenResponse.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class TokenResponse
{
[JsonPropertyName("success")]
public bool Success { get; set; }
[JsonPropertyName("message")]
public string Message { get; set; } = null!;
[JsonPropertyName("data")]
public TokenData? Data { get; set; }
[JsonPropertyName("error")]
public string? Error { get; set; }
}

View File

@@ -0,0 +1,16 @@
// src/Elecciones.Core/DTOs/VotosOtrosDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class VotosOtrosDto
{
[JsonPropertyName("votosNulos")]
public long VotosNulos { get; set; }
[JsonPropertyName("votosEnBlanco")]
public long VotosEnBlanco { get; set; }
[JsonPropertyName("votosRecurridosComandoImpugnados")]
public long VotosRecurridos { get; set; }
}

View File

@@ -0,0 +1,16 @@
// src/Elecciones.Core/DTOs/VotosPositivosDto.cs
using System.Text.Json.Serialization;
namespace Elecciones.Core.DTOs;
public class VotosPositivosDto
{
[JsonPropertyName("idAgrupacion")]
public string IdAgrupacion { get; set; } = null!;
[JsonPropertyName("nombreAgrupacion")]
public string NombreAgrupacion { get; set; } = null!;
[JsonPropertyName("votos")]
public long Votos { get; set; }
}

View File

@@ -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+d9bcfd70865a12c229e6a761639094b45de862bd")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b90baadeedb870b5b1c9eeeb7022a0d211b61bec")]
[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")]

View File

@@ -1,6 +0,0 @@
namespace Elecciones.Database;
public class Class1
{
}

View File

@@ -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+d9bcfd70865a12c229e6a761639094b45de862bd")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b90baadeedb870b5b1c9eeeb7022a0d211b61bec")]
[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")]

View File

@@ -1,6 +0,0 @@
namespace Elecciones.Infrastructure;
public class Class1
{
}

View File

@@ -4,6 +4,11 @@
<ProjectReference Include="..\Elecciones.Core\Elecciones.Core.csproj" /> <ProjectReference Include="..\Elecciones.Core\Elecciones.Core.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.8" />
</ItemGroup>
<PropertyGroup> <PropertyGroup>
<TargetFramework>net9.0</TargetFramework> <TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings> <ImplicitUsings>enable</ImplicitUsings>

View File

@@ -0,0 +1,86 @@
using Elecciones.Core.DTOs;
using Microsoft.Extensions.Configuration;
using System.Collections.Generic;
using System.Net.Http;
using System.Net.Http.Json;
using System.Threading.Tasks;
namespace Elecciones.Infrastructure.Services;
public class ElectoralApiService : IElectoralApiService
{
private readonly IHttpClientFactory _httpClientFactory;
private readonly IConfiguration _configuration;
public ElectoralApiService(IHttpClientFactory httpClientFactory, IConfiguration configuration)
{
_httpClientFactory = httpClientFactory;
_configuration = configuration;
}
public async Task<string?> GetAuthTokenAsync()
{
var client = _httpClientFactory.CreateClient("ElectoralApiClient");
var username = _configuration["ElectoralApi:Username"];
var password = _configuration["ElectoralApi:Password"];
if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) return null;
var request = new HttpRequestMessage(HttpMethod.Get, "/api/createtoken");
request.Headers.Add("username", username);
request.Headers.Add("password", password);
var response = await client.SendAsync(request);
if (!response.IsSuccessStatusCode) return null;
var tokenResponse = await response.Content.ReadFromJsonAsync<TokenResponse>();
return (tokenResponse is { Success: true, Data.AccessToken: not null })
? tokenResponse.Data.AccessToken
: null;
}
public async Task<List<CatalogoDto>?> GetCatalogoCompletoAsync(string authToken)
{
var client = _httpClientFactory.CreateClient("ElectoralApiClient");
var request = new HttpRequestMessage(HttpMethod.Get, "/api/catalogo/getCatalogo?categoriald=5");
request.Headers.Add("Authorization", $"Bearer {authToken}");
var response = await client.SendAsync(request);
return response.IsSuccessStatusCode
? await response.Content.ReadFromJsonAsync<List<CatalogoDto>>()
: null;
}
public async Task<List<AgrupacionDto>?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId)
{
var client = _httpClientFactory.CreateClient("ElectoralApiClient");
var requestUri = $"/api/catalogo/getAgrupaciones?distritold={distritoId}&categoriald={categoriaId}";
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
request.Headers.Add("Authorization", $"Bearer {authToken}");
var response = await client.SendAsync(request);
return response.IsSuccessStatusCode
? await response.Content.ReadFromJsonAsync<List<AgrupacionDto>>()
: null;
}
public async Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string seccionId, string municipioId)
{
var client = _httpClientFactory.CreateClient("ElectoralApiClient");
// Construimos la URL con todos los parámetros requeridos. Usamos categoría 5 (Diputados) como ejemplo.
var requestUri = $"/api/resultados/getResultados?distritold={distritoId}&seccionld={seccionId}&municipiold={municipioId}&categoriald=5";
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
request.Headers.Add("Authorization", $"Bearer {authToken}");
var response = await client.SendAsync(request);
if (!response.IsSuccessStatusCode)
{
return null;
}
return await response.Content.ReadFromJsonAsync<ResultadosDto>();
}
}

View File

@@ -0,0 +1,101 @@
// src/Elecciones.Infrastructure/Services/FakeElectoralApiService.cs
using Elecciones.Core.DTOs;
using Microsoft.Extensions.Logging;
namespace Elecciones.Infrastructure.Services;
public class FakeElectoralApiService : IElectoralApiService
{
private readonly ILogger<FakeElectoralApiService> _logger;
public FakeElectoralApiService(ILogger<FakeElectoralApiService> logger)
{
_logger = logger;
}
public Task<string?> GetAuthTokenAsync()
{
_logger.LogWarning("--- USANDO SERVICIO FALSO (FAKE) ---");
_logger.LogInformation("Simulando obtención de token...");
string fakeToken = "FAKE_TOKEN_FOR_DEVELOPMENT";
return Task.FromResult<string?>(fakeToken);
}
public Task<List<CatalogoDto>?> GetCatalogoCompletoAsync(string authToken)
{
_logger.LogInformation("Simulando obtención de Catálogo Completo...");
var catalogo = new List<CatalogoDto>
{
new() // Simulamos el catálogo para la categoría de Diputados (ID 5)
{
Version = 1,
CategoriaId = 5,
Ambitos =
[
new() { NivelId = 10, Nombre = "BUENOS AIRES", CodigoAmbitos = new() { DistritoId = "02" } },
new() { NivelId = 5, Nombre = "LA PLATA", CodigoAmbitos = new() { DistritoId = "02", SeccionId = "0001", MunicipioId = "056" } },
new() { NivelId = 5, Nombre = "MAR DEL PLATA", CodigoAmbitos = new() { DistritoId = "02", SeccionId = "0005", MunicipioId = "035" } }
],
Niveles =
[
new() { NivelId = 10, Nombre = "Provincia" },
new() { NivelId = 5, Nombre = "Municipio" }
]
}
};
return Task.FromResult<List<CatalogoDto>?>(catalogo);
}
public Task<List<AgrupacionDto>?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId)
{
_logger.LogInformation("Simulando obtención de Agrupaciones Políticas para el distrito {Distrito} y categoría {Categoria}...", distritoId, categoriaId);
var agrupaciones = new List<AgrupacionDto>
{
new() { IdAgrupacion = "018", IdAgrupacionTelegrama = "131", NombreAgrupacion = "FRENTE DE AVANZADA" },
new() { IdAgrupacion = "025", IdAgrupacionTelegrama = "132", NombreAgrupacion = "ALIANZA POR EL FUTURO" },
new() { IdAgrupacion = "031", IdAgrupacionTelegrama = "133", NombreAgrupacion = "UNION POPULAR" },
new() { IdAgrupacion = "045", IdAgrupacionTelegrama = "134", NombreAgrupacion = "PARTIDO VECINALISTA" }
};
return Task.FromResult<List<AgrupacionDto>?>(agrupaciones);
}
public Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string seccionId, string municipioId)
{
_logger.LogInformation("Simulando obtención de Resultados para el municipio {MunicipioId}...", municipioId);
// YA NO FILTRAMOS POR ID. DEVOLVEMOS DATOS SIMULADOS PARA CUALQUIER MUNICIPIO.
var random = new Random();
var resultados = new ResultadosDto
{
FechaTotalizacion = DateTime.Now.ToString("o"),
EstadoRecuento = new EstadoRecuentoDto
{
MesasEsperadas = random.Next(100, 2000), // Hacemos que varíe
MesasTotalizadas = random.Next(50, 100),
CantidadElectores = random.Next(50000, 600000),
ParticipacionPorcentaje = random.Next(60, 85) + (decimal)random.NextDouble()
},
ValoresTotalizadosPositivos =
[
// Usamos los IDs reales de nuestro catálogo de agrupaciones falsas
new() { IdAgrupacion = "018", NombreAgrupacion = "FRENTE DE AVANZADA", Votos = random.Next(10000, 20000) },
new() { IdAgrupacion = "025", NombreAgrupacion = "ALIANZA POR EL FUTURO", Votos = random.Next(15000, 25000) },
new() { IdAgrupacion = "031", NombreAgrupacion = "UNION POPULAR", Votos = random.Next(5000, 10000) },
new() { IdAgrupacion = "045", NombreAgrupacion = "PARTIDO VECINALISTA", Votos = random.Next(2000, 5000) }
],
ValoresTotalizadosOtros = new VotosOtrosDto
{
VotosEnBlanco = random.Next(1000, 2000),
VotosNulos = random.Next(500, 1000),
VotosRecurridos = random.Next(20, 50)
}
};
return Task.FromResult<ResultadosDto?>(resultados);
}
}

View File

@@ -0,0 +1,12 @@
// src/Elecciones.Infrastructure/Services/IElectoralApiService.cs
using Elecciones.Core.DTOs;
namespace Elecciones.Infrastructure.Services;
public interface IElectoralApiService
{
Task<string?> GetAuthTokenAsync();
Task<List<CatalogoDto>?> GetCatalogoCompletoAsync(string authToken);
Task<List<AgrupacionDto>?> GetAgrupacionesAsync(string authToken, string distritoId, int categoriaId);
Task<ResultadosDto?> GetResultadosAsync(string authToken, string distritoId, string seccionId, string municipioId);
}

View File

@@ -8,12 +8,167 @@
".NETCoreApp,Version=v9.0": { ".NETCoreApp,Version=v9.0": {
"Elecciones.Infrastructure/1.0.0": { "Elecciones.Infrastructure/1.0.0": {
"dependencies": { "dependencies": {
"Elecciones.Core": "1.0.0" "Elecciones.Core": "1.0.0",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Http": "9.0.8"
}, },
"runtime": { "runtime": {
"Elecciones.Infrastructure.dll": {} "Elecciones.Infrastructure.dll": {}
} }
}, },
"Microsoft.Extensions.Configuration/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Primitives": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Configuration.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Configuration.Abstractions/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Primitives": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Configuration.Abstractions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Configuration.Binder/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Configuration.Binder.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.DependencyInjection/9.0.8": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.DependencyInjection.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.DependencyInjection.Abstractions/9.0.8": {
"runtime": {
"lib/net9.0/Microsoft.Extensions.DependencyInjection.Abstractions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Diagnostics/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration": "9.0.8",
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.8",
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Diagnostics.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Diagnostics.Abstractions/9.0.8": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Http/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Diagnostics": "9.0.8",
"Microsoft.Extensions.Logging": "9.0.8",
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Http.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Logging/9.0.8": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.8",
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Logging.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Logging.Abstractions/9.0.8": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Logging.Abstractions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Options/9.0.8": {
"dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Primitives": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Options.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Options.ConfigurationExtensions/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Configuration.Binder": "9.0.8",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8",
"Microsoft.Extensions.Primitives": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Primitives/9.0.8": {
"runtime": {
"lib/net9.0/Microsoft.Extensions.Primitives.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Elecciones.Core/1.0.0": { "Elecciones.Core/1.0.0": {
"runtime": { "runtime": {
"Elecciones.Core.dll": { "Elecciones.Core.dll": {
@@ -30,6 +185,97 @@
"serviceable": false, "serviceable": false,
"sha512": "" "sha512": ""
}, },
"Microsoft.Extensions.Configuration/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-6m+8Xgmf8UWL0p/oGqBM+0KbHE5/ePXbV1hKXgC59zEv0aa0DW5oiiyxDbK5kH5j4gIvyD5uWL0+HadKBJngvQ==",
"path": "microsoft.extensions.configuration/9.0.8",
"hashPath": "microsoft.extensions.configuration.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Abstractions/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-yNou2KM35RvzOh4vUFtl2l33rWPvOCoba+nzEDJ+BgD8aOL/jew4WPCibQvntRfOJ2pJU8ARygSMD+pdjvDHuA==",
"path": "microsoft.extensions.configuration.abstractions/9.0.8",
"hashPath": "microsoft.extensions.configuration.abstractions.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Configuration.Binder/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-0vK9DnYrYChdiH3yRZWkkp4x4LbrfkWEdBc5HOsQ8t/0CLOWKXKkkhOE8A1shlex0hGydbGrhObeypxz/QTm+w==",
"path": "microsoft.extensions.configuration.binder/9.0.8",
"hashPath": "microsoft.extensions.configuration.binder.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-JJjI2Fa+QtZcUyuNjbKn04OjIUX5IgFGFu/Xc+qvzh1rXdZHLcnqqVXhR4093bGirTwacRlHiVg1XYI9xum6QQ==",
"path": "microsoft.extensions.dependencyinjection/9.0.8",
"hashPath": "microsoft.extensions.dependencyinjection.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.DependencyInjection.Abstractions/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-xY3lTjj4+ZYmiKIkyWitddrp1uL5uYiweQjqo4BKBw01ZC4HhcfgLghDpPZcUlppgWAFqFy9SgkiYWOMx365pw==",
"path": "microsoft.extensions.dependencyinjection.abstractions/9.0.8",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Diagnostics/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-BKkLCFXzJvNmdngeYBf72VXoZqTJSb1orvjdzDLaGobicoGFBPW8ug2ru1nnEewMEwJzMgnsjHQY8EaKWmVhKg==",
"path": "microsoft.extensions.diagnostics/9.0.8",
"hashPath": "microsoft.extensions.diagnostics.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Diagnostics.Abstractions/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-UDY7blv4DCyIJ/8CkNrQKLaAZFypXQavRZ2DWf/2zi1mxYYKKw2t8AOCBWxNntyPZHPGhtEmL3snFM98ADZqTw==",
"path": "microsoft.extensions.diagnostics.abstractions/9.0.8",
"hashPath": "microsoft.extensions.diagnostics.abstractions.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Http/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-jDj+4aDByk47oESlDDTtk6LWzlXlmoCsjCn6ihd+i9OntN885aPLszUII5+w0B/7wYSZcS3KdjqLAIhKLSiBXQ==",
"path": "microsoft.extensions.http/9.0.8",
"hashPath": "microsoft.extensions.http.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Logging/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-Z/7ze+0iheT7FJeZPqJKARYvyC2bmwu3whbm/48BJjdlGVvgDguoCqJIkI/67NkroTYobd5geai1WheNQvWrgA==",
"path": "microsoft.extensions.logging/9.0.8",
"hashPath": "microsoft.extensions.logging.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Logging.Abstractions/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-pYnAffJL7ARD/HCnnPvnFKSIHnTSmWz84WIlT9tPeQ4lHNiu0Az7N/8itihWvcF8sT+VVD5lq8V+ckMzu4SbOw==",
"path": "microsoft.extensions.logging.abstractions/9.0.8",
"hashPath": "microsoft.extensions.logging.abstractions.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Options/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-OmTaQ0v4gxGQkehpwWIqPoEiwsPuG/u4HUsbOFoWGx4DKET2AXzopnFe/fE608FIhzc/kcg2p8JdyMRCCUzitQ==",
"path": "microsoft.extensions.options/9.0.8",
"hashPath": "microsoft.extensions.options.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Options.ConfigurationExtensions/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-eW2s6n06x0w6w4nsX+SvpgsFYkl+Y0CttYAt6DKUXeqprX+hzNqjSfOh637fwNJBg7wRBrOIRHe49gKiTgJxzQ==",
"path": "microsoft.extensions.options.configurationextensions/9.0.8",
"hashPath": "microsoft.extensions.options.configurationextensions.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Primitives/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-tizSIOEsIgSNSSh+hKeUVPK7xmTIjR8s+mJWOu1KXV3htvNQiPMFRMO17OdI1y/4ZApdBVk49u/08QGC9yvLug==",
"path": "microsoft.extensions.primitives/9.0.8",
"hashPath": "microsoft.extensions.primitives.9.0.8.nupkg.sha512"
},
"Elecciones.Core/1.0.0": { "Elecciones.Core/1.0.0": {
"type": "project", "type": "project",
"serviceable": false, "serviceable": false,

View File

@@ -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+d9bcfd70865a12c229e6a761639094b45de862bd")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b90baadeedb870b5b1c9eeeb7022a0d211b61bec")]
[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")]

View File

@@ -118,6 +118,16 @@
"frameworks": { "frameworks": {
"net9.0": { "net9.0": {
"targetAlias": "net9.0", "targetAlias": "net9.0",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": {
"target": "Package",
"version": "[9.0.8, )"
},
"Microsoft.Extensions.Http": {
"target": "Package",
"version": "[9.0.8, )"
}
},
"imports": [ "imports": [
"net461", "net461",
"net462", "net462",

View File

@@ -1,2 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?> <?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" /> <Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.8\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.8\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
</ImportGroup>
</Project>

View File

@@ -10,6 +10,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" /> <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="9.0.5" />
<PackageReference Include="Microsoft.Extensions.Http" Version="9.0.8" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -1,4 +1,5 @@
using Elecciones.Database; using Elecciones.Database;
using Elecciones.Infrastructure.Services;
using Elecciones.Worker; using Elecciones.Worker;
using Microsoft.EntityFrameworkCore; using Microsoft.EntityFrameworkCore;
@@ -6,15 +7,32 @@ var builder = Host.CreateApplicationBuilder(args);
// --- Configuración de Servicios --- // --- Configuración de Servicios ---
// Añade la cadena de conexión y el DbContext. El worker lo necesita para guardar los datos. // 1. Configuración de Base de Datos (¡Este bloque es esencial!)
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection"); var connectionString = builder.Configuration.GetConnectionString("DefaultConnection");
builder.Services.AddDbContext<EleccionesDbContext>(options => builder.Services.AddDbContext<EleccionesDbContext>(options =>
options.UseSqlServer(connectionString)); options.UseSqlServer(connectionString));
// Registra el Worker como un servicio que se ejecuta en segundo plano. // 2. Configuración del Servicio de API (elegirá el Real o el Falso según el modo de compilación)
#if DEBUG
// En modo DEBUG (desarrollo local), usamos el servicio FALSO.
// No es necesario registrar el ILogger, .NET lo inyecta automáticamente.
builder.Services.AddSingleton<IElectoralApiService, FakeElectoralApiService>();
#else
// En modo RELEASE (producción), usamos el servicio REAL.
builder.Services.AddHttpClient("ElectoralApiClient", client =>
{
var baseUrl = builder.Configuration["ElectoralApi:BaseUrl"];
if (!string.IsNullOrEmpty(baseUrl))
{
client.BaseAddress = new Uri(baseUrl);
}
});
builder.Services.AddSingleton<IElectoralApiService, ElectoralApiService>();
#endif
// 3. Registrar el Worker como un servicio que se ejecuta en segundo plano.
builder.Services.AddHostedService<Worker>(); builder.Services.AddHostedService<Worker>();
var host = builder.Build();
// Inicia el host, que a su vez iniciará nuestro Worker. var host = builder.Build();
host.Run(); host.Run();

View File

@@ -1,23 +1,233 @@
using Elecciones.Database;
using Elecciones.Database.Entities;
using Elecciones.Infrastructure.Services;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Elecciones.Worker; namespace Elecciones.Worker;
public class Worker : BackgroundService public class Worker : BackgroundService
{ {
private readonly ILogger<Worker> _logger; private readonly ILogger<Worker> _logger;
private readonly IElectoralApiService _apiService;
private readonly IServiceProvider _serviceProvider;
private string? _authToken; // Almacenamos el token para reutilizarlo en el ciclo de vida
public Worker(ILogger<Worker> logger) public Worker(ILogger<Worker> logger, IElectoralApiService apiService, IServiceProvider serviceProvider)
{ {
_logger = logger; _logger = logger;
_apiService = apiService;
_serviceProvider = serviceProvider;
} }
protected override async Task ExecuteAsync(CancellationToken stoppingToken) protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{ {
_logger.LogInformation("Elecciones Worker iniciado a las: {time}", DateTimeOffset.Now);
// --- 1. SINCRONIZACIÓN INICIAL DE CATÁLOGOS ---
// Se ejecuta una sola vez al inicio para poblar las tablas maestras.
await SincronizarCatalogosAsync(stoppingToken);
// --- 2. BUCLE DE SONDEO DE RESULTADOS ---
_logger.LogInformation("-------------------------------------------------");
_logger.LogInformation("Iniciando sondeo periódico de resultados...");
_logger.LogInformation("-------------------------------------------------");
while (!stoppingToken.IsCancellationRequested) while (!stoppingToken.IsCancellationRequested)
{ {
if (_logger.IsEnabled(LogLevel.Information)) await SondearResultadosAsync(stoppingToken);
try
{ {
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now); // Esperamos 10 segundos antes de la siguiente consulta.
await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
} }
await Task.Delay(1000, stoppingToken); catch (TaskCanceledException)
{
// Es normal que esto ocurra cuando se detiene la aplicación.
break;
}
}
_logger.LogInformation("Elecciones Worker se está deteniendo.");
}
private async Task ObtenerTokenSiEsNecesario(CancellationToken stoppingToken)
{
// En un futuro, se podría añadir lógica para renovar el token solo cuando expire.
// Por ahora, para asegurar que siempre sea válido, lo obtenemos cada vez.
_authToken = await _apiService.GetAuthTokenAsync();
if (string.IsNullOrEmpty(_authToken))
{
_logger.LogError("No se pudo obtener el token, se cancelan las operaciones.");
}
}
private async Task SondearResultadosAsync(CancellationToken stoppingToken)
{
try
{
await ObtenerTokenSiEsNecesario(stoppingToken);
if (string.IsNullOrEmpty(_authToken) || stoppingToken.IsCancellationRequested) return;
// Usamos un 'scope' propio para esta operación
using var scope = _serviceProvider.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<EleccionesDbContext>();
// 1. OBTENEMOS LA LISTA DE TODOS LOS MUNICIPIOS DE NUESTRA BD
var municipiosASondear = await dbContext.AmbitosGeograficos
.AsNoTracking()
.Where(a => a.NivelId == 5 && a.MunicipioId != null && a.DistritoId != null && a.SeccionId != null)
.Select(a => new { a.Id, a.MunicipioId, a.SeccionId, a.DistritoId })
.ToListAsync(stoppingToken);
_logger.LogInformation("Iniciando sondeo para {count} municipios.", municipiosASondear.Count);
// 2. RECORREMOS LA LISTA Y PROCESAMOS CADA MUNICIPIO
foreach (var municipio in municipiosASondear)
{
if (stoppingToken.IsCancellationRequested) break;
_logger.LogInformation("Sondeando resultados para el municipio: {municipioId}", municipio.MunicipioId);
var resultados = await _apiService.GetResultadosAsync(_authToken, municipio.DistritoId!, municipio.SeccionId!, municipio.MunicipioId!);
if (resultados is null)
{
_logger.LogWarning("No se recibieron resultados para el municipio {municipioId}", municipio.MunicipioId);
continue; // Saltamos al siguiente municipio
}
// 3. GUARDAMOS LOS DATOS (Lógica de Upsert)
// La lógica de guardado que ya teníamos funciona perfectamente para cada municipio.
// La pasamos a un método separado para mayor claridad.
await GuardarResultadosDeAmbitoAsync(dbContext, municipio.Id, resultados, stoppingToken);
_logger.LogInformation("Resultados para el municipio {municipioId} guardados/actualizados.", municipio.MunicipioId);
}
}
catch (Exception ex)
{
_logger.LogError(ex, "Ocurrió un error inesperado durante el sondeo de resultados.");
}
}
// NUEVO MÉTODO AUXILIAR PARA GUARDAR LOS DATOS
private async Task GuardarResultadosDeAmbitoAsync(EleccionesDbContext dbContext, int ambitoId, Elecciones.Core.DTOs.ResultadosDto resultados, CancellationToken stoppingToken)
{
// --- ACTUALIZAR O INSERTAR ESTADO RECUENTO ---
var estadoRecuento = await dbContext.EstadosRecuentos.FindAsync(new object[] { ambitoId }, cancellationToken: stoppingToken);
if (estadoRecuento == null)
{
estadoRecuento = new EstadoRecuento { AmbitoGeograficoId = ambitoId };
dbContext.EstadosRecuentos.Add(estadoRecuento);
}
estadoRecuento.FechaTotalizacion = DateTime.Parse(resultados.FechaTotalizacion).ToUniversalTime();
estadoRecuento.MesasEsperadas = resultados.EstadoRecuento.MesasEsperadas;
estadoRecuento.MesasTotalizadas = resultados.EstadoRecuento.MesasTotalizadas;
estadoRecuento.CantidadElectores = resultados.EstadoRecuento.CantidadElectores;
estadoRecuento.ParticipacionPorcentaje = resultados.EstadoRecuento.ParticipacionPorcentaje;
if (resultados.ValoresTotalizadosOtros != null)
{
estadoRecuento.VotosEnBlanco = resultados.ValoresTotalizadosOtros.VotosEnBlanco;
estadoRecuento.VotosNulos = resultados.ValoresTotalizadosOtros.VotosNulos;
estadoRecuento.VotosRecurridos = resultados.ValoresTotalizadosOtros.VotosRecurridos;
}
// --- ACTUALIZAR O INSERTAR VOTOS POSITIVOS ---
foreach (var votoPositivo in resultados.ValoresTotalizadosPositivos)
{
var resultadoVoto = await dbContext.ResultadosVotos.FirstOrDefaultAsync(
rv => rv.AmbitoGeograficoId == ambitoId && rv.AgrupacionPoliticaId == votoPositivo.IdAgrupacion, stoppingToken);
if (resultadoVoto == null)
{
resultadoVoto = new ResultadoVoto
{
AmbitoGeograficoId = ambitoId,
AgrupacionPoliticaId = votoPositivo.IdAgrupacion
};
dbContext.ResultadosVotos.Add(resultadoVoto);
}
resultadoVoto.CantidadVotos = votoPositivo.Votos;
}
await dbContext.SaveChangesAsync(stoppingToken);
}
private async Task SincronizarCatalogosAsync(CancellationToken stoppingToken)
{
try
{
_logger.LogInformation("Iniciando sincronización de catálogos maestros...");
await ObtenerTokenSiEsNecesario(stoppingToken);
if (string.IsNullOrEmpty(_authToken) || stoppingToken.IsCancellationRequested) return;
using var scope = _serviceProvider.CreateScope();
var dbContext = scope.ServiceProvider.GetRequiredService<EleccionesDbContext>();
_logger.LogInformation("Limpiando tablas maestras para la nueva ingesta...");
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM ResultadosVotos", stoppingToken);
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM EstadosRecuentos", stoppingToken);
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM AgrupacionesPoliticas", stoppingToken);
await dbContext.Database.ExecuteSqlRawAsync("DELETE FROM AmbitosGeograficos", stoppingToken);
// --- 1. INGESTA DE ÁMBITOS GEOGRÁFICOS ---
var catalogos = await _apiService.GetCatalogoCompletoAsync(_authToken);
if (catalogos is { Count: > 0 })
{
foreach (var ambitoDto in catalogos.SelectMany(c => c.Ambitos))
{
var nuevoAmbito = new AmbitoGeografico
{
Nombre = ambitoDto.Nombre,
NivelId = ambitoDto.NivelId,
DistritoId = ambitoDto.CodigoAmbitos.DistritoId,
SeccionId = ambitoDto.CodigoAmbitos.SeccionId,
MunicipioId = ambitoDto.CodigoAmbitos.MunicipioId,
SeccionProvincialId = ambitoDto.CodigoAmbitos.SeccionProvincialId
};
await dbContext.AmbitosGeograficos.AddAsync(nuevoAmbito, stoppingToken);
}
_logger.LogInformation("Datos de Ámbitos Geográficos listos para ser guardados.");
}
else
{
_logger.LogWarning("No se recibieron datos del catálogo de Ámbitos.");
}
// --- 2. INGESTA DE AGRUPACIONES POLÍTICAS ---
var agrupaciones = await _apiService.GetAgrupacionesAsync(_authToken, "02", 5);
if (agrupaciones is { Count: > 0 })
{
foreach (var agrupacionDto in agrupaciones)
{
var nuevaAgrupacion = new AgrupacionPolitica
{
Id = agrupacionDto.IdAgrupacion,
IdTelegrama = agrupacionDto.IdAgrupacionTelegrama,
Nombre = agrupacionDto.NombreAgrupacion
};
await dbContext.AgrupacionesPoliticas.AddAsync(nuevaAgrupacion, stoppingToken);
}
_logger.LogInformation("Datos de Agrupaciones Políticas listos para ser guardados.");
}
else
{
_logger.LogWarning("No se recibieron datos del catálogo de Agrupaciones.");
}
// --- 3. GUARDADO FINAL EN LA BASE DE DATOS ---
int registrosGuardados = await dbContext.SaveChangesAsync(stoppingToken);
_logger.LogInformation("{count} registros totales han sido guardados en la base de datos.", registrosGuardados);
_logger.LogInformation("Sincronización de catálogos completada exitosamente.");
}
catch (Exception ex)
{
_logger.LogError(ex, "Ocurrió un error CRÍTICO durante la sincronización de catálogos. El worker podría no funcionar correctamente.");
} }
} }
} }

View File

@@ -4,5 +4,13 @@
"Default": "Information", "Default": "Information",
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
},
"ElectoralApi": {
"BaseUrl": "https://api.eleccionesbonaerenses.gba.gob.ar",
"Username": "30500094156@elecciones2025.onmicrosoft.com",
"Password": "PTP847elec"
},
"ConnectionStrings": {
"DefaultConnection": "Server=TECNICA3;Database=Elecciones2025;User Id=apielecciones2025;Password=PTP847Elecciones2025;Encrypt=False;MultipleActiveResultSets=True;TrustServerCertificate=True;"
} }
} }

View File

@@ -4,5 +4,10 @@
"Default": "Information", "Default": "Information",
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
},
"ElectoralApi": {
"BaseUrl": "https://api.eleccionesbonaerenses.gba.gob.ar",
"Username": "30500094156@elecciones2025.onmicrosoft.com",
"Password": "PTP847elec"
} }
} }

View File

@@ -11,7 +11,8 @@
"Elecciones.Database": "1.0.0", "Elecciones.Database": "1.0.0",
"Elecciones.Infrastructure": "1.0.0", "Elecciones.Infrastructure": "1.0.0",
"Microsoft.EntityFrameworkCore.SqlServer": "9.0.8", "Microsoft.EntityFrameworkCore.SqlServer": "9.0.8",
"Microsoft.Extensions.Hosting": "9.0.5" "Microsoft.Extensions.Hosting": "9.0.5",
"Microsoft.Extensions.Http": "9.0.8"
}, },
"runtime": { "runtime": {
"Elecciones.Worker.dll": {} "Elecciones.Worker.dll": {}
@@ -202,7 +203,7 @@
} }
} }
}, },
"Microsoft.Extensions.Configuration/9.0.5": { "Microsoft.Extensions.Configuration/9.0.8": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8", "Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Primitives": "9.0.8" "Microsoft.Extensions.Primitives": "9.0.8"
@@ -210,7 +211,7 @@
"runtime": { "runtime": {
"lib/net9.0/Microsoft.Extensions.Configuration.dll": { "lib/net9.0/Microsoft.Extensions.Configuration.dll": {
"assemblyVersion": "9.0.0.0", "assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.525.21509" "fileVersion": "9.0.825.36511"
} }
} }
}, },
@@ -225,20 +226,20 @@
} }
} }
}, },
"Microsoft.Extensions.Configuration.Binder/9.0.5": { "Microsoft.Extensions.Configuration.Binder/9.0.8": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8" "Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
}, },
"runtime": { "runtime": {
"lib/net9.0/Microsoft.Extensions.Configuration.Binder.dll": { "lib/net9.0/Microsoft.Extensions.Configuration.Binder.dll": {
"assemblyVersion": "9.0.0.0", "assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.525.21509" "fileVersion": "9.0.825.36511"
} }
} }
}, },
"Microsoft.Extensions.Configuration.CommandLine/9.0.5": { "Microsoft.Extensions.Configuration.CommandLine/9.0.5": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration": "9.0.5", "Microsoft.Extensions.Configuration": "9.0.8",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8" "Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
}, },
"runtime": { "runtime": {
@@ -250,7 +251,7 @@
}, },
"Microsoft.Extensions.Configuration.EnvironmentVariables/9.0.5": { "Microsoft.Extensions.Configuration.EnvironmentVariables/9.0.5": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration": "9.0.5", "Microsoft.Extensions.Configuration": "9.0.8",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8" "Microsoft.Extensions.Configuration.Abstractions": "9.0.8"
}, },
"runtime": { "runtime": {
@@ -262,7 +263,7 @@
}, },
"Microsoft.Extensions.Configuration.FileExtensions/9.0.5": { "Microsoft.Extensions.Configuration.FileExtensions/9.0.5": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration": "9.0.5", "Microsoft.Extensions.Configuration": "9.0.8",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8", "Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.5", "Microsoft.Extensions.FileProviders.Abstractions": "9.0.5",
"Microsoft.Extensions.FileProviders.Physical": "9.0.5", "Microsoft.Extensions.FileProviders.Physical": "9.0.5",
@@ -277,7 +278,7 @@
}, },
"Microsoft.Extensions.Configuration.Json/9.0.5": { "Microsoft.Extensions.Configuration.Json/9.0.5": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration": "9.0.5", "Microsoft.Extensions.Configuration": "9.0.8",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8", "Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Configuration.FileExtensions": "9.0.5", "Microsoft.Extensions.Configuration.FileExtensions": "9.0.5",
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.5" "Microsoft.Extensions.FileProviders.Abstractions": "9.0.5"
@@ -322,20 +323,20 @@
} }
} }
}, },
"Microsoft.Extensions.Diagnostics/9.0.5": { "Microsoft.Extensions.Diagnostics/9.0.8": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration": "9.0.5", "Microsoft.Extensions.Configuration": "9.0.8",
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.5", "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.8",
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.5" "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.8"
}, },
"runtime": { "runtime": {
"lib/net9.0/Microsoft.Extensions.Diagnostics.dll": { "lib/net9.0/Microsoft.Extensions.Diagnostics.dll": {
"assemblyVersion": "9.0.0.0", "assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.525.21509" "fileVersion": "9.0.825.36511"
} }
} }
}, },
"Microsoft.Extensions.Diagnostics.Abstractions/9.0.5": { "Microsoft.Extensions.Diagnostics.Abstractions/9.0.8": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8" "Microsoft.Extensions.Options": "9.0.8"
@@ -343,7 +344,7 @@
"runtime": { "runtime": {
"lib/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": { "lib/net9.0/Microsoft.Extensions.Diagnostics.Abstractions.dll": {
"assemblyVersion": "9.0.0.0", "assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.525.21509" "fileVersion": "9.0.825.36511"
} }
} }
}, },
@@ -381,9 +382,9 @@
}, },
"Microsoft.Extensions.Hosting/9.0.5": { "Microsoft.Extensions.Hosting/9.0.5": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration": "9.0.5", "Microsoft.Extensions.Configuration": "9.0.8",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8", "Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Configuration.Binder": "9.0.5", "Microsoft.Extensions.Configuration.Binder": "9.0.8",
"Microsoft.Extensions.Configuration.CommandLine": "9.0.5", "Microsoft.Extensions.Configuration.CommandLine": "9.0.5",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "9.0.5", "Microsoft.Extensions.Configuration.EnvironmentVariables": "9.0.5",
"Microsoft.Extensions.Configuration.FileExtensions": "9.0.5", "Microsoft.Extensions.Configuration.FileExtensions": "9.0.5",
@@ -391,7 +392,7 @@
"Microsoft.Extensions.Configuration.UserSecrets": "9.0.5", "Microsoft.Extensions.Configuration.UserSecrets": "9.0.5",
"Microsoft.Extensions.DependencyInjection": "9.0.8", "Microsoft.Extensions.DependencyInjection": "9.0.8",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Diagnostics": "9.0.5", "Microsoft.Extensions.Diagnostics": "9.0.8",
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.5", "Microsoft.Extensions.FileProviders.Abstractions": "9.0.5",
"Microsoft.Extensions.FileProviders.Physical": "9.0.5", "Microsoft.Extensions.FileProviders.Physical": "9.0.5",
"Microsoft.Extensions.Hosting.Abstractions": "9.0.5", "Microsoft.Extensions.Hosting.Abstractions": "9.0.5",
@@ -415,7 +416,7 @@
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8", "Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Diagnostics.Abstractions": "9.0.5", "Microsoft.Extensions.Diagnostics.Abstractions": "9.0.8",
"Microsoft.Extensions.FileProviders.Abstractions": "9.0.5", "Microsoft.Extensions.FileProviders.Abstractions": "9.0.5",
"Microsoft.Extensions.Logging.Abstractions": "9.0.8" "Microsoft.Extensions.Logging.Abstractions": "9.0.8"
}, },
@@ -426,6 +427,22 @@
} }
} }
}, },
"Microsoft.Extensions.Http/9.0.8": {
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Diagnostics": "9.0.8",
"Microsoft.Extensions.Logging": "9.0.8",
"Microsoft.Extensions.Logging.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8"
},
"runtime": {
"lib/net9.0/Microsoft.Extensions.Http.dll": {
"assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.825.36511"
}
}
},
"Microsoft.Extensions.Logging/9.0.8": { "Microsoft.Extensions.Logging/9.0.8": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.DependencyInjection": "9.0.8", "Microsoft.Extensions.DependencyInjection": "9.0.8",
@@ -452,14 +469,14 @@
}, },
"Microsoft.Extensions.Logging.Configuration/9.0.5": { "Microsoft.Extensions.Logging.Configuration/9.0.5": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration": "9.0.5", "Microsoft.Extensions.Configuration": "9.0.8",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8", "Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Configuration.Binder": "9.0.5", "Microsoft.Extensions.Configuration.Binder": "9.0.8",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Logging": "9.0.8", "Microsoft.Extensions.Logging": "9.0.8",
"Microsoft.Extensions.Logging.Abstractions": "9.0.8", "Microsoft.Extensions.Logging.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8", "Microsoft.Extensions.Options": "9.0.8",
"Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.5" "Microsoft.Extensions.Options.ConfigurationExtensions": "9.0.8"
}, },
"runtime": { "runtime": {
"lib/net9.0/Microsoft.Extensions.Logging.Configuration.dll": { "lib/net9.0/Microsoft.Extensions.Logging.Configuration.dll": {
@@ -538,10 +555,10 @@
} }
} }
}, },
"Microsoft.Extensions.Options.ConfigurationExtensions/9.0.5": { "Microsoft.Extensions.Options.ConfigurationExtensions/9.0.8": {
"dependencies": { "dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8", "Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Configuration.Binder": "9.0.5", "Microsoft.Extensions.Configuration.Binder": "9.0.8",
"Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8", "Microsoft.Extensions.DependencyInjection.Abstractions": "9.0.8",
"Microsoft.Extensions.Options": "9.0.8", "Microsoft.Extensions.Options": "9.0.8",
"Microsoft.Extensions.Primitives": "9.0.8" "Microsoft.Extensions.Primitives": "9.0.8"
@@ -549,7 +566,7 @@
"runtime": { "runtime": {
"lib/net9.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": { "lib/net9.0/Microsoft.Extensions.Options.ConfigurationExtensions.dll": {
"assemblyVersion": "9.0.0.0", "assemblyVersion": "9.0.0.0",
"fileVersion": "9.0.525.21509" "fileVersion": "9.0.825.36511"
} }
} }
}, },
@@ -918,7 +935,9 @@
}, },
"Elecciones.Infrastructure/1.0.0": { "Elecciones.Infrastructure/1.0.0": {
"dependencies": { "dependencies": {
"Elecciones.Core": "1.0.0" "Elecciones.Core": "1.0.0",
"Microsoft.Extensions.Configuration.Abstractions": "9.0.8",
"Microsoft.Extensions.Http": "9.0.8"
}, },
"runtime": { "runtime": {
"Elecciones.Infrastructure.dll": { "Elecciones.Infrastructure.dll": {
@@ -1026,12 +1045,12 @@
"path": "microsoft.extensions.caching.memory/9.0.8", "path": "microsoft.extensions.caching.memory/9.0.8",
"hashPath": "microsoft.extensions.caching.memory.9.0.8.nupkg.sha512" "hashPath": "microsoft.extensions.caching.memory.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Configuration/9.0.5": { "Microsoft.Extensions.Configuration/9.0.8": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-uYXLg2Gt8KUH5nT3u+TBpg9VrRcN5+2zPmIjqEHR4kOoBwsbtMDncEJw9HiLvZqGgIo2TR4oraibAoy5hXn2bQ==", "sha512": "sha512-6m+8Xgmf8UWL0p/oGqBM+0KbHE5/ePXbV1hKXgC59zEv0aa0DW5oiiyxDbK5kH5j4gIvyD5uWL0+HadKBJngvQ==",
"path": "microsoft.extensions.configuration/9.0.5", "path": "microsoft.extensions.configuration/9.0.8",
"hashPath": "microsoft.extensions.configuration.9.0.5.nupkg.sha512" "hashPath": "microsoft.extensions.configuration.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Configuration.Abstractions/9.0.8": { "Microsoft.Extensions.Configuration.Abstractions/9.0.8": {
"type": "package", "type": "package",
@@ -1040,12 +1059,12 @@
"path": "microsoft.extensions.configuration.abstractions/9.0.8", "path": "microsoft.extensions.configuration.abstractions/9.0.8",
"hashPath": "microsoft.extensions.configuration.abstractions.9.0.8.nupkg.sha512" "hashPath": "microsoft.extensions.configuration.abstractions.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Configuration.Binder/9.0.5": { "Microsoft.Extensions.Configuration.Binder/9.0.8": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-7pQ4Tkyofm8DFWFhqn9ZmG8qSAC2VitWleATj5qob9V9KtoxCVdwRtmiVl/ha3WAgjkEfW++JLWXox9MJwMgkg==", "sha512": "sha512-0vK9DnYrYChdiH3yRZWkkp4x4LbrfkWEdBc5HOsQ8t/0CLOWKXKkkhOE8A1shlex0hGydbGrhObeypxz/QTm+w==",
"path": "microsoft.extensions.configuration.binder/9.0.5", "path": "microsoft.extensions.configuration.binder/9.0.8",
"hashPath": "microsoft.extensions.configuration.binder.9.0.5.nupkg.sha512" "hashPath": "microsoft.extensions.configuration.binder.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Configuration.CommandLine/9.0.5": { "Microsoft.Extensions.Configuration.CommandLine/9.0.5": {
"type": "package", "type": "package",
@@ -1096,19 +1115,19 @@
"path": "microsoft.extensions.dependencyinjection.abstractions/9.0.8", "path": "microsoft.extensions.dependencyinjection.abstractions/9.0.8",
"hashPath": "microsoft.extensions.dependencyinjection.abstractions.9.0.8.nupkg.sha512" "hashPath": "microsoft.extensions.dependencyinjection.abstractions.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Diagnostics/9.0.5": { "Microsoft.Extensions.Diagnostics/9.0.8": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-fRiUjmhm9e4vMp6WEO9MgWNxVtWSr4Pcgh1W4DyJIr8bRANlZz9JU7uicf7ShzMspDxo/9Ejo9zJ6qQZY0IhVw==", "sha512": "sha512-BKkLCFXzJvNmdngeYBf72VXoZqTJSb1orvjdzDLaGobicoGFBPW8ug2ru1nnEewMEwJzMgnsjHQY8EaKWmVhKg==",
"path": "microsoft.extensions.diagnostics/9.0.5", "path": "microsoft.extensions.diagnostics/9.0.8",
"hashPath": "microsoft.extensions.diagnostics.9.0.5.nupkg.sha512" "hashPath": "microsoft.extensions.diagnostics.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Diagnostics.Abstractions/9.0.5": { "Microsoft.Extensions.Diagnostics.Abstractions/9.0.8": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-6YfTcULCYREMTqtk+s3UiszsFV2xN2FXtxdQpurmQJY9Cp/QGiM4MTKfJKUo7AzdLuzjOKKMWjQITmvtK7AsUg==", "sha512": "sha512-UDY7blv4DCyIJ/8CkNrQKLaAZFypXQavRZ2DWf/2zi1mxYYKKw2t8AOCBWxNntyPZHPGhtEmL3snFM98ADZqTw==",
"path": "microsoft.extensions.diagnostics.abstractions/9.0.5", "path": "microsoft.extensions.diagnostics.abstractions/9.0.8",
"hashPath": "microsoft.extensions.diagnostics.abstractions.9.0.5.nupkg.sha512" "hashPath": "microsoft.extensions.diagnostics.abstractions.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.FileProviders.Abstractions/9.0.5": { "Microsoft.Extensions.FileProviders.Abstractions/9.0.5": {
"type": "package", "type": "package",
@@ -1145,6 +1164,13 @@
"path": "microsoft.extensions.hosting.abstractions/9.0.5", "path": "microsoft.extensions.hosting.abstractions/9.0.5",
"hashPath": "microsoft.extensions.hosting.abstractions.9.0.5.nupkg.sha512" "hashPath": "microsoft.extensions.hosting.abstractions.9.0.5.nupkg.sha512"
}, },
"Microsoft.Extensions.Http/9.0.8": {
"type": "package",
"serviceable": true,
"sha512": "sha512-jDj+4aDByk47oESlDDTtk6LWzlXlmoCsjCn6ihd+i9OntN885aPLszUII5+w0B/7wYSZcS3KdjqLAIhKLSiBXQ==",
"path": "microsoft.extensions.http/9.0.8",
"hashPath": "microsoft.extensions.http.9.0.8.nupkg.sha512"
},
"Microsoft.Extensions.Logging/9.0.8": { "Microsoft.Extensions.Logging/9.0.8": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
@@ -1201,12 +1227,12 @@
"path": "microsoft.extensions.options/9.0.8", "path": "microsoft.extensions.options/9.0.8",
"hashPath": "microsoft.extensions.options.9.0.8.nupkg.sha512" "hashPath": "microsoft.extensions.options.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Options.ConfigurationExtensions/9.0.5": { "Microsoft.Extensions.Options.ConfigurationExtensions/9.0.8": {
"type": "package", "type": "package",
"serviceable": true, "serviceable": true,
"sha512": "sha512-CJbAVdovKPFh2FoKxesu20odRVSbL/vtvzzObnG+5u38sOfzRS2Ncy25id0TjYUGQzMhNnJUHgTUzTMDl/3c9g==", "sha512": "sha512-eW2s6n06x0w6w4nsX+SvpgsFYkl+Y0CttYAt6DKUXeqprX+hzNqjSfOh637fwNJBg7wRBrOIRHe49gKiTgJxzQ==",
"path": "microsoft.extensions.options.configurationextensions/9.0.5", "path": "microsoft.extensions.options.configurationextensions/9.0.8",
"hashPath": "microsoft.extensions.options.configurationextensions.9.0.5.nupkg.sha512" "hashPath": "microsoft.extensions.options.configurationextensions.9.0.8.nupkg.sha512"
}, },
"Microsoft.Extensions.Primitives/9.0.8": { "Microsoft.Extensions.Primitives/9.0.8": {
"type": "package", "type": "package",

View File

@@ -4,5 +4,13 @@
"Default": "Information", "Default": "Information",
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
},
"ElectoralApi": {
"BaseUrl": "https://api.eleccionesbonaerenses.gba.gob.ar",
"Username": "30500094156@elecciones2025.onmicrosoft.com",
"Password": "PTP847elec"
},
"ConnectionStrings": {
"DefaultConnection": "Server=TECNICA3;Database=Elecciones2025;User Id=apielecciones2025;Password=PTP847Elecciones2025;Encrypt=False;MultipleActiveResultSets=True;TrustServerCertificate=True;"
} }
} }

View File

@@ -4,5 +4,10 @@
"Default": "Information", "Default": "Information",
"Microsoft.Hosting.Lifetime": "Information" "Microsoft.Hosting.Lifetime": "Information"
} }
},
"ElectoralApi": {
"BaseUrl": "https://api.eleccionesbonaerenses.gba.gob.ar",
"Username": "30500094156@elecciones2025.onmicrosoft.com",
"Password": "PTP847elec"
} }
} }

View File

@@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Worker")] [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Worker")]
[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+d9bcfd70865a12c229e6a761639094b45de862bd")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+b90baadeedb870b5b1c9eeeb7022a0d211b61bec")]
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Worker")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Worker")]
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Worker")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Worker")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@@ -95,3 +95,4 @@ E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Debug\net9.0\refint\
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Debug\net9.0\Elecciones.Worker.pdb E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Debug\net9.0\Elecciones.Worker.pdb
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Debug\net9.0\Elecciones.Worker.genruntimeconfig.cache E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Debug\net9.0\Elecciones.Worker.genruntimeconfig.cache
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Debug\net9.0\ref\Elecciones.Worker.dll E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\obj\Debug\net9.0\ref\Elecciones.Worker.dll
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Worker\bin\Debug\net9.0\Microsoft.Extensions.Http.dll

View File

@@ -195,6 +195,16 @@
"frameworks": { "frameworks": {
"net9.0": { "net9.0": {
"targetAlias": "net9.0", "targetAlias": "net9.0",
"dependencies": {
"Microsoft.Extensions.Configuration.Abstractions": {
"target": "Package",
"version": "[9.0.8, )"
},
"Microsoft.Extensions.Http": {
"target": "Package",
"version": "[9.0.8, )"
}
},
"imports": [ "imports": [
"net461", "net461",
"net462", "net462",
@@ -275,6 +285,10 @@
"Microsoft.Extensions.Hosting": { "Microsoft.Extensions.Hosting": {
"target": "Package", "target": "Package",
"version": "[9.0.5, )" "version": "[9.0.5, )"
},
"Microsoft.Extensions.Http": {
"target": "Package",
"version": "[9.0.8, )"
} }
}, },
"imports": [ "imports": [

View File

@@ -3,7 +3,7 @@
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' "> <ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<Import Project="$(NuGetPackageRoot)system.text.json\9.0.8\buildTransitive\net8.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\9.0.8\buildTransitive\net8.0\System.Text.Json.targets')" /> <Import Project="$(NuGetPackageRoot)system.text.json\9.0.8\buildTransitive\net8.0\System.Text.Json.targets" Condition="Exists('$(NuGetPackageRoot)system.text.json\9.0.8\buildTransitive\net8.0\System.Text.Json.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Options.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.5\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.5\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.8\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\9.0.8\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\9.0.8\buildTransitive\net8.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\9.0.5\buildTransitive\net8.0\Microsoft.Extensions.Configuration.UserSecrets.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\9.0.5\buildTransitive\net8.0\Microsoft.Extensions.Configuration.UserSecrets.targets')" /> <Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\9.0.5\buildTransitive\net8.0\Microsoft.Extensions.Configuration.UserSecrets.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.usersecrets\9.0.5\buildTransitive\net8.0\Microsoft.Extensions.Configuration.UserSecrets.targets')" />
</ImportGroup> </ImportGroup>