Trabajo de ajuste en widgets y db para frontend
This commit is contained in:
24
Elecciones-Web/frontend-admin/.gitignore
vendored
Normal file
24
Elecciones-Web/frontend-admin/.gitignore
vendored
Normal 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?
|
||||||
69
Elecciones-Web/frontend-admin/README.md
Normal file
69
Elecciones-Web/frontend-admin/README.md
Normal 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...
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
```
|
||||||
23
Elecciones-Web/frontend-admin/eslint.config.js
Normal file
23
Elecciones-Web/frontend-admin/eslint.config.js
Normal 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,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
])
|
||||||
13
Elecciones-Web/frontend-admin/index.html
Normal file
13
Elecciones-Web/frontend-admin/index.html
Normal 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>
|
||||||
3749
Elecciones-Web/frontend-admin/package-lock.json
generated
Normal file
3749
Elecciones-Web/frontend-admin/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
33
Elecciones-Web/frontend-admin/package.json
Normal file
33
Elecciones-Web/frontend-admin/package.json
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
{
|
||||||
|
"name": "frontend-admin",
|
||||||
|
"private": true,
|
||||||
|
"version": "0.0.0",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"dev": "vite",
|
||||||
|
"build": "tsc -b && vite build",
|
||||||
|
"lint": "eslint .",
|
||||||
|
"preview": "vite preview"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@dnd-kit/core": "^6.3.1",
|
||||||
|
"@dnd-kit/sortable": "^10.0.0",
|
||||||
|
"@tanstack/react-query": "^5.85.5",
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
1
Elecciones-Web/frontend-admin/public/vite.svg
Normal file
1
Elecciones-Web/frontend-admin/public/vite.svg
Normal 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 |
42
Elecciones-Web/frontend-admin/src/App.css
Normal file
42
Elecciones-Web/frontend-admin/src/App.css
Normal 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;
|
||||||
|
}
|
||||||
17
Elecciones-Web/frontend-admin/src/App.tsx
Normal file
17
Elecciones-Web/frontend-admin/src/App.tsx
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
// src/App.tsx
|
||||||
|
import { useAuth } from './context/AuthContext';
|
||||||
|
import { LoginPage } from './components/LoginPage';
|
||||||
|
import { DashboardPage } from './components/DashboardPage';
|
||||||
|
import './App.css'; // Puede añadir estilos globales aquí
|
||||||
|
|
||||||
|
function App() {
|
||||||
|
const { isAuthenticated } = useAuth();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="App">
|
||||||
|
{isAuthenticated ? <DashboardPage /> : <LoginPage />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default App;
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/* src/components/AgrupacionesManager.css */
|
||||||
|
.admin-module {
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 8px;
|
||||||
|
margin-top: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
th, td {
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
padding: 8px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr:nth-child(even) {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
}
|
||||||
|
|
||||||
|
td input[type="text"] {
|
||||||
|
width: 100%;
|
||||||
|
padding: 4px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
td button {
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable-list-horizontal {
|
||||||
|
list-style: none;
|
||||||
|
padding: 8px;
|
||||||
|
margin: 0;
|
||||||
|
border: 1px dashed #ccc;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: flex; /* <-- La clave para la alineación horizontal */
|
||||||
|
flex-wrap: wrap; /* <-- La clave para que salte de línea */
|
||||||
|
gap: 8px; /* Espacio entre elementos */
|
||||||
|
min-height: 50px; /* Un poco de altura para que la zona de drop sea visible */
|
||||||
|
}
|
||||||
|
|
||||||
|
.sortable-item {
|
||||||
|
padding: 8px 12px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: grab;
|
||||||
|
/* Opcional: para que no se puedan seleccionar el texto mientras se arrastra */
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chamber-tabs {
|
||||||
|
display: flex;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 6px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.chamber-tabs button {
|
||||||
|
flex: 1;
|
||||||
|
padding: 0.75rem 0.5rem;
|
||||||
|
border: none;
|
||||||
|
background-color: #f8f9fa;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s;
|
||||||
|
}
|
||||||
|
.chamber-tabs button:first-child { border-right: 1px solid #ccc; }
|
||||||
|
.chamber-tabs button.active { background-color: #007bff; color: white; }
|
||||||
@@ -0,0 +1,113 @@
|
|||||||
|
// src/components/AgrupacionesManager.tsx
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { getAgrupaciones, updateAgrupacion } from '../services/apiService';
|
||||||
|
import type { AgrupacionPolitica, UpdateAgrupacionData } from '../types';
|
||||||
|
import './AgrupacionesManager.css';
|
||||||
|
|
||||||
|
export const AgrupacionesManager = () => {
|
||||||
|
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [editingId, setEditingId] = useState<string | null>(null);
|
||||||
|
const [formData, setFormData] = useState<UpdateAgrupacionData>({
|
||||||
|
nombreCorto: '',
|
||||||
|
color: '#000000',
|
||||||
|
logoUrl: '',
|
||||||
|
});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
fetchAgrupaciones();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const fetchAgrupaciones = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
const data = await getAgrupaciones();
|
||||||
|
setAgrupaciones(data);
|
||||||
|
} catch (err) {
|
||||||
|
setError('No se pudieron cargar las agrupaciones.');
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleEdit = (agrupacion: AgrupacionPolitica) => {
|
||||||
|
setEditingId(agrupacion.id);
|
||||||
|
setFormData({
|
||||||
|
nombreCorto: agrupacion.nombreCorto || '',
|
||||||
|
color: agrupacion.color || '#000000',
|
||||||
|
logoUrl: agrupacion.logoUrl || '',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
setEditingId(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSave = async (id: string) => {
|
||||||
|
try {
|
||||||
|
await updateAgrupacion(id, formData);
|
||||||
|
setEditingId(null);
|
||||||
|
fetchAgrupaciones(); // Recargar datos para ver los cambios
|
||||||
|
} catch (err) {
|
||||||
|
alert('Error al guardar los cambios.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setFormData({ ...formData, [e.target.name]: e.target.value });
|
||||||
|
};
|
||||||
|
|
||||||
|
if (loading) return <p>Cargando agrupaciones...</p>;
|
||||||
|
if (error) return <p style={{ color: 'red' }}>{error}</p>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="admin-module">
|
||||||
|
<h3>Gestión de Agrupaciones Políticas</h3>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Nombre</th>
|
||||||
|
<th>Nombre Corto</th>
|
||||||
|
<th>Color</th>
|
||||||
|
<th>Logo URL</th>
|
||||||
|
<th>Acciones</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{agrupaciones.map((agrupacion) => (
|
||||||
|
<tr key={agrupacion.id}>
|
||||||
|
{editingId === agrupacion.id ? (
|
||||||
|
<>
|
||||||
|
<td>{agrupacion.nombre}</td>
|
||||||
|
<td><input type="text" name="nombreCorto" value={formData.nombreCorto || ''} onChange={handleChange} /></td>
|
||||||
|
<td><input type="color" name="color" value={formData.color || '#000000'} onChange={handleChange} /></td>
|
||||||
|
<td><input type="text" name="logoUrl" value={formData.logoUrl || ''} onChange={handleChange} /></td>
|
||||||
|
<td>
|
||||||
|
<button onClick={() => handleSave(agrupacion.id)}>Guardar</button>
|
||||||
|
<button onClick={handleCancel}>Cancelar</button>
|
||||||
|
</td>
|
||||||
|
</>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<td>{agrupacion.nombre}</td>
|
||||||
|
<td>{agrupacion.nombreCorto}</td>
|
||||||
|
<td>
|
||||||
|
<div style={{ display: 'flex', alignItems: 'center', gap: '8px' }}>
|
||||||
|
<div style={{ width: '20px', height: '20px', backgroundColor: agrupacion.color || 'transparent', border: '1px solid #ccc' }}></div>
|
||||||
|
{agrupacion.color}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>{agrupacion.logoUrl}</td>
|
||||||
|
<td>
|
||||||
|
<button onClick={() => handleEdit(agrupacion)}>Editar</button>
|
||||||
|
</td>
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
121
Elecciones-Web/frontend-admin/src/components/BancasManager.tsx
Normal file
121
Elecciones-Web/frontend-admin/src/components/BancasManager.tsx
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
// src/components/BancasManager.tsx
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
|
import { getBancadas, getAgrupaciones, updateBancada, type UpdateBancadaData } from '../services/apiService';
|
||||||
|
import type { Bancada, AgrupacionPolitica } from '../types';
|
||||||
|
import { OcupantesModal } from './OcupantesModal';
|
||||||
|
import './AgrupacionesManager.css'; // Asegúrate de que este CSS tenga los estilos de .chamber-tabs
|
||||||
|
|
||||||
|
const camaras = ['diputados', 'senadores'] as const;
|
||||||
|
|
||||||
|
export const BancasManager = () => {
|
||||||
|
const [activeTab, setActiveTab] = useState<'diputados' | 'senadores'>('diputados');
|
||||||
|
const [modalVisible, setModalVisible] = useState(false);
|
||||||
|
const [bancadaSeleccionada, setBancadaSeleccionada] = useState<Bancada | null>(null);
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
|
// Obtenemos todas las agrupaciones para poblar el <select>
|
||||||
|
const { data: agrupaciones = [] } = useQuery<AgrupacionPolitica[]>({
|
||||||
|
queryKey: ['agrupaciones'],
|
||||||
|
queryFn: getAgrupaciones
|
||||||
|
});
|
||||||
|
|
||||||
|
// Obtenemos las bancas para la cámara activa (diputados o senadores)
|
||||||
|
const { data: bancadas = [], isLoading, error } = useQuery<Bancada[]>({
|
||||||
|
queryKey: ['bancadas', activeTab],
|
||||||
|
queryFn: () => getBancadas(activeTab),
|
||||||
|
});
|
||||||
|
|
||||||
|
const handleAgrupacionChange = async (bancadaId: number, nuevaAgrupacionId: string | null) => {
|
||||||
|
const bancadaActual = bancadas.find(b => b.id === bancadaId);
|
||||||
|
if (!bancadaActual) return;
|
||||||
|
|
||||||
|
// Si se desasigna el partido (vacante), también se limpia el ocupante
|
||||||
|
const payload: UpdateBancadaData = {
|
||||||
|
agrupacionPoliticaId: nuevaAgrupacionId,
|
||||||
|
nombreOcupante: nuevaAgrupacionId ? (bancadaActual.ocupante?.nombreOcupante ?? null) : null,
|
||||||
|
fotoUrl: nuevaAgrupacionId ? (bancadaActual.ocupante?.fotoUrl ?? null) : null,
|
||||||
|
periodo: nuevaAgrupacionId ? (bancadaActual.ocupante?.periodo ?? null) : null,
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
await updateBancada(bancadaId, payload);
|
||||||
|
// Invalida la query para forzar una recarga de datos frescos desde el servidor
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['bancadas', activeTab] });
|
||||||
|
} catch (err) {
|
||||||
|
alert("Error al guardar el cambio.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleOpenModal = (bancada: Bancada) => {
|
||||||
|
setBancadaSeleccionada(bancada);
|
||||||
|
setModalVisible(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (error) return <p style={{ color: 'red' }}>Error al cargar las bancas.</p>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="admin-module">
|
||||||
|
<h2>Gestión de Ocupación de Bancas</h2>
|
||||||
|
<p>Asigne a cada banca un partido político y, opcionalmente, los datos de la persona que la ocupa.</p>
|
||||||
|
|
||||||
|
<div className="chamber-tabs">
|
||||||
|
{camaras.map(camara => (
|
||||||
|
<button
|
||||||
|
key={camara}
|
||||||
|
className={activeTab === camara ? 'active' : ''}
|
||||||
|
onClick={() => setActiveTab(camara)}
|
||||||
|
>
|
||||||
|
{camara === 'diputados' ? 'Cámara de Diputados' : 'Cámara de Senadores'}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{isLoading ? <p>Cargando bancas...</p> : (
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Banca #</th>
|
||||||
|
<th>Partido Asignado</th>
|
||||||
|
<th>Ocupante Actual</th>
|
||||||
|
<th>Acciones</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{bancadas.map((bancada, index) => (
|
||||||
|
<tr key={bancada.id}>
|
||||||
|
<td>{`${activeTab.charAt(0).toUpperCase()}-${index + 1}`}</td>
|
||||||
|
<td>
|
||||||
|
<select
|
||||||
|
value={bancada.agrupacionPoliticaId || ''}
|
||||||
|
onChange={(e) => handleAgrupacionChange(bancada.id, e.target.value || null)}
|
||||||
|
>
|
||||||
|
<option value="">-- Vacante --</option>
|
||||||
|
{agrupaciones.map(a => <option key={a.id} value={a.id}>{a.nombre}</option>)}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>{bancada.ocupante?.nombreOcupante || 'Sin asignar'}</td>
|
||||||
|
<td>
|
||||||
|
<button
|
||||||
|
disabled={!bancada.agrupacionPoliticaId}
|
||||||
|
onClick={() => handleOpenModal(bancada)}
|
||||||
|
>
|
||||||
|
Editar Ocupante
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
))}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{modalVisible && bancadaSeleccionada && (
|
||||||
|
<OcupantesModal
|
||||||
|
bancada={bancadaSeleccionada}
|
||||||
|
onClose={() => setModalVisible(false)}
|
||||||
|
activeTab={activeTab}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,110 @@
|
|||||||
|
// src/components/ConfiguracionGeneral.tsx
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { getAgrupaciones, getConfiguracion, updateConfiguracion } from '../services/apiService';
|
||||||
|
import type { AgrupacionPolitica } from '../types';
|
||||||
|
import './AgrupacionesManager.css'; // Reutilizamos los estilos para mantener la consistencia
|
||||||
|
|
||||||
|
export const ConfiguracionGeneral = () => {
|
||||||
|
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
// Estado específico para la configuración de la presidencia del Senado
|
||||||
|
const [presidenciaSenadoId, setPresidenciaSenadoId] = useState<string>('');
|
||||||
|
const [usarDatosOficiales, setUsarDatosOficiales] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const loadInitialData = async () => {
|
||||||
|
try {
|
||||||
|
setLoading(true);
|
||||||
|
setError(null);
|
||||||
|
|
||||||
|
// Hacemos ambas llamadas a la API en paralelo para más eficiencia
|
||||||
|
const [agrupacionesData, configData] = await Promise.all([
|
||||||
|
getAgrupaciones(),
|
||||||
|
getConfiguracion()
|
||||||
|
]);
|
||||||
|
|
||||||
|
setAgrupaciones(agrupacionesData);
|
||||||
|
|
||||||
|
// Asignamos el valor guardado, si existe
|
||||||
|
if (configData && configData.PresidenciaSenadores) {
|
||||||
|
setPresidenciaSenadoId(configData.PresidenciaSenadores);
|
||||||
|
}
|
||||||
|
setUsarDatosOficiales(configData.UsarDatosDeBancadasOficiales === 'true');
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error al cargar datos de configuración:", err);
|
||||||
|
setError("No se pudieron cargar los datos necesarios para la configuración.");
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
loadInitialData();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleSave = async () => {
|
||||||
|
try {
|
||||||
|
await updateConfiguracion({ "PresidenciaSenadores": presidenciaSenadoId, "UsarDatosDeBancadasOficiales": usarDatosOficiales.toString() });
|
||||||
|
alert('Configuración guardada con éxito.');
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Error al guardar la configuración:", err);
|
||||||
|
alert('Error al guardar la configuración.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (loading) return <div className="admin-module"><p>Cargando configuración...</p></div>;
|
||||||
|
if (error) return <div className="admin-module"><p style={{ color: 'red' }}>{error}</p></div>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="admin-module">
|
||||||
|
<h3>Configuración General de Cámaras</h3>
|
||||||
|
<div className="form-group">
|
||||||
|
<label>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={usarDatosOficiales}
|
||||||
|
onChange={e => setUsarDatosOficiales(e.target.checked)}
|
||||||
|
/>
|
||||||
|
Activar Modo "Resultados Oficiales"
|
||||||
|
</label>
|
||||||
|
<p style={{ fontSize: '0.8rem', color: '#666', margin: '0.5rem 0 0 0' }}>
|
||||||
|
Si está activo, el widget del Congreso mostrará la composición gestionada manualmente en esta página. Si está inactivo, mostrará la proyección en tiempo real de las elecciones.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div style={{ marginTop: '1rem', paddingBottom: '1rem', borderBottom: '1px solid #eee' }}>
|
||||||
|
<label
|
||||||
|
htmlFor="presidencia-senado"
|
||||||
|
style={{ display: 'block', fontWeight: 'bold', marginBottom: '0.5rem' }}
|
||||||
|
>
|
||||||
|
Presidencia Cámara de Senadores (Vicegobernador)
|
||||||
|
</label>
|
||||||
|
<select
|
||||||
|
id="presidencia-senado"
|
||||||
|
value={presidenciaSenadoId}
|
||||||
|
onChange={e => setPresidenciaSenadoId(e.target.value)}
|
||||||
|
style={{ width: '100%', padding: '8px' }}
|
||||||
|
>
|
||||||
|
<option value="">-- No Asignado --</option>
|
||||||
|
{agrupaciones.map(a => (
|
||||||
|
<option key={a.id} value={a.id}>
|
||||||
|
{a.nombre}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
<p style={{ fontSize: '0.8rem', color: '#666', margin: '0.5rem 0 0 0' }}>
|
||||||
|
Seleccione el partido político al que pertenece el Vicegobernador. El asiento presidencial del Senado se pintará con el color de este partido.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div style={{ marginTop: '1rem' }}>
|
||||||
|
<p style={{ fontWeight: 'bold', margin: 0 }}>
|
||||||
|
Presidencia Cámara de Diputados
|
||||||
|
</p>
|
||||||
|
<p style={{ fontSize: '0.8rem', color: '#666', margin: '0.5rem 0 0 0' }}>
|
||||||
|
Esta banca se asigna y colorea automáticamente según la agrupación política con la mayoría de bancas totales en la cámara.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<button onClick={handleSave} style={{ marginTop: '1.5rem' }}>
|
||||||
|
Guardar Configuración
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
// src/components/DashboardPage.tsx
|
||||||
|
import { useAuth } from '../context/AuthContext';
|
||||||
|
import { AgrupacionesManager } from './AgrupacionesManager';
|
||||||
|
import { OrdenDiputadosManager } from './OrdenDiputadosManager';
|
||||||
|
import { OrdenSenadoresManager } from './OrdenSenadoresManager';
|
||||||
|
import { ConfiguracionGeneral } from './ConfiguracionGeneral';
|
||||||
|
import { BancasManager } from './BancasManager';
|
||||||
|
|
||||||
|
export const DashboardPage = () => {
|
||||||
|
const { logout } = useAuth();
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ padding: '1rem 2rem' }}>
|
||||||
|
<header style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', borderBottom: '2px solid #eee', paddingBottom: '1rem' }}>
|
||||||
|
<h1>Panel de Administración Electoral</h1>
|
||||||
|
<button onClick={logout}>Cerrar Sesión</button>
|
||||||
|
</header>
|
||||||
|
<main style={{ marginTop: '2rem' }}>
|
||||||
|
<ConfiguracionGeneral />
|
||||||
|
<AgrupacionesManager />
|
||||||
|
|
||||||
|
<div style={{ display: 'flex', gap: '2rem', flexWrap: 'wrap', marginTop: '2rem' }}>
|
||||||
|
<div style={{ flex: '1 1 400px' }}>
|
||||||
|
<OrdenDiputadosManager />
|
||||||
|
</div>
|
||||||
|
<div style={{ flex: '1 1 400px' }}>
|
||||||
|
<OrdenSenadoresManager />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<BancasManager />
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
49
Elecciones-Web/frontend-admin/src/components/LoginPage.tsx
Normal file
49
Elecciones-Web/frontend-admin/src/components/LoginPage.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// src/components/LoginPage.tsx
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useAuth } from '../context/AuthContext';
|
||||||
|
|
||||||
|
export const LoginPage = () => {
|
||||||
|
const [username, setUsername] = useState('');
|
||||||
|
const [password, setPassword] = useState('');
|
||||||
|
const [error, setError] = useState('');
|
||||||
|
const { login } = useAuth();
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setError('');
|
||||||
|
const success = await login({ username, password });
|
||||||
|
if (!success) {
|
||||||
|
setError('Usuario o contraseña incorrectos.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div style={{ /* Estilos simples para centrar */ }}>
|
||||||
|
<h2>Panel de Administración</h2>
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="username">Usuario:</label>
|
||||||
|
<input
|
||||||
|
id="username"
|
||||||
|
type="text"
|
||||||
|
value={username}
|
||||||
|
onChange={(e) => setUsername(e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<label htmlFor="password">Contraseña:</label>
|
||||||
|
<input
|
||||||
|
id="password"
|
||||||
|
type="password"
|
||||||
|
value={password}
|
||||||
|
onChange={(e) => setPassword(e.target.value)}
|
||||||
|
required
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{error && <p style={{ color: 'red' }}>{error}</p>}
|
||||||
|
<button type="submit">Ingresar</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
.modal-overlay {
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
.modal-content {
|
||||||
|
background: white;
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
width: 90%;
|
||||||
|
max-width: 500px;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.modal-close {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
right: 15px;
|
||||||
|
border: none;
|
||||||
|
background: none;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.modal-content h4 { margin-top: 0; }
|
||||||
|
.modal-content h5 { margin-top: 0; color: #666; }
|
||||||
|
.form-group {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
}
|
||||||
|
.form-group label {
|
||||||
|
display: block;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
.form-group input {
|
||||||
|
width: 100%;
|
||||||
|
padding: 8px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
.modal-actions {
|
||||||
|
text-align: right;
|
||||||
|
margin-top: 1.5rem;
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
// src/components/OcupantesModal.tsx
|
||||||
|
import { useState } from 'react';
|
||||||
|
import { useQueryClient } from '@tanstack/react-query';
|
||||||
|
import { updateBancada, type UpdateBancadaData } from '../services/apiService';
|
||||||
|
import type { Bancada } from '../types';
|
||||||
|
import './OcupantesModal.css'; // Crearemos este archivo
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
bancada: Bancada;
|
||||||
|
onClose: () => void;
|
||||||
|
activeTab: 'diputados' | 'senadores';
|
||||||
|
}
|
||||||
|
|
||||||
|
export const OcupantesModal = ({ bancada, onClose, activeTab }: Props) => {
|
||||||
|
const queryClient = useQueryClient();
|
||||||
|
const [nombre, setNombre] = useState(bancada.ocupante?.nombreOcupante || '');
|
||||||
|
const [fotoUrl, setFotoUrl] = useState(bancada.ocupante?.fotoUrl || '');
|
||||||
|
const [periodo, setPeriodo] = useState(bancada.ocupante?.periodo || '');
|
||||||
|
|
||||||
|
const handleSubmit = async (e: React.FormEvent) => {
|
||||||
|
e.preventDefault();
|
||||||
|
const payload: UpdateBancadaData = {
|
||||||
|
agrupacionPoliticaId: bancada.agrupacionPoliticaId,
|
||||||
|
nombreOcupante: nombre || null,
|
||||||
|
fotoUrl: fotoUrl || null,
|
||||||
|
periodo: periodo || null,
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
await updateBancada(bancada.id, payload);
|
||||||
|
// Invalida la query para que la tabla principal se actualice
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['bancadas', activeTab] });
|
||||||
|
onClose();
|
||||||
|
} catch (err) {
|
||||||
|
alert("Error al guardar el ocupante.");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="modal-overlay" onClick={onClose}>
|
||||||
|
<div className="modal-content" onClick={e => e.stopPropagation()}>
|
||||||
|
<button className="modal-close" onClick={onClose}>×</button>
|
||||||
|
<h4>Ocupante de la Banca #{bancada.id}</h4>
|
||||||
|
<h5>{bancada.agrupacionPolitica?.nombre || 'Banca Vacante'}</h5>
|
||||||
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="nombre">Nombre Completo</label>
|
||||||
|
<input id="nombre" type="text" value={nombre} onChange={e => setNombre(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="fotoUrl">URL de la Foto</label>
|
||||||
|
<input id="fotoUrl" type="text" value={fotoUrl} onChange={e => setFotoUrl(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="form-group">
|
||||||
|
<label htmlFor="periodo">Período (ej. 2023-2027)</label>
|
||||||
|
<input id="periodo" type="text" value={periodo} onChange={e => setPeriodo(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="modal-actions">
|
||||||
|
<button type="submit">Guardar Cambios</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
// src/components/OrdenDiputadosManager.tsx
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import {
|
||||||
|
DndContext,
|
||||||
|
closestCenter,
|
||||||
|
KeyboardSensor,
|
||||||
|
PointerSensor,
|
||||||
|
useSensor,
|
||||||
|
useSensors,
|
||||||
|
type DragEndEvent,
|
||||||
|
} from '@dnd-kit/core';
|
||||||
|
import {
|
||||||
|
arrayMove,
|
||||||
|
SortableContext,
|
||||||
|
sortableKeyboardCoordinates,
|
||||||
|
horizontalListSortingStrategy,
|
||||||
|
} from '@dnd-kit/sortable';
|
||||||
|
|
||||||
|
import { getAgrupaciones } from '../services/apiService';
|
||||||
|
import type { AgrupacionPolitica } from '../types';
|
||||||
|
import { SortableItem } from './SortableItem';
|
||||||
|
import './AgrupacionesManager.css'; // Reutilizamos los estilos
|
||||||
|
|
||||||
|
// Función para llamar al endpoint específico de diputados
|
||||||
|
const updateOrdenDiputadosApi = async (ids: string[]) => {
|
||||||
|
const token = localStorage.getItem('admin-jwt-token');
|
||||||
|
const response = await fetch('http://localhost:5217/api/admin/agrupaciones/orden-diputados', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${token}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify(ids)
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to save Diputados order");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const OrdenDiputadosManager = () => {
|
||||||
|
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const sensors = useSensors(
|
||||||
|
useSensor(PointerSensor),
|
||||||
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchAndSortAgrupaciones = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const data = await getAgrupaciones();
|
||||||
|
// Ordenar por el orden de Diputados. Los nulos van al final.
|
||||||
|
data.sort((a, b) => (a.ordenDiputados || 999) - (b.ordenDiputados || 999));
|
||||||
|
setAgrupaciones(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch agrupaciones for Diputados:", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchAndSortAgrupaciones();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDragEnd = (event: DragEndEvent) => {
|
||||||
|
const { active, over } = event;
|
||||||
|
if (over && active.id !== over.id) {
|
||||||
|
setAgrupaciones((items) => {
|
||||||
|
const oldIndex = items.findIndex((item) => item.id === active.id);
|
||||||
|
const newIndex = items.findIndex((item) => item.id === over.id);
|
||||||
|
return arrayMove(items, oldIndex, newIndex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveOrder = async () => {
|
||||||
|
const idsOrdenados = agrupaciones.map(a => a.id);
|
||||||
|
try {
|
||||||
|
await updateOrdenDiputadosApi(idsOrdenados);
|
||||||
|
alert('Orden de Diputados guardado con éxito!');
|
||||||
|
} catch (error) {
|
||||||
|
alert('Error al guardar el orden de Diputados.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (loading) return <p>Cargando orden de Diputados...</p>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="admin-module">
|
||||||
|
<h3>Ordenar Agrupaciones (Diputados)</h3>
|
||||||
|
<p>Arrastre para reordenar.</p>
|
||||||
|
<p>Ancla izquierda. Prioridad de izquierda a derecha y de arriba abajo.</p>
|
||||||
|
<DndContext
|
||||||
|
sensors={sensors}
|
||||||
|
collisionDetection={closestCenter}
|
||||||
|
onDragEnd={handleDragEnd}
|
||||||
|
>
|
||||||
|
<SortableContext
|
||||||
|
items={agrupaciones.map(a => a.id)}
|
||||||
|
strategy={horizontalListSortingStrategy}
|
||||||
|
>
|
||||||
|
<ul className="sortable-list-horizontal">
|
||||||
|
{agrupaciones.map(agrupacion => (
|
||||||
|
<SortableItem key={agrupacion.id} id={agrupacion.id}>
|
||||||
|
{agrupacion.nombreCorto || agrupacion.nombre}
|
||||||
|
</SortableItem>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</SortableContext>
|
||||||
|
</DndContext>
|
||||||
|
<button onClick={handleSaveOrder} style={{ marginTop: '1rem' }}>Guardar Orden Diputados</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
// src/components/OrdenSenadoresManager.tsx
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import {
|
||||||
|
DndContext,
|
||||||
|
closestCenter,
|
||||||
|
KeyboardSensor,
|
||||||
|
PointerSensor,
|
||||||
|
useSensor,
|
||||||
|
useSensors,
|
||||||
|
type DragEndEvent,
|
||||||
|
} from '@dnd-kit/core';
|
||||||
|
import {
|
||||||
|
arrayMove,
|
||||||
|
SortableContext,
|
||||||
|
sortableKeyboardCoordinates,
|
||||||
|
horizontalListSortingStrategy,
|
||||||
|
} from '@dnd-kit/sortable';
|
||||||
|
|
||||||
|
import { getAgrupaciones } from '../services/apiService';
|
||||||
|
import type { AgrupacionPolitica } from '../types';
|
||||||
|
import { SortableItem } from './SortableItem';
|
||||||
|
import './AgrupacionesManager.css'; // Reutilizamos los estilos
|
||||||
|
|
||||||
|
// Función para llamar al endpoint específico de senadores
|
||||||
|
const updateOrdenSenadoresApi = async (ids: string[]) => {
|
||||||
|
const token = localStorage.getItem('admin-jwt-token');
|
||||||
|
const response = await fetch('http://localhost:5217/api/admin/agrupaciones/orden-senadores', {
|
||||||
|
method: 'PUT',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': `Bearer ${token}`
|
||||||
|
},
|
||||||
|
body: JSON.stringify(ids)
|
||||||
|
});
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error("Failed to save Senadores order");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const OrdenSenadoresManager = () => {
|
||||||
|
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
||||||
|
const [loading, setLoading] = useState(true);
|
||||||
|
const sensors = useSensors(
|
||||||
|
useSensor(PointerSensor),
|
||||||
|
useSensor(KeyboardSensor, { coordinateGetter: sortableKeyboardCoordinates })
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
const fetchAndSortAgrupaciones = async () => {
|
||||||
|
setLoading(true);
|
||||||
|
try {
|
||||||
|
const data = await getAgrupaciones();
|
||||||
|
// Ordenar por el orden de Senadores. Los nulos van al final.
|
||||||
|
data.sort((a, b) => (a.ordenSenadores || 999) - (b.ordenSenadores || 999));
|
||||||
|
setAgrupaciones(data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to fetch agrupaciones for Senadores:", error);
|
||||||
|
} finally {
|
||||||
|
setLoading(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fetchAndSortAgrupaciones();
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleDragEnd = (event: DragEndEvent) => {
|
||||||
|
const { active, over } = event;
|
||||||
|
if (over && active.id !== over.id) {
|
||||||
|
setAgrupaciones((items) => {
|
||||||
|
const oldIndex = items.findIndex((item) => item.id === active.id);
|
||||||
|
const newIndex = items.findIndex((item) => item.id === over.id);
|
||||||
|
return arrayMove(items, oldIndex, newIndex);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleSaveOrder = async () => {
|
||||||
|
const idsOrdenados = agrupaciones.map(a => a.id);
|
||||||
|
try {
|
||||||
|
await updateOrdenSenadoresApi(idsOrdenados);
|
||||||
|
alert('Orden de Senadores guardado con éxito!');
|
||||||
|
} catch (error) {
|
||||||
|
alert('Error al guardar el orden de Senadores.');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (loading) return <p>Cargando orden de Senadores...</p>;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="admin-module">
|
||||||
|
<h3>Ordenar Agrupaciones (Senado)</h3>
|
||||||
|
<p>Arrastre para reordenar.</p>
|
||||||
|
<p>Ancla izquierda. Prioridad de izquierda a derecha y de arriba abajo.</p>
|
||||||
|
<DndContext
|
||||||
|
sensors={sensors}
|
||||||
|
collisionDetection={closestCenter}
|
||||||
|
onDragEnd={handleDragEnd}
|
||||||
|
>
|
||||||
|
<SortableContext
|
||||||
|
items={agrupaciones.map(a => a.id)}
|
||||||
|
strategy={horizontalListSortingStrategy}
|
||||||
|
>
|
||||||
|
<ul className="sortable-list-horizontal">
|
||||||
|
{agrupaciones.map(agrupacion => (
|
||||||
|
<SortableItem key={agrupacion.id} id={agrupacion.id}>
|
||||||
|
{agrupacion.nombreCorto || agrupacion.nombre}
|
||||||
|
</SortableItem>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</SortableContext>
|
||||||
|
</DndContext>
|
||||||
|
<button onClick={handleSaveOrder} style={{ marginTop: '1rem' }}>Guardar Orden Senado</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
// src/components/SortableItem.tsx
|
||||||
|
import { useSortable } from '@dnd-kit/sortable';
|
||||||
|
import { CSS } from '@dnd-kit/utilities';
|
||||||
|
|
||||||
|
export function SortableItem(props: { id: string, children: React.ReactNode }) {
|
||||||
|
const {
|
||||||
|
attributes,
|
||||||
|
listeners,
|
||||||
|
setNodeRef,
|
||||||
|
transform,
|
||||||
|
transition,
|
||||||
|
} = useSortable({ id: props.id });
|
||||||
|
|
||||||
|
// La única propiedad de estilo que necesitamos en línea es la que calcula dnd-kit
|
||||||
|
const style = {
|
||||||
|
transform: CSS.Transform.toString(transform),
|
||||||
|
transition,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Añadimos la clase CSS que creamos
|
||||||
|
return (
|
||||||
|
<li ref={setNodeRef} style={style} {...attributes} {...listeners} className="sortable-item">
|
||||||
|
{props.children}
|
||||||
|
</li>
|
||||||
|
);
|
||||||
|
}
|
||||||
71
Elecciones-Web/frontend-admin/src/context/AuthContext.tsx
Normal file
71
Elecciones-Web/frontend-admin/src/context/AuthContext.tsx
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
// src/context/AuthContext.tsx
|
||||||
|
import { createContext, useState, useContext, type ReactNode, useEffect } from 'react';
|
||||||
|
import { loginUser } from '../services/apiService'; // Importaremos esta función
|
||||||
|
import type { LoginCredentials } from '../services/apiService'; // y este tipo
|
||||||
|
import { subscribeToLogout } from './authUtils';
|
||||||
|
|
||||||
|
interface AuthContextType {
|
||||||
|
isAuthenticated: boolean;
|
||||||
|
token: string | null;
|
||||||
|
login: (credentials: LoginCredentials) => Promise<boolean>;
|
||||||
|
logout: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AuthContext = createContext<AuthContextType | undefined>(undefined);
|
||||||
|
|
||||||
|
export const AuthProvider = ({ children }: { children: ReactNode }) => {
|
||||||
|
const [token, setToken] = useState<string | null>(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Al cargar la app, revisamos si ya hay un token guardado
|
||||||
|
const storedToken = localStorage.getItem('admin-jwt-token');
|
||||||
|
if (storedToken) {
|
||||||
|
setToken(storedToken);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const logout = () => {
|
||||||
|
localStorage.removeItem('admin-jwt-token');
|
||||||
|
setToken(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Nos suscribimos al evento de logout global.
|
||||||
|
const handleLogout = () => logout();
|
||||||
|
subscribeToLogout(handleLogout);
|
||||||
|
}, []); // Se ejecuta solo una vez
|
||||||
|
|
||||||
|
const login = async (credentials: LoginCredentials): Promise<boolean> => {
|
||||||
|
try {
|
||||||
|
const receivedToken = await loginUser(credentials);
|
||||||
|
if (receivedToken) {
|
||||||
|
localStorage.setItem('admin-jwt-token', receivedToken);
|
||||||
|
setToken(receivedToken);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Login failed:", error);
|
||||||
|
// Asegurarse de que el usuario esté deslogueado si falla
|
||||||
|
logout();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const value = {
|
||||||
|
isAuthenticated: !!token,
|
||||||
|
token,
|
||||||
|
login,
|
||||||
|
logout,
|
||||||
|
};
|
||||||
|
|
||||||
|
return <AuthContext.Provider value={value}>{children}</AuthContext.Provider>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const useAuth = () => {
|
||||||
|
const context = useContext(AuthContext);
|
||||||
|
if (context === undefined) {
|
||||||
|
throw new Error('useAuth must be used within an AuthProvider');
|
||||||
|
}
|
||||||
|
return context;
|
||||||
|
};
|
||||||
14
Elecciones-Web/frontend-admin/src/context/authUtils.ts
Normal file
14
Elecciones-Web/frontend-admin/src/context/authUtils.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
// src/context/authUtils.ts
|
||||||
|
|
||||||
|
// Creamos un "emisor de eventos" muy simple.
|
||||||
|
const events = new EventTarget();
|
||||||
|
|
||||||
|
// La API escuchará este evento personalizado.
|
||||||
|
export function subscribeToLogout(callback: () => void) {
|
||||||
|
events.addEventListener('logout', callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
// El interceptor llamará a esta función para disparar el evento.
|
||||||
|
export function triggerLogout() {
|
||||||
|
events.dispatchEvent(new Event('logout'));
|
||||||
|
}
|
||||||
0
Elecciones-Web/frontend-admin/src/index.css
Normal file
0
Elecciones-Web/frontend-admin/src/index.css
Normal file
22
Elecciones-Web/frontend-admin/src/main.tsx
Normal file
22
Elecciones-Web/frontend-admin/src/main.tsx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// src/main.tsx
|
||||||
|
import React from 'react';
|
||||||
|
import ReactDOM from 'react-dom/client';
|
||||||
|
import App from './App.tsx';
|
||||||
|
import './index.css';
|
||||||
|
import { AuthProvider } from './context/AuthContext.tsx';
|
||||||
|
|
||||||
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||||
|
|
||||||
|
// 1. Crear una instancia del cliente de query
|
||||||
|
const queryClient = new QueryClient();
|
||||||
|
|
||||||
|
ReactDOM.createRoot(document.getElementById('root')!).render(
|
||||||
|
<React.StrictMode>
|
||||||
|
{/* 2. Envolver la aplicación con el proveedor */}
|
||||||
|
<QueryClientProvider client={queryClient}>
|
||||||
|
<AuthProvider>
|
||||||
|
<App />
|
||||||
|
</AuthProvider>
|
||||||
|
</QueryClientProvider>
|
||||||
|
</React.StrictMode>
|
||||||
|
);
|
||||||
97
Elecciones-Web/frontend-admin/src/services/apiService.ts
Normal file
97
Elecciones-Web/frontend-admin/src/services/apiService.ts
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// src/services/apiService.ts
|
||||||
|
import axios from 'axios';
|
||||||
|
import { triggerLogout } from '../context/authUtils';
|
||||||
|
import type { AgrupacionPolitica, UpdateAgrupacionData, Bancada } from '../types';
|
||||||
|
|
||||||
|
const AUTH_API_URL = 'http://localhost:5217/api/auth';
|
||||||
|
const ADMIN_API_URL = 'http://localhost:5217/api/admin';
|
||||||
|
|
||||||
|
const adminApiClient = axios.create({
|
||||||
|
baseURL: ADMIN_API_URL,
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- INTERCEPTORES (una sola vez) ---
|
||||||
|
|
||||||
|
// Interceptor de Peticiones: Añade el token JWT a cada llamada
|
||||||
|
adminApiClient.interceptors.request.use(
|
||||||
|
(config) => {
|
||||||
|
const token = localStorage.getItem('admin-jwt-token');
|
||||||
|
if (token) {
|
||||||
|
config.headers['Authorization'] = `Bearer ${token}`;
|
||||||
|
}
|
||||||
|
return config;
|
||||||
|
},
|
||||||
|
(error) => Promise.reject(error)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Interceptor de Respuestas: Maneja la expiración del token (error 401)
|
||||||
|
adminApiClient.interceptors.response.use(
|
||||||
|
(response) => response,
|
||||||
|
(error) => {
|
||||||
|
if (axios.isAxiosError(error) && error.response?.status === 401) {
|
||||||
|
console.log("Token expirado o inválido. Deslogueando...");
|
||||||
|
triggerLogout();
|
||||||
|
}
|
||||||
|
return Promise.reject(error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// --- SERVICIOS DE API ---
|
||||||
|
|
||||||
|
// 1. Autenticación
|
||||||
|
export interface LoginCredentials { username: string; password: string; }
|
||||||
|
|
||||||
|
export const loginUser = async (credentials: LoginCredentials): Promise<string | null> => {
|
||||||
|
try {
|
||||||
|
const response = await axios.post(`${AUTH_API_URL}/login`, credentials);
|
||||||
|
return response.data.token;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error during login request:", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// 2. Agrupaciones Políticas
|
||||||
|
export const getAgrupaciones = async (): Promise<AgrupacionPolitica[]> => {
|
||||||
|
const response = await adminApiClient.get('/agrupaciones');
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateAgrupacion = async (id: string, data: UpdateAgrupacionData): Promise<void> => {
|
||||||
|
await adminApiClient.put(`/agrupaciones/${id}`, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 3. Ordenamiento de Agrupaciones
|
||||||
|
export const updateOrden = async (camara: 'diputados' | 'senadores', ids: string[]): Promise<void> => {
|
||||||
|
await adminApiClient.put(`/agrupaciones/orden-${camara}`, ids);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 4. Gestión de Bancas y Ocupantes
|
||||||
|
export const getBancadas = async (camara: 'diputados' | 'senadores'): Promise<Bancada[]> => {
|
||||||
|
const camaraId = camara === 'diputados' ? 0 : 1;
|
||||||
|
const response = await adminApiClient.get(`/bancadas/${camaraId}`);
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface UpdateBancadaData {
|
||||||
|
agrupacionPoliticaId: string | null;
|
||||||
|
nombreOcupante: string | null;
|
||||||
|
fotoUrl: string | null;
|
||||||
|
periodo: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const updateBancada = async (bancadaId: number, data: UpdateBancadaData): Promise<void> => {
|
||||||
|
await adminApiClient.put(`/bancadas/${bancadaId}`, data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// 5. Configuración General
|
||||||
|
export type ConfiguracionResponse = Record<string, string>;
|
||||||
|
|
||||||
|
export const getConfiguracion = async (): Promise<ConfiguracionResponse> => {
|
||||||
|
const response = await adminApiClient.get('/configuracion');
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateConfiguracion = async (data: Record<string, string>): Promise<void> => {
|
||||||
|
await adminApiClient.put('/configuracion', data);
|
||||||
|
};
|
||||||
42
Elecciones-Web/frontend-admin/src/types/index.ts
Normal file
42
Elecciones-Web/frontend-admin/src/types/index.ts
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
// src/types/index.ts
|
||||||
|
|
||||||
|
export interface AgrupacionPolitica {
|
||||||
|
id: string;
|
||||||
|
idTelegrama: string;
|
||||||
|
nombre: string;
|
||||||
|
nombreCorto: string | null;
|
||||||
|
color: string | null;
|
||||||
|
logoUrl: string | null;
|
||||||
|
ordenDiputados: number | null;
|
||||||
|
ordenSenadores: number | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface UpdateAgrupacionData {
|
||||||
|
nombreCorto: string | null;
|
||||||
|
color: string | null;
|
||||||
|
logoUrl: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TipoCamara = {
|
||||||
|
Diputados: 0,
|
||||||
|
Senadores: 1,
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export type TipoCamaraValue = typeof TipoCamara[keyof typeof TipoCamara];
|
||||||
|
|
||||||
|
export interface OcupanteBanca {
|
||||||
|
id: number;
|
||||||
|
bancadaId: number;
|
||||||
|
nombreOcupante: string;
|
||||||
|
fotoUrl: string | null;
|
||||||
|
periodo: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nueva interfaz para la Bancada
|
||||||
|
export interface Bancada {
|
||||||
|
id: number;
|
||||||
|
camara: TipoCamaraValue;
|
||||||
|
agrupacionPoliticaId: string | null;
|
||||||
|
agrupacionPolitica: AgrupacionPolitica | null;
|
||||||
|
ocupante: OcupanteBanca | null;
|
||||||
|
}
|
||||||
1
Elecciones-Web/frontend-admin/src/vite-env.d.ts
vendored
Normal file
1
Elecciones-Web/frontend-admin/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
/// <reference types="vite/client" />
|
||||||
27
Elecciones-Web/frontend-admin/tsconfig.app.json
Normal file
27
Elecciones-Web/frontend-admin/tsconfig.app.json
Normal 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"]
|
||||||
|
}
|
||||||
7
Elecciones-Web/frontend-admin/tsconfig.json
Normal file
7
Elecciones-Web/frontend-admin/tsconfig.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"files": [],
|
||||||
|
"references": [
|
||||||
|
{ "path": "./tsconfig.app.json" },
|
||||||
|
{ "path": "./tsconfig.node.json" }
|
||||||
|
]
|
||||||
|
}
|
||||||
25
Elecciones-Web/frontend-admin/tsconfig.node.json
Normal file
25
Elecciones-Web/frontend-admin/tsconfig.node.json
Normal 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"]
|
||||||
|
}
|
||||||
7
Elecciones-Web/frontend-admin/vite.config.ts
Normal file
7
Elecciones-Web/frontend-admin/vite.config.ts
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import react from '@vitejs/plugin-react'
|
||||||
|
|
||||||
|
// https://vite.dev/config/
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [react()],
|
||||||
|
})
|
||||||
@@ -2,6 +2,51 @@
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import type { ResumenProvincial, ProyeccionBancas, MunicipioSimple, TelegramaData, CatalogoItem } from './types/types';
|
import type { ResumenProvincial, ProyeccionBancas, MunicipioSimple, TelegramaData, CatalogoItem } from './types/types';
|
||||||
|
|
||||||
|
interface PartidoData {
|
||||||
|
id: string;
|
||||||
|
nombre: string;
|
||||||
|
nombreCorto: string | null;
|
||||||
|
bancasTotales: number;
|
||||||
|
color: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CamaraData {
|
||||||
|
camaraNombre: string;
|
||||||
|
totalBancas: number;
|
||||||
|
bancasEnJuego: number;
|
||||||
|
partidos: PartidoData[];
|
||||||
|
presidenteBancada: { color: string | null } | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ComposicionData {
|
||||||
|
diputados: CamaraData;
|
||||||
|
senadores: CamaraData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OcupanteBanca {
|
||||||
|
id: number;
|
||||||
|
nombreOcupante: string;
|
||||||
|
fotoUrl: string;
|
||||||
|
periodo: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface PartidoData {
|
||||||
|
id: string;
|
||||||
|
nombre: string;
|
||||||
|
nombreCorto: string | null;
|
||||||
|
bancasTotales: number;
|
||||||
|
bancasEnJuego: number;
|
||||||
|
color: string | null;
|
||||||
|
ocupantes: OcupanteBanca[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface BancadaDetalle {
|
||||||
|
id: number; // Este es el ID de la Bancada
|
||||||
|
camara: number; // 0 o 1
|
||||||
|
agrupacionPoliticaId: string | null;
|
||||||
|
ocupante: OcupanteBanca | null;
|
||||||
|
}
|
||||||
|
|
||||||
const API_BASE_URL = 'http://localhost:5217/api';
|
const API_BASE_URL = 'http://localhost:5217/api';
|
||||||
|
|
||||||
const apiClient = axios.create({
|
const apiClient = axios.create({
|
||||||
@@ -36,26 +81,36 @@ export const getTelegramaPorId = async (mesaId: string): Promise<TelegramaData>
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const getSecciones = async (): Promise<CatalogoItem[]> => {
|
export const getSecciones = async (): Promise<CatalogoItem[]> => {
|
||||||
const response = await apiClient.get('/catalogos/secciones');
|
const response = await apiClient.get('/catalogos/secciones');
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getMunicipiosPorSeccion = async (seccionId: string): Promise<CatalogoItem[]> => {
|
export const getMunicipiosPorSeccion = async (seccionId: string): Promise<CatalogoItem[]> => {
|
||||||
const response = await apiClient.get(`/catalogos/municipios/${seccionId}`);
|
const response = await apiClient.get(`/catalogos/municipios/${seccionId}`);
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getCircuitosPorMunicipio = async (municipioId: string): Promise<CatalogoItem[]> => {
|
export const getCircuitosPorMunicipio = async (municipioId: string): Promise<CatalogoItem[]> => {
|
||||||
const response = await apiClient.get(`/catalogos/circuitos/${municipioId}`);
|
const response = await apiClient.get(`/catalogos/circuitos/${municipioId}`);
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getEstablecimientosPorCircuito = async (circuitoId: string): Promise<CatalogoItem[]> => {
|
export const getEstablecimientosPorCircuito = async (circuitoId: string): Promise<CatalogoItem[]> => {
|
||||||
const response = await apiClient.get(`/catalogos/establecimientos/${circuitoId}`);
|
const response = await apiClient.get(`/catalogos/establecimientos/${circuitoId}`);
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getMesasPorEstablecimiento = async (establecimientoId: string): Promise<CatalogoItem[]> => {
|
export const getMesasPorEstablecimiento = async (establecimientoId: string): Promise<CatalogoItem[]> => {
|
||||||
const response = await apiClient.get(`/catalogos/mesas/${establecimientoId}`);
|
const response = await apiClient.get(`/catalogos/mesas/${establecimientoId}`);
|
||||||
return response.data;
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getComposicionCongreso = async (): Promise<ComposicionData> => {
|
||||||
|
const response = await apiClient.get('/resultados/composicion-congreso');
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getBancadasDetalle = async (): Promise<BancadaDetalle[]> => {
|
||||||
|
const response = await apiClient.get('/resultados/bancadas-detalle');
|
||||||
|
return response.data;
|
||||||
};
|
};
|
||||||
@@ -31,8 +31,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@keyframes fadeIn {
|
@keyframes fadeIn {
|
||||||
from { opacity: 0; transform: scale(0.9); }
|
from {
|
||||||
to { opacity: 1; transform: scale(1); }
|
opacity: 0;
|
||||||
|
transform: scale(0.9);
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.congreso-summary {
|
.congreso-summary {
|
||||||
@@ -138,6 +145,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
padding: 1.5rem;
|
padding: 1.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.congreso-summary {
|
.congreso-summary {
|
||||||
border-left: none;
|
border-left: none;
|
||||||
padding-left: 0;
|
padding-left: 0;
|
||||||
@@ -145,4 +153,52 @@
|
|||||||
border-top: 1px solid #e0e0e0;
|
border-top: 1px solid #e0e0e0;
|
||||||
padding-top: 1.5rem;
|
padding-top: 1.5rem;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.seat-tooltip {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 5px;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.seat-tooltip img {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seat-tooltip p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.seat-tooltip {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
gap: 5px;
|
||||||
|
padding: 8px;
|
||||||
|
background-color: white;
|
||||||
|
}
|
||||||
|
.seat-tooltip img {
|
||||||
|
width: 60px;
|
||||||
|
height: 60px;
|
||||||
|
border-radius: 50%;
|
||||||
|
object-fit: cover;
|
||||||
|
border: 2px solid #ccc;
|
||||||
|
}
|
||||||
|
.seat-tooltip p {
|
||||||
|
margin: 0;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #333;
|
||||||
}
|
}
|
||||||
@@ -1,125 +1,109 @@
|
|||||||
// src/components/CongresoWidget.tsx
|
// src/components/CongresoWidget.tsx
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useMemo } from 'react';
|
||||||
// 1. Importar ambos layouts
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { ParliamentLayout } from './ParliamentLayout';
|
import { ParliamentLayout } from './ParliamentLayout';
|
||||||
import { SenateLayout } from './SenateLayout';
|
import { SenateLayout } from './SenateLayout';
|
||||||
|
import { getComposicionCongreso, getBancadasDetalle } from '../apiService';
|
||||||
|
import type { ComposicionData, BancadaDetalle } from '../apiService';
|
||||||
|
import { Tooltip } from 'react-tooltip';
|
||||||
import './CongresoWidget.css';
|
import './CongresoWidget.css';
|
||||||
|
|
||||||
// ... (Interfaces sin cambios)
|
|
||||||
type CamaraType = 'diputados' | 'senadores';
|
type CamaraType = 'diputados' | 'senadores';
|
||||||
|
const DEFAULT_COLOR = '#808080';
|
||||||
interface PartidoData {
|
|
||||||
id: string;
|
|
||||||
nombre: string;
|
|
||||||
bancasTotales: number;
|
|
||||||
bancasEnJuego: number;
|
|
||||||
color: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface CamaraData {
|
|
||||||
camaraNombre: string;
|
|
||||||
totalBancas: number;
|
|
||||||
bancasEnJuego: number;
|
|
||||||
partidos: PartidoData[];
|
|
||||||
}
|
|
||||||
|
|
||||||
interface ComposicionData {
|
|
||||||
diputados: CamaraData;
|
|
||||||
senadores: CamaraData;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const CongresoWidget = () => {
|
export const CongresoWidget = () => {
|
||||||
const [data, setData] = useState<ComposicionData | null>(null);
|
|
||||||
const [camaraActiva, setCamaraActiva] = useState<CamaraType>('diputados');
|
const [camaraActiva, setCamaraActiva] = useState<CamaraType>('diputados');
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
|
|
||||||
useEffect(() => {
|
const { data: composicionData, isLoading: isLoadingComposicion, error: errorComposicion } = useQuery<ComposicionData>({
|
||||||
// ... (fetchData sin cambios)
|
queryKey: ['composicionCongreso'],
|
||||||
const fetchData = async () => {
|
queryFn: getComposicionCongreso,
|
||||||
try {
|
|
||||||
const response = await fetch('http://localhost:5217/api/resultados/composicion-congreso');
|
|
||||||
if (!response.ok) throw new Error('La respuesta de la red no fue exitosa');
|
|
||||||
const result: ComposicionData = await response.json();
|
|
||||||
setData(result);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Error cargando datos de composición:", err);
|
|
||||||
setError("No se pudieron cargar los datos de composición del congreso.");
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
fetchData();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
if (loading) return <div className="congreso-container loading">Cargando...</div>;
|
|
||||||
if (error) return <div className="congreso-container error">{error}</div>;
|
|
||||||
|
|
||||||
const datosCamaraActual = data ? data[camaraActiva] : null;
|
|
||||||
|
|
||||||
if (!datosCamaraActual) {
|
|
||||||
return <div className="congreso-container error">Datos no disponibles para la cámara seleccionada.</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
const partidosOrdenados = datosCamaraActual.partidos;
|
|
||||||
|
|
||||||
const seatFillData = partidosOrdenados.flatMap(party => {
|
|
||||||
const retainedSeats = party.bancasTotales - party.bancasEnJuego;
|
|
||||||
const inPlaySeats = party.bancasEnJuego;
|
|
||||||
return [
|
|
||||||
...Array(retainedSeats).fill({ color: party.color, isEnJuego: false }),
|
|
||||||
...Array(inPlaySeats).fill({ color: party.color, isEnJuego: true }),
|
|
||||||
];
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const { data: bancadasDetalle = [] } = useQuery<BancadaDetalle[]>({
|
||||||
|
queryKey: ['bancadasDetalle'],
|
||||||
|
queryFn: getBancadasDetalle,
|
||||||
|
enabled: !!composicionData,
|
||||||
|
});
|
||||||
|
|
||||||
|
const datosCamaraActual = composicionData ? composicionData[camaraActiva] : null;
|
||||||
|
|
||||||
|
// --- LÓGICA DE SEATFILLDATA ---
|
||||||
|
const seatFillData = useMemo(() => {
|
||||||
|
if (!datosCamaraActual || !bancadasDetalle.length) return [];
|
||||||
|
|
||||||
|
const camaraId = camaraActiva === 'diputados' ? 0 : 1;
|
||||||
|
const bancadasDeCamara = bancadasDetalle.filter(b => b.camara === camaraId);
|
||||||
|
|
||||||
|
// Creamos un mapa de AgrupacionId -> Color para un acceso rápido
|
||||||
|
const colorMap = new Map<string, string>();
|
||||||
|
datosCamaraActual.partidos.forEach(p => {
|
||||||
|
if (p.id && p.color) {
|
||||||
|
colorMap.set(p.id, p.color);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 1. Aseguramos que la lista de bancas esté en orden físico (por su ID).
|
||||||
|
const bancadasOrdenadas = bancadasDeCamara.sort((a, b) => a.id - b.id);
|
||||||
|
|
||||||
|
// 2. Mapeamos cada banca física a un objeto SeatFillData.
|
||||||
|
// El índice del array corresponderá al asiento visual.
|
||||||
|
return bancadasOrdenadas.map(bancada => ({
|
||||||
|
color: bancada.agrupacionPoliticaId ? colorMap.get(bancada.agrupacionPoliticaId) || DEFAULT_COLOR : DEFAULT_COLOR,
|
||||||
|
ocupante: bancada.ocupante
|
||||||
|
}));
|
||||||
|
|
||||||
|
}, [datosCamaraActual, bancadasDetalle, camaraActiva]);
|
||||||
|
|
||||||
|
if (isLoadingComposicion) return <div className="congreso-container loading">Cargando...</div>;
|
||||||
|
if (errorComposicion || !datosCamaraActual) return <div className="congreso-container error">No se pudo cargar la composición.</div>;
|
||||||
|
|
||||||
|
const partidosOrdenados = datosCamaraActual.partidos;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="congreso-container">
|
<div className="congreso-container">
|
||||||
<div className="congreso-grafico">
|
<div className="congreso-grafico">
|
||||||
{/* --- INICIO DE LA MODIFICACIÓN: RENDERIZADO CONDICIONAL --- */}
|
|
||||||
{camaraActiva === 'diputados' ? (
|
{camaraActiva === 'diputados' ? (
|
||||||
<ParliamentLayout seatData={seatFillData} />
|
<ParliamentLayout seatData={seatFillData} presidenteBancada={datosCamaraActual.presidenteBancada} />
|
||||||
) : (
|
) : (
|
||||||
<SenateLayout seatData={seatFillData} />
|
<SenateLayout seatData={seatFillData} presidenteBancada={datosCamaraActual.presidenteBancada} />
|
||||||
)}
|
)}
|
||||||
{/* --- FIN DE LA MODIFICACIÓN --- */}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="congreso-summary">
|
<div className="congreso-summary">
|
||||||
<div className="chamber-tabs">
|
<div className="chamber-tabs">
|
||||||
<button
|
<button
|
||||||
className={camaraActiva === 'diputados' ? 'active' : ''}
|
className={camaraActiva === 'diputados' ? 'active' : ''}
|
||||||
onClick={() => setCamaraActiva('diputados')}
|
onClick={() => setCamaraActiva('diputados')}
|
||||||
>
|
>
|
||||||
Diputados
|
Diputados
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className={camaraActiva === 'senadores' ? 'active' : ''}
|
className={camaraActiva === 'senadores' ? 'active' : ''}
|
||||||
onClick={() => setCamaraActiva('senadores')}
|
onClick={() => setCamaraActiva('senadores')}
|
||||||
>
|
>
|
||||||
Senadores
|
Senadores
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h3>{datosCamaraActual.camaraNombre}</h3>
|
<h3>{datosCamaraActual.camaraNombre}</h3>
|
||||||
<div className="summary-metric">
|
<div className="summary-metric">
|
||||||
<span>Total de Bancas</span>
|
<span>Total de Bancas</span>
|
||||||
<strong>{datosCamaraActual.totalBancas}</strong>
|
<strong>{datosCamaraActual.totalBancas}</strong>
|
||||||
</div>
|
</div>
|
||||||
<div className="summary-metric">
|
|
||||||
<span>Bancas en juego</span>
|
|
||||||
<strong>{datosCamaraActual.bancasEnJuego}</strong>
|
|
||||||
</div>
|
|
||||||
<hr />
|
<hr />
|
||||||
<ul className="partido-lista">
|
<ul className="partido-lista">
|
||||||
{partidosOrdenados.map(partido => (
|
{partidosOrdenados.map(partido => (
|
||||||
<li key={partido.id}>
|
<li key={partido.id}>
|
||||||
<span className="partido-color-box" style={{ backgroundColor: partido.color }}></span>
|
<span className="partido-color-box" style={{ backgroundColor: partido.color || DEFAULT_COLOR }}></span>
|
||||||
<span className="partido-nombre">{partido.nombre}</span>
|
<span className="partido-nombre">
|
||||||
|
{partido.nombreCorto || partido.nombre}
|
||||||
|
</span>
|
||||||
<strong className="partido-bancas">{partido.bancasTotales}</strong>
|
<strong className="partido-bancas">{partido.bancasTotales}</strong>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
{/* Es importante que el Tooltip esté fuera del div que se re-renderiza con el cambio de pestaña */}
|
||||||
|
<Tooltip id="seat-tooltip" />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -7,7 +7,6 @@ import { useQuery } from '@tanstack/react-query';
|
|||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import type { Feature, Geometry } from 'geojson';
|
import type { Feature, Geometry } from 'geojson';
|
||||||
import { geoCentroid } from 'd3-geo';
|
import { geoCentroid } from 'd3-geo';
|
||||||
|
|
||||||
import './MapaBsAs.css';
|
import './MapaBsAs.css';
|
||||||
|
|
||||||
// --- Interfaces y Tipos ---
|
// --- Interfaces y Tipos ---
|
||||||
@@ -17,6 +16,7 @@ interface ResultadoMapa {
|
|||||||
ambitoId: number;
|
ambitoId: number;
|
||||||
departamentoNombre: string;
|
departamentoNombre: string;
|
||||||
agrupacionGanadoraId: string;
|
agrupacionGanadoraId: string;
|
||||||
|
colorGanador: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ResultadoDetalladoMunicipio {
|
interface ResultadoDetalladoMunicipio {
|
||||||
@@ -44,14 +44,11 @@ type PartidoGeography = Feature<Geometry, PartidoProperties> & { rsmKey: string
|
|||||||
|
|
||||||
// --- Constantes ---
|
// --- Constantes ---
|
||||||
const API_BASE_URL = 'http://localhost:5217/api';
|
const API_BASE_URL = 'http://localhost:5217/api';
|
||||||
const COLORES_BASE: string[] = ["#FF5733", "#33FF57", "#3357FF", "#FF33A1", "#A133FF", "#33FFA1", "#FFC300", "#C70039", "#900C3F", "#581845"];
|
|
||||||
const MIN_ZOOM = 1;
|
const MIN_ZOOM = 1;
|
||||||
const MAX_ZOOM = 8;
|
const MAX_ZOOM = 8;
|
||||||
// Define los límites del paneo: [[x0, y0], [x1, y1]].
|
|
||||||
// Esto evita que el mapa se "pierda" fuera de la vista.
|
|
||||||
// Estos valores pueden necesitar ajuste fino según el tamaño final del contenedor del mapa.
|
|
||||||
const TRANSLATE_EXTENT: [[number, number], [number, number]] = [[-100, -600], [1100, 300]];
|
const TRANSLATE_EXTENT: [[number, number], [number, number]] = [[-100, -600], [1100, 300]];
|
||||||
const INITIAL_POSITION = { center: [-60, -37.25] as PointTuple, zoom: MIN_ZOOM };
|
const INITIAL_POSITION = { center: [-60.5, -37.2] as PointTuple, zoom: MIN_ZOOM };
|
||||||
|
const DEFAULT_MAP_COLOR = '#E0E0E0';
|
||||||
|
|
||||||
// --- Componente Principal ---
|
// --- Componente Principal ---
|
||||||
const MapaBsAs = () => {
|
const MapaBsAs = () => {
|
||||||
@@ -71,26 +68,34 @@ const MapaBsAs = () => {
|
|||||||
queryFn: async () => (await axios.get(`${API_BASE_URL}/Catalogos/agrupaciones`)).data,
|
queryFn: async () => (await axios.get(`${API_BASE_URL}/Catalogos/agrupaciones`)).data,
|
||||||
});
|
});
|
||||||
|
|
||||||
const { nombresAgrupaciones, coloresPartidos, resultadosPorDepartamento } = useMemo(() => {
|
// --- SU SOLUCIÓN CORRECTA INTEGRADA ---
|
||||||
const nombresMap = new Map<string, string>();
|
const { nombresAgrupaciones, resultadosPorDepartamento } = useMemo<{
|
||||||
const coloresMap = new Map<string, string>();
|
nombresAgrupaciones: Map<string, string>;
|
||||||
const resultadosMap = new Map<string, ResultadoMapa>();
|
resultadosPorDepartamento: Map<string, ResultadoMapa>;
|
||||||
if (agrupacionesData) {
|
}>(() => {
|
||||||
agrupacionesData.forEach((agrupacion, index) => {
|
const nombresMap = new Map<string, string>();
|
||||||
nombresMap.set(agrupacion.id, agrupacion.nombre);
|
const resultadosMap = new Map<string, ResultadoMapa>();
|
||||||
coloresMap.set(agrupacion.id, COLORES_BASE[index % COLORES_BASE.length]);
|
|
||||||
});
|
if (agrupacionesData) {
|
||||||
}
|
agrupacionesData.forEach((agrupacion) => {
|
||||||
// Se cambia el color por defecto a uno más apropiado para fondo claro
|
nombresMap.set(agrupacion.id, agrupacion.nombre);
|
||||||
coloresMap.set('default', '#E0E0E0');
|
});
|
||||||
if (resultadosData) {
|
}
|
||||||
resultadosData.forEach(r => resultadosMap.set(r.departamentoNombre.toUpperCase(), r));
|
|
||||||
}
|
if (resultadosData) {
|
||||||
return { nombresAgrupaciones: nombresMap, coloresPartidos: coloresMap, resultadosPorDepartamento: resultadosMap };
|
resultadosData.forEach(r => resultadosMap.set(r.departamentoNombre.toUpperCase(), r));
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
nombresAgrupaciones: nombresMap,
|
||||||
|
resultadosPorDepartamento: resultadosMap
|
||||||
|
};
|
||||||
}, [agrupacionesData, resultadosData]);
|
}, [agrupacionesData, resultadosData]);
|
||||||
|
|
||||||
const isLoading = isLoadingResultados || isLoadingAgrupaciones || isLoadingGeo;
|
const isLoading = isLoadingResultados || isLoadingAgrupaciones || isLoadingGeo;
|
||||||
|
|
||||||
|
// ... (el resto del componente no necesita cambios)
|
||||||
|
|
||||||
const handleReset = useCallback(() => {
|
const handleReset = useCallback(() => {
|
||||||
setSelectedAmbitoId(null);
|
setSelectedAmbitoId(null);
|
||||||
setPosition(INITIAL_POSITION);
|
setPosition(INITIAL_POSITION);
|
||||||
@@ -111,22 +116,15 @@ const MapaBsAs = () => {
|
|||||||
}, [selectedAmbitoId, handleReset, resultadosPorDepartamento]);
|
}, [selectedAmbitoId, handleReset, resultadosPorDepartamento]);
|
||||||
|
|
||||||
const handleMoveEnd = (newPosition: { coordinates: PointTuple; zoom: number }) => {
|
const handleMoveEnd = (newPosition: { coordinates: PointTuple; zoom: number }) => {
|
||||||
// La lógica de reseteo cuando se hace zoom out completamente con la rueda del ratón se mantiene.
|
|
||||||
// El `translateExtent` ya previene que el mapa se mueva fuera de los límites.
|
|
||||||
if (newPosition.zoom <= MIN_ZOOM) {
|
if (newPosition.zoom <= MIN_ZOOM) {
|
||||||
if (position.zoom > MIN_ZOOM || selectedAmbitoId !== null) {
|
if (position.zoom > MIN_ZOOM || selectedAmbitoId !== null) {
|
||||||
handleReset();
|
handleReset();
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Si se está haciendo zoom out desde una vista detallada, se deselecciona el municipio
|
|
||||||
// para volver a la vista general sin resetear completamente la posición.
|
|
||||||
if (newPosition.zoom < position.zoom && selectedAmbitoId !== null) {
|
if (newPosition.zoom < position.zoom && selectedAmbitoId !== null) {
|
||||||
setSelectedAmbitoId(null);
|
setSelectedAmbitoId(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Actualiza el estado con la nueva posición y zoom del paneo/zoom del usuario.
|
|
||||||
setPosition({ center: newPosition.coordinates, zoom: newPosition.zoom });
|
setPosition({ center: newPosition.coordinates, zoom: newPosition.zoom });
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -144,8 +142,10 @@ const MapaBsAs = () => {
|
|||||||
|
|
||||||
const getPartyFillColor = (departamentoNombre: string) => {
|
const getPartyFillColor = (departamentoNombre: string) => {
|
||||||
const resultado = resultadosPorDepartamento.get(departamentoNombre.toUpperCase());
|
const resultado = resultadosPorDepartamento.get(departamentoNombre.toUpperCase());
|
||||||
if (!resultado) return coloresPartidos.get('default') || '#D6D6DA';
|
if (!resultado || !resultado.colorGanador) {
|
||||||
return coloresPartidos.get(resultado.agrupacionGanadoraId) || coloresPartidos.get('default');
|
return DEFAULT_MAP_COLOR;
|
||||||
|
}
|
||||||
|
return resultado.colorGanador;
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseEnter = (e: MouseEvent<SVGPathElement>) => {
|
const handleMouseEnter = (e: MouseEvent<SVGPathElement>) => {
|
||||||
@@ -160,8 +160,7 @@ const MapaBsAs = () => {
|
|||||||
return (
|
return (
|
||||||
<div className="mapa-wrapper">
|
<div className="mapa-wrapper">
|
||||||
<div className="mapa-container">
|
<div className="mapa-container">
|
||||||
{/* Se elimina el 'style' con el backgroundColor para que lo controle el CSS */}
|
<ComposableMap projection="geoMercator" projectionConfig={{ scale: 4400, center: [-60.5, -37.2] }} className="rsm-svg">
|
||||||
<ComposableMap projection="geoMercator" projectionConfig={{ scale: 6000, center: [-60, -37.25] }} className="rsm-svg">
|
|
||||||
<ZoomableGroup
|
<ZoomableGroup
|
||||||
center={position.center}
|
center={position.center}
|
||||||
zoom={position.zoom}
|
zoom={position.zoom}
|
||||||
@@ -171,7 +170,6 @@ const MapaBsAs = () => {
|
|||||||
minZoom={MIN_ZOOM}
|
minZoom={MIN_ZOOM}
|
||||||
maxZoom={MAX_ZOOM}
|
maxZoom={MAX_ZOOM}
|
||||||
filterZoomEvent={(e: WheelEvent) => {
|
filterZoomEvent={(e: WheelEvent) => {
|
||||||
// Detectamos si la rueda se mueve hacia atrás (zoom out)
|
|
||||||
if (e.deltaY > 0) {
|
if (e.deltaY > 0) {
|
||||||
handleReset();
|
handleReset();
|
||||||
} else if (e.deltaY < 0) {
|
} else if (e.deltaY < 0) {
|
||||||
@@ -198,7 +196,6 @@ const MapaBsAs = () => {
|
|||||||
data-tooltip-content={`${geo.properties.departamento}: ${nombreAgrupacionGanadora}`}
|
data-tooltip-content={`${geo.properties.departamento}: ${nombreAgrupacionGanadora}`}
|
||||||
className={`rsm-geography ${isSelected ? 'selected' : ''} ${isFaded ? 'faded' : ''}`}
|
className={`rsm-geography ${isSelected ? 'selected' : ''} ${isFaded ? 'faded' : ''}`}
|
||||||
fill={getPartyFillColor(geo.properties.departamento)}
|
fill={getPartyFillColor(geo.properties.departamento)}
|
||||||
// Se elimina la prop 'stroke' para que la controle el CSS
|
|
||||||
onClick={() => handleGeographyClick(geo)}
|
onClick={() => handleGeographyClick(geo)}
|
||||||
onMouseEnter={handleMouseEnter}
|
onMouseEnter={handleMouseEnter}
|
||||||
/>
|
/>
|
||||||
@@ -209,13 +206,12 @@ const MapaBsAs = () => {
|
|||||||
)}
|
)}
|
||||||
</ZoomableGroup>
|
</ZoomableGroup>
|
||||||
</ComposableMap>
|
</ComposableMap>
|
||||||
{/* Se añade una variante 'light' al Tooltip para que combine mejor */}
|
|
||||||
<Tooltip id="partido-tooltip" variant="light" />
|
<Tooltip id="partido-tooltip" variant="light" />
|
||||||
{selectedAmbitoId !== null && <ControlesMapa onReset={handleReset} />}
|
{selectedAmbitoId !== null && <ControlesMapa onReset={handleReset} />}
|
||||||
</div>
|
</div>
|
||||||
<div className="info-panel">
|
<div className="info-panel">
|
||||||
<DetalleMunicipio ambitoId={selectedAmbitoId} onReset={handleReset} />
|
<DetalleMunicipio ambitoId={selectedAmbitoId} onReset={handleReset} />
|
||||||
<Legend colores={coloresPartidos} nombres={nombresAgrupaciones} />
|
<Legend resultados={resultadosPorDepartamento} nombresAgrupaciones={nombresAgrupaciones} />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
@@ -264,9 +260,34 @@ const DetalleMunicipio = ({ ambitoId, onReset }: { ambitoId: number | null; onRe
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Legend = ({ colores, nombres }: { colores: Map<string, string>; nombres: Map<string, string> }) => {
|
const Legend = ({ resultados, nombresAgrupaciones }: { resultados: Map<string, ResultadoMapa>, nombresAgrupaciones: Map<string, string> }) => {
|
||||||
const legendItems = Array.from(colores.entries()).filter(([id]) => id !== 'default').map(([id, color]) => ({ nombre: nombres.get(id) || 'Desconocido', color: color }));
|
|
||||||
return (<div className="legend"><h4>Leyenda de Ganadores</h4>{legendItems.map(item => (<div key={item.nombre} className="legend-item"><div className="legend-color-box" style={{ backgroundColor: item.color }} /><span>{item.nombre}</span></div>))}</div>);
|
const legendItems = useMemo(() => {
|
||||||
|
const ganadoresUnicos = new Map<string, { nombre: string; color: string }>();
|
||||||
|
|
||||||
|
resultados.forEach(resultado => {
|
||||||
|
if (resultado.colorGanador && !ganadoresUnicos.has(resultado.agrupacionGanadoraId)) {
|
||||||
|
ganadoresUnicos.set(resultado.agrupacionGanadoraId, {
|
||||||
|
nombre: nombresAgrupaciones.get(resultado.agrupacionGanadoraId) || 'Desconocido',
|
||||||
|
color: resultado.colorGanador
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return Array.from(ganadoresUnicos.values());
|
||||||
|
}, [resultados, nombresAgrupaciones]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="legend">
|
||||||
|
<h4>Leyenda de Ganadores</h4>
|
||||||
|
{legendItems.map(item => (
|
||||||
|
<div key={item.nombre} className="legend-item">
|
||||||
|
<div className="legend-color-box" style={{ backgroundColor: item.color }} />
|
||||||
|
<span>{item.nombre}</span>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default MapaBsAs;
|
export default MapaBsAs;
|
||||||
@@ -1,139 +1,169 @@
|
|||||||
// src/components/ParliamentLayout.tsx
|
// src/components/ParliamentLayout.tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
// Interfaces (sin cambios)
|
// Interfaces (no cambian)
|
||||||
interface SeatFillData {
|
interface SeatFillData {
|
||||||
color: string;
|
color: string;
|
||||||
isEnJuego: boolean;
|
// Añadimos la propiedad opcional 'ocupante'
|
||||||
|
ocupante?: {
|
||||||
|
nombreOcupante: string;
|
||||||
|
fotoUrl: string | null;
|
||||||
|
} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ParliamentLayoutProps {
|
interface ParliamentLayoutProps {
|
||||||
seatData: SeatFillData[];
|
seatData: SeatFillData[];
|
||||||
size?: number;
|
size?: number;
|
||||||
|
presidenteBancada: { color: string | null } | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PRESIDENTE_SEAT_INDEX = 91;
|
||||||
|
|
||||||
export const ParliamentLayout: React.FC<ParliamentLayoutProps> = ({
|
export const ParliamentLayout: React.FC<ParliamentLayoutProps> = ({
|
||||||
seatData,
|
seatData,
|
||||||
size = 400,
|
size = 400,
|
||||||
|
presidenteBancada,
|
||||||
}) => {
|
}) => {
|
||||||
const uniqueColors = [...new Set(seatData.map(d => d.color))];
|
const uniqueColors = [...new Set(seatData.map(d => d.color))];
|
||||||
|
|
||||||
// La plantilla de círculos estáticos
|
// --- NUEVO ARRAY DE ELEMENTOS ORDENADO ---
|
||||||
const seatElements = [
|
const seatElements = [
|
||||||
<circle key="seat-0" id="seat-0" r="9.964" cy="160.283" cx="-255.056" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-0" id="seat-0" r="12" cy="268.306" cx="202.26" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-1" id="seat-1" r="9.964" cy="114.844" cx="-252.766" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-1" id="seat-1" r="12" cy="214.247" cx="223.62" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-2" id="seat-2" r="9.964" cy="68.323" cx="-249.04" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-2" id="seat-2" r="12" cy="253.417" cx="184.047" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-3" id="seat-3" r="9.964" cy="167.585" cx="-230.037" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-3" id="seat-3" r="12" cy="290.475" cx="148.465" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-4" id="seat-4" r="9.964" cy="121.335" cx="-226.656" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-4" id="seat-4" r="12" cy="199.221" cx="204.812" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-5" id="seat-5" r="9.964" cy="74.003" cx="-224.493" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-5" id="seat-5" r="12" cy="238.165" cx="165.39" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-6" id="seat-6" r="9.964" cy="22.948" cx="-223.55" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-6" id="seat-6" r="12" cy="274.606" cx="129.053" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-7" id="seat-7" r="9.964" cy="183.347" cx="-208.602" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-7" id="seat-7" r="12" cy="307.801" cx="95.891" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-8" id="seat-8" r="9.964" cy="132.154" cx="-203.666" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-8" id="seat-8" r="12" cy="184.139" cx="184.653" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-9" id="seat-9" r="9.964" cy="82.117" cx="-199.609" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-9" id="seat-9" r="12" cy="223.156" cx="147.029" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-10" id="seat-10" r="9.964" cy="30.215" cx="-197.157" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-10" id="seat-10" r="12" cy="259.444" cx="110.504" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-11" id="seat-11" r="9.964" cy="145.407" cx="-182.84" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-11" id="seat-11" r="12" cy="291.519" cx="75.175" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-12" id="seat-12" r="9.964" cy="93.477" cx="-175.808" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-12" id="seat-12" r="12" cy="169.647" cx="164.36" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-13" id="seat-13" r="9.964" cy="39.969" cx="-171.147" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-13" id="seat-13" r="12" cy="209.251" cx="125.789" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-14" id="seat-14" r="9.964" cy="163.733" cx="-163.582" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-14" id="seat-14" r="12" cy="246.564" cx="88.133" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-15" id="seat-15" r="9.964" cy="108.082" cx="-153.63" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-15" id="seat-15" r="12" cy="280.15" cx="51.596" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-16" id="seat-16" r="9.964" cy="51.554" cx="-147.409" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-16" id="seat-16" r="12" cy="157.248" cx="142.356" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-17" id="seat-17" r="9.964" cy="125.122" cx="-134.967" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-17" id="seat-17" r="12" cy="197.635" cx="103.42" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-18" id="seat-18" r="9.964" cy="66.206" cx="-124.894" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-18" id="seat-18" r="12" cy="238.303" cx="63.378" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-19" id="seat-19" r="9.964" cy="143.999" cx="-118.288" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-19" id="seat-19" r="12" cy="145.84" cx="118.145" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-20" id="seat-20" r="9.964" cy="82.48" cx="-104.338" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-20" id="seat-20" r="12" cy="187.919" cx="77.562" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-21" id="seat-21" r="9.964" cy="102.267" cx="-85.471" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-21" id="seat-21" r="12" cy="137.535" cx="91.746" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-22" id="seat-22" r="9.964" cy="123.093" cx="-70.302" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-22" id="seat-22" r="12" cy="123.093" cx="-70.302" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-23" id="seat-23" r="9.964" cy="280.15" cx="51.596" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-23" id="seat-23" r="12" cy="143.999" cx="-118.288" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-24" id="seat-24" r="9.964" cy="238.303" cx="63.378" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-24" id="seat-24" r="12" cy="163.733" cx="-163.582" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-25" id="seat-25" r="9.964" cy="187.919" cx="77.562" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-25" id="seat-25" r="12" cy="183.347" cx="-208.602" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-26" id="seat-26" r="9.964" cy="137.535" cx="91.746" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-26" id="seat-26" r="12" cy="102.267" cx="-85.471" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-27" id="seat-27" r="9.964" cy="291.519" cx="75.175" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-27" id="seat-27" r="12" cy="125.122" cx="-134.967" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-28" id="seat-28" r="9.964" cy="246.564" cx="88.133" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-28" id="seat-28" r="12" cy="145.407" cx="-182.84" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-29" id="seat-29" r="9.964" cy="197.635" cx="103.42" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-29" id="seat-29" r="12" cy="167.585" cx="-230.037" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-30" id="seat-30" r="9.964" cy="145.84" cx="118.145" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-30" id="seat-30" r="12" cy="82.48" cx="-104.338" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-31" id="seat-31" r="9.964" cy="307.801" cx="95.891" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-31" id="seat-31" r="12" cy="108.082" cx="-153.63" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-32" id="seat-32" r="9.964" cy="259.444" cx="110.504" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-32" id="seat-32" r="12" cy="132.154" cx="-203.666" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-33" id="seat-33" r="9.964" cy="209.251" cx="125.789" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-33" id="seat-33" r="12" cy="160.283" cx="-255.056" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-34" id="seat-34" r="9.964" cy="157.248" cx="142.356" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-34" id="seat-34" r="12" cy="66.206" cx="-124.894" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-35" id="seat-35" r="9.964" cy="274.606" cx="129.053" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-35" id="seat-35" r="12" cy="93.477" cx="-175.808" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-36" id="seat-36" r="9.964" cy="223.156" cx="147.029" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-36" id="seat-36" r="12" cy="121.335" cx="-226.656" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-37" id="seat-37" r="9.964" cy="169.647" cx="164.36" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-37" id="seat-37" r="12" cy="51.554" cx="-147.409" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-38" id="seat-38" r="9.964" cy="290.475" cx="148.465" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-38" id="seat-38" r="12" cy="82.117" cx="-199.609" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-39" id="seat-39" r="9.964" cy="238.165" cx="165.39" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-39" id="seat-39" r="12" cy="114.844" cx="-252.766" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-40" id="seat-40" r="9.964" cy="184.139" cx="184.653" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-40" id="seat-40" r="12" cy="39.969" cx="-171.147" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-41" id="seat-41" r="9.964" cy="253.417" cx="184.047" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-41" id="seat-41" r="12" cy="74.003" cx="-224.493" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-42" id="seat-42" r="9.964" cy="199.221" cx="204.812" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-42" id="seat-42" r="12" cy="30.215" cx="-197.157" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-43" id="seat-43" r="9.964" cy="268.306" cx="202.26" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-43" id="seat-43" r="12" cy="68.323" cx="-249.04" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-44" id="seat-44" r="9.964" cy="214.247" cx="223.62" transform="matrix(-0.632908, 0.774227, 0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-44" id="seat-44" r="12" cy="22.948" cx="-223.55" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="seat-45" id="seat-45" r="9.964" cy="308.5" cx="-275.898" transform="matrix(-1, 0, 0, 1, 0, 0)"/>,
|
<circle key="seat-45" id="seat-45" r="12" cy="22.948" cx="328.246" />,
|
||||||
<circle key="seat-46" id="seat-46" r="9.964" cy="160.283" cx="296.74"/>,
|
<circle key="seat-46" id="seat-46" r="12" cy="68.323" cx="302.756" />,
|
||||||
<circle key="seat-47" id="seat-47" r="9.964" cy="114.844" cx="299.029"/>,
|
<circle key="seat-47" id="seat-47" r="12" cy="114.844" cx="299.029" />,
|
||||||
<circle key="seat-48" id="seat-48" r="9.964" cy="68.323" cx="302.756"/>,
|
<circle key="seat-48" id="seat-48" r="12" cy="160.283" cx="296.74" />,
|
||||||
<circle key="seat-49" id="seat-49" r="9.964" cy="167.585" cx="321.759"/>,
|
<circle key="seat-49" id="seat-49" r="12" cy="30.215" cx="354.639" />,
|
||||||
<circle key="seat-50" id="seat-50" r="9.964" cy="121.335" cx="325.14"/>,
|
<circle key="seat-50" id="seat-50" r="12" cy="74.003" cx="327.303" />,
|
||||||
<circle key="seat-51" id="seat-51" r="9.964" cy="74.003" cx="327.303"/>,
|
<circle key="seat-51" id="seat-51" r="12" cy="121.335" cx="325.14" />,
|
||||||
<circle key="seat-52" id="seat-52" r="9.964" cy="22.948" cx="328.246"/>,
|
<circle key="seat-52" id="seat-52" r="12" cy="167.585" cx="321.759" />,
|
||||||
<circle key="seat-53" id="seat-53" r="9.964" cy="183.347" cx="343.194"/>,
|
<circle key="seat-53" id="seat-53" r="12" cy="39.969" cx="380.649" />,
|
||||||
<circle key="seat-54" id="seat-54" r="9.964" cy="132.154" cx="348.129"/>,
|
<circle key="seat-54" id="seat-54" r="12" cy="82.117" cx="352.187" />,
|
||||||
<circle key="seat-55" id="seat-55" r="9.964" cy="82.117" cx="352.187"/>,
|
<circle key="seat-55" id="seat-55" r="12" cy="132.154" cx="348.129" />,
|
||||||
<circle key="seat-56" id="seat-56" r="9.964" cy="30.215" cx="354.639"/>,
|
<circle key="seat-56" id="seat-56" r="12" cy="183.347" cx="343.194" />,
|
||||||
<circle key="seat-57" id="seat-57" r="9.964" cy="145.407" cx="368.956"/>,
|
<circle key="seat-57" id="seat-57" r="12" cy="51.554" cx="404.387" />,
|
||||||
<circle key="seat-58" id="seat-58" r="9.964" cy="93.477" cx="375.988"/>,
|
<circle key="seat-58" id="seat-58" r="12" cy="93.477" cx="375.988" />,
|
||||||
<circle key="seat-59" id="seat-59" r="9.964" cy="39.969" cx="380.649"/>,
|
<circle key="seat-59" id="seat-59" r="12" cy="145.407" cx="368.956" />,
|
||||||
<circle key="seat-60" id="seat-60" r="9.964" cy="163.733" cx="388.214"/>,
|
<circle key="seat-60" id="seat-60" r="12" cy="66.206" cx="426.902" />,
|
||||||
<circle key="seat-61" id="seat-61" r="9.964" cy="108.082" cx="398.166"/>,
|
<circle key="seat-61" id="seat-61" r="12" cy="108.082" cx="398.166" />,
|
||||||
<circle key="seat-62" id="seat-62" r="9.964" cy="51.554" cx="404.387"/>,
|
<circle key="seat-62" id="seat-62" r="12" cy="163.733" cx="388.214" />,
|
||||||
<circle key="seat-63" id="seat-63" r="9.964" cy="125.122" cx="416.829"/>,
|
<circle key="seat-63" id="seat-63" r="12" cy="82.48" cx="447.457" />,
|
||||||
<circle key="seat-64" id="seat-64" r="9.964" cy="66.206" cx="426.902"/>,
|
<circle key="seat-64" id="seat-64" r="12" cy="125.122" cx="416.829" />,
|
||||||
<circle key="seat-65" id="seat-65" r="9.964" cy="143.999" cx="433.508"/>,
|
<circle key="seat-65" id="seat-65" r="12" cy="102.267" cx="466.325" />,
|
||||||
<circle key="seat-66" id="seat-66" r="9.964" cy="82.48" cx="447.457"/>,
|
<circle key="seat-66" id="seat-66" r="12" cy="143.999" cx="433.508" />,
|
||||||
<circle key="seat-67" id="seat-67" r="9.964" cy="102.267" cx="466.325"/>,
|
<circle key="seat-67" id="seat-67" r="12" cy="123.093" cx="481.494" />,
|
||||||
<circle key="seat-68" id="seat-68" r="9.964" cy="123.093" cx="481.494"/>,
|
<circle key="seat-68" id="seat-68" r="12" cy="-289.68" cx="440.983" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-69" id="seat-69" r="9.964" cy="-147.065" cx="400.833" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-69" id="seat-69" r="12" cy="-239.296" cx="426.798" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-70" id="seat-70" r="9.964" cy="-188.912" cx="412.614" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-70" id="seat-70" r="12" cy="-188.912" cx="412.614" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-71" id="seat-71" r="9.964" cy="-239.296" cx="426.798" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-71" id="seat-71" r="12" cy="-147.065" cx="400.833" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-72" id="seat-72" r="9.964" cy="-289.68" cx="440.983" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-72" id="seat-72" r="12" cy="-281.375" cx="467.381" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-73" id="seat-73" r="9.964" cy="-135.696" cx="424.411" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-73" id="seat-73" r="12" cy="-229.58" cx="452.656" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-74" id="seat-74" r="9.964" cy="-180.651" cx="437.369" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-74" id="seat-74" r="12" cy="-180.651" cx="437.369" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-75" id="seat-75" r="9.964" cy="-229.58" cx="452.656" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-75" id="seat-75" r="12" cy="-135.696" cx="424.411" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-76" id="seat-76" r="9.964" cy="-281.375" cx="467.381" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-76" id="seat-76" r="12" cy="-269.967" cx="491.592" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-77" id="seat-77" r="9.964" cy="-119.414" cx="445.127" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-77" id="seat-77" r="12" cy="-217.964" cx="475.026" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-78" id="seat-78" r="9.964" cy="-167.771" cx="459.741" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-78" id="seat-78" r="12" cy="-167.771" cx="459.741" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-79" id="seat-79" r="9.964" cy="-217.964" cx="475.026" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-79" id="seat-79" r="12" cy="-119.414" cx="445.127" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-80" id="seat-80" r="9.964" cy="-269.967" cx="491.592" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-80" id="seat-80" r="12" cy="-257.568" cx="513.597" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-81" id="seat-81" r="9.964" cy="-152.609" cx="478.289" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-81" id="seat-81" r="12" cy="-204.059" cx="496.265" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-82" id="seat-82" r="9.964" cy="-204.059" cx="496.265" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-82" id="seat-82" r="12" cy="-152.609" cx="478.289" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-83" id="seat-83" r="9.964" cy="-257.568" cx="513.597" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-83" id="seat-83" r="12" cy="-243.076" cx="533.889" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-84" id="seat-84" r="9.964" cy="-136.74" cx="497.701" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-84" id="seat-84" r="12" cy="-189.049" cx="514.627" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-85" id="seat-85" r="9.964" cy="-189.049" cx="514.627" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-85" id="seat-85" r="12" cy="-136.74" cx="497.701" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-86" id="seat-86" r="9.964" cy="-243.076" cx="533.889" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-86" id="seat-86" r="12" cy="-227.994" cx="554.048" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-87" id="seat-87" r="9.964" cy="-173.798" cx="533.284" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-87" id="seat-87" r="12" cy="-173.798" cx="533.284" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-88" id="seat-88" r="9.964" cy="-227.994" cx="554.048" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-88" id="seat-88" r="12" cy="-212.968" cx="572.857" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-89" id="seat-89" r="9.964" cy="-158.909" cx="551.496" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-89" id="seat-89" r="12" cy="-158.909" cx="551.496" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-90" id="seat-90" r="9.964" cy="-212.968" cx="572.857" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-90" id="seat-90" r="12" cy="-197.942" cx="591.665" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)" />,
|
||||||
<circle key="seat-91" id="seat-91" r="9.964" cy="-197.942" cx="591.665" transform="matrix(0.632908, 0.774227, -0.774227, 0.632908, 0, 0)"/>,
|
<circle key="seat-91" id="seat-91" r="12" cy="308.5" cx="-275.898" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
];
|
];
|
||||||
|
|
||||||
const renderedElements = seatElements.map((child, index) => {
|
// Creamos una copia mutable de los datos de asientos para poder modificarla.
|
||||||
// Si no hay datos para este asiento (ej. en la cámara de senadores que tiene menos de 92 bancas)
|
const finalSeatData = [...seatData];
|
||||||
// lo pintamos de gris.
|
|
||||||
if (index >= seatData.length) {
|
// Si hay un presidente y su partido tiene bancas, le quitamos una para asignarla.
|
||||||
return React.cloneElement(child, {
|
if (presidenteBancada && presidenteBancada.color) {
|
||||||
fill: '#E0E0E0',
|
// Encontramos el índice del último asiento que pertenece al partido del presidente.
|
||||||
stroke: '#ffffff',
|
const lastSeatIndex = finalSeatData.map(s => s.color).lastIndexOf(presidenteBancada.color);
|
||||||
strokeWidth: 1.5,
|
|
||||||
});
|
if (lastSeatIndex !== -1) {
|
||||||
|
// Eliminamos ese asiento de la lista de asientos electorales.
|
||||||
|
finalSeatData.splice(lastSeatIndex, 1);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const seat = seatData[index];
|
const renderedElements = seatElements.map((child, index) => {
|
||||||
const patternId = `stripes-${seat.color.replace('#', '')}`;
|
// El asiento presidencial sigue siendo un caso especial
|
||||||
|
if (index === PRESIDENTE_SEAT_INDEX) {
|
||||||
return React.cloneElement(child, {
|
return React.cloneElement(child, {
|
||||||
fill: seat.isEnJuego ? `url(#${patternId})` : seat.color,
|
fill: presidenteBancada?.color || '#A9A9A9',
|
||||||
stroke: '#ffffff',
|
stroke: '#000000',
|
||||||
strokeWidth: 1.5,
|
strokeWidth: 2,
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// La lógica ahora es simple: el asiento en el índice X del SVG
|
||||||
|
// corresponde al asiento en el índice X de los datos.
|
||||||
|
const seat = seatData[index];
|
||||||
|
|
||||||
|
if (!seat) {
|
||||||
|
return React.cloneElement(child, { fill: '#E0E0E0', stroke: '#ffffff', strokeWidth: 1.5 });
|
||||||
|
}
|
||||||
|
|
||||||
|
return React.cloneElement(child, {
|
||||||
|
fill: seat.color,
|
||||||
|
stroke: '#ffffff',
|
||||||
|
strokeWidth: 1.5,
|
||||||
|
'data-tooltip-id': seat.ocupante ? 'seat-tooltip' : undefined,
|
||||||
|
'data-tooltip-html': seat.ocupante
|
||||||
|
? `<div class="seat-tooltip"><img src="${seat.ocupante.fotoUrl || '/default-avatar.png'}" alt="${seat.ocupante.nombreOcupante}" /><p>${seat.ocupante.nombreOcupante}</p></div>`
|
||||||
|
: undefined,
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<svg viewBox="0 0 550 375" width={size} height={size * (375 / 550)} style={{ display: 'block', margin: 'auto' }}>
|
<svg viewBox="0 0 550 375" width={size} height={size * (375 / 550)} style={{ display: 'block', margin: 'auto' }}>
|
||||||
|
|||||||
@@ -1,89 +1,121 @@
|
|||||||
// src/components/SenateLayout.tsx
|
// src/components/SenateLayout.tsx
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
// Las interfaces son las mismas que para el otro layout
|
// Interfaces
|
||||||
interface SeatFillData {
|
interface SeatFillData {
|
||||||
color: string;
|
color: string;
|
||||||
isEnJuego: boolean;
|
// Añadimos la propiedad opcional 'ocupante'
|
||||||
|
ocupante?: {
|
||||||
|
nombreOcupante: string;
|
||||||
|
fotoUrl: string | null;
|
||||||
|
} | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface SenateLayoutProps {
|
interface SenateLayoutProps {
|
||||||
seatData: SeatFillData[];
|
seatData: SeatFillData[];
|
||||||
size?: number;
|
size?: number;
|
||||||
|
presidenteBancada: { color: string | null } | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const PRESIDENTE_SEAT_INDEX = 45; // El último asiento (índice 45 de 46)
|
||||||
|
|
||||||
export const SenateLayout: React.FC<SenateLayoutProps> = ({
|
export const SenateLayout: React.FC<SenateLayoutProps> = ({
|
||||||
seatData,
|
seatData,
|
||||||
size = 400,
|
size = 400,
|
||||||
|
presidenteBancada,
|
||||||
}) => {
|
}) => {
|
||||||
const uniqueColors = [...new Set(seatData.map(d => d.color).filter(Boolean))];
|
const uniqueColors = [...new Set(seatData.map(d => d.color).filter(Boolean))];
|
||||||
|
|
||||||
// Plantilla estática de los 46 asientos del Senado, ordenados para el llenado por columnas.
|
// --- NUEVO ARRAY DE ELEMENTOS ORDENADO PARA EL SENADO ---
|
||||||
const seatElements = [
|
const seatElements = [
|
||||||
<circle key="senate-seat-0" id="senate-seat-0" r="8" cy="354.956" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-0" id="senate-seat-0" r="9" cy="354.956" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-1" id="senate-seat-1" r="8" cy="331.318" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-1" id="senate-seat-1" r="9" cy="354.956" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-2" id="senate-seat-2" r="8" cy="307.598" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-2" id="senate-seat-2" r="9" cy="331.318" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-3" id="senate-seat-3" r="8" cy="285.358" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-3" id="senate-seat-3" r="9" cy="333.318" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-4" id="senate-seat-4" r="8" cy="261.241" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-4" id="senate-seat-4" r="9" cy="307.598" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-5" id="senate-seat-5" r="8" cy="354.956" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-5" id="senate-seat-5" r="9" cy="312.598" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-6" id="senate-seat-6" r="8" cy="333.318" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-6" id="senate-seat-6" r="9" cy="285.358" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-7" id="senate-seat-7" r="8" cy="312.598" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-7" id="senate-seat-7" r="9" cy="292.358" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-8" id="senate-seat-8" r="8" cy="292.358" cx="-164.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-8" id="senate-seat-8" r="9" cy="292.358" cx="-206.672" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-9" id="senate-seat-9" r="8" cy="269.241" cx="-165.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-9" id="senate-seat-9" r="9" cy="261.241" cx="-121.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-10" id="senate-seat-10" r="8" cy="246.521" cx="-170.309" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-10" id="senate-seat-10" r="9" cy="269.241" cx="-165.933" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-11" id="senate-seat-11" r="8" cy="229.407" cx="-183.766" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-11" id="senate-seat-11" r="9" cy="268.057" cx="-208.672" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-12" id="senate-seat-12" r="8" cy="217.294" cx="-201.175" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-12" id="senate-seat-12" r="9" cy="184.514" cx="327.2" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 488.237, 84.441)" />,
|
||||||
<circle key="senate-seat-13" id="senate-seat-13" r="8" cy="268.057" cx="-208.672" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-13" id="senate-seat-13" r="9" cy="246.521" cx="-170.309" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-14" id="senate-seat-14" r="8" cy="292.358" cx="-206.672" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-14" id="senate-seat-14" r="9" cy="184.514" cx="327.2" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 507.83, 65.575)" />,
|
||||||
<circle key="senate-seat-15" id="senate-seat-15" r="8" cy="211.882" cx="-223.172" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-15" id="senate-seat-15" r="9" cy="229.407" cx="-183.766" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-16" id="senate-seat-16" r="8" cy="252.557" cx="-227.172" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
<circle key="senate-seat-16" id="senate-seat-16" r="9" cy="184.514" cx="327.2" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 528.776, 52.17)" />,
|
||||||
<circle key="senate-seat-17" id="senate-seat-17" r="8" cy="347.619" cx="243.841" />,
|
<circle key="senate-seat-17" id="senate-seat-17" r="9" cy="217.294" cx="-201.175" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-18" id="senate-seat-18" r="8" cy="252.557" cx="258.729" />,
|
<circle key="senate-seat-18" id="senate-seat-18" r="9" cy="252.557" cx="-227.172" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-19" id="senate-seat-19" r="8" cy="211.882" cx="262.728" />,
|
<circle key="senate-seat-19" id="senate-seat-19" r="9" cy="170.401" cx="311.791" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 535.427, 55.561)" />,
|
||||||
<circle key="senate-seat-20" id="senate-seat-20" r="8" cy="268.057" cx="277.228" />,
|
<circle key="senate-seat-20" id="senate-seat-20" r="9" cy="211.882" cx="-223.172" transform="matrix(-1, 0, 0, 1, 0, 0)" />,
|
||||||
<circle key="senate-seat-21" id="senate-seat-21" r="8" cy="292.358" cx="279.228" />,
|
<circle key="senate-seat-21" id="senate-seat-21" r="9" cy="159.989" cx="295.143" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 540.544, 61.56)" />,
|
||||||
<circle key="senate-seat-22" id="senate-seat-22" r="8" cy="217.294" cx="284.726" />,
|
<circle key="senate-seat-22" id="senate-seat-22" r="9" cy="159.989" cx="295.143" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -54.66, 61.555)" />,
|
||||||
<circle key="senate-seat-23" id="senate-seat-23" r="8" cy="159.989" cx="295.143" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -54.66, 61.555)" />,
|
<circle key="senate-seat-23" id="senate-seat-23" r="9" cy="211.882" cx="262.728" />,
|
||||||
<circle key="senate-seat-24" id="senate-seat-24" r="8" cy="229.407" cx="302.134" />,
|
<circle key="senate-seat-24" id="senate-seat-24" r="9" cy="252.557" cx="258.729" />,
|
||||||
<circle key="senate-seat-25" id="senate-seat-25" r="8" cy="170.401" cx="311.791" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -49.543, 55.556)" />,
|
<circle key="senate-seat-25" id="senate-seat-25" r="9" cy="170.401" cx="311.791" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -49.543, 55.556)" />,
|
||||||
<circle key="senate-seat-26" id="senate-seat-26" r="8" cy="246.521" cx="315.591" />,
|
<circle key="senate-seat-26" id="senate-seat-26" r="9" cy="217.294" cx="284.726" />,
|
||||||
<circle key="senate-seat-27" id="senate-seat-27" r="8" cy="269.241" cx="319.968" />,
|
<circle key="senate-seat-27" id="senate-seat-27" r="9" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -42.892, 52.164)" />,
|
||||||
<circle key="senate-seat-28" id="senate-seat-28" r="8" cy="292.358" cx="320.968" />,
|
<circle key="senate-seat-28" id="senate-seat-28" r="9" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -21.946, 65.569)" />,
|
||||||
<circle key="senate-seat-29" id="senate-seat-29" r="8" cy="312.598" cx="320.968" />,
|
<circle key="senate-seat-29" id="senate-seat-29" r="9" cy="229.407" cx="302.134" />,
|
||||||
<circle key="senate-seat-30" id="senate-seat-30" r="8" cy="333.318" cx="320.968" />,
|
<circle key="senate-seat-30" id="senate-seat-30" r="9" cy="268.057" cx="277.228" />,
|
||||||
<circle key="senate-seat-31" id="senate-seat-31" r="8" cy="354.956" cx="320.968" />,
|
<circle key="senate-seat-31" id="senate-seat-31" r="9" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -2.353, 84.436)" />,
|
||||||
<circle key="senate-seat-32" id="senate-seat-32" r="8" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -42.892, 52.164)" />,
|
<circle key="senate-seat-32" id="senate-seat-32" r="9" cy="246.521" cx="315.591" />,
|
||||||
<circle key="senate-seat-33" id="senate-seat-33" r="8" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -21.946, 65.569)" />,
|
<circle key="senate-seat-33" id="senate-seat-33" r="9" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, 8.933, 107.941)" />,
|
||||||
<circle key="senate-seat-34" id="senate-seat-34" r="8" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, -2.353, 84.436)" />,
|
<circle key="senate-seat-34" id="senate-seat-34" r="9" cy="269.241" cx="319.968" />,
|
||||||
<circle key="senate-seat-35" id="senate-seat-35" r="8" cy="184.514" cx="327.2" transform="matrix(0.986454, -0.16404, 0.16404, 0.986454, 8.933, 107.941)" />,
|
<circle key="senate-seat-35" id="senate-seat-35" r="9" cy="292.358" cx="279.228" />,
|
||||||
<circle key="senate-seat-36" id="senate-seat-36" r="8" cy="261.241" cx="363.968" />,
|
<circle key="senate-seat-36" id="senate-seat-36" r="9" cy="261.241" cx="363.968" />,
|
||||||
<circle key="senate-seat-37" id="senate-seat-37" r="8" cy="285.358" cx="363.968" />,
|
<circle key="senate-seat-37" id="senate-seat-37" r="9" cy="292.358" cx="320.968" />,
|
||||||
<circle key="senate-seat-38" id="senate-seat-38" r="8" cy="307.598" cx="363.968" />,
|
<circle key="senate-seat-38" id="senate-seat-38" r="9" cy="285.358" cx="363.968" />,
|
||||||
<circle key="senate-seat-39" id="senate-seat-39" r="8" cy="331.318" cx="363.968" />,
|
<circle key="senate-seat-39" id="senate-seat-39" r="9" cy="312.598" cx="320.968" />,
|
||||||
<circle key="senate-seat-40" id="senate-seat-40" r="8" cy="354.956" cx="363.968" />,
|
<circle key="senate-seat-40" id="senate-seat-40" r="9" cy="307.598" cx="363.968" />,
|
||||||
<circle key="senate-seat-41" id="senate-seat-41" r="8" cy="159.989" cx="295.143" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 540.544, 61.56)" />,
|
<circle key="senate-seat-41" id="senate-seat-41" r="9" cy="333.318" cx="320.968" />,
|
||||||
<circle key="senate-seat-42" id="senate-seat-42" r="8" cy="170.401" cx="311.791" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 535.427, 55.561)" />,
|
<circle key="senate-seat-42" id="senate-seat-42" r="9" cy="331.318" cx="363.968" />,
|
||||||
<circle key="senate-seat-43" id="senate-seat-43" r="8" cy="184.514" cx="327.2" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 528.776, 52.17)" />,
|
<circle key="senate-seat-43" id="senate-seat-43" r="9" cy="354.956" cx="320.968" />,
|
||||||
<circle key="senate-seat-44" id="senate-seat-44" r="8" cy="184.514" cx="327.2" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 507.83, 65.575)" />,
|
<circle key="senate-seat-44" id="senate-seat-44" r="9" cy="354.956" cx="363.968" />,
|
||||||
<circle key="senate-seat-45" id="senate-seat-45" r="8" cy="184.514" cx="327.2" transform="matrix(-0.986454, -0.16404, -0.16404, 0.986454, 488.237, 84.441)" />,
|
<circle key="senate-seat-45" id="senate-seat-45" r="9" cy="347.619" cx="243.841" />,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
// Creamos una copia mutable de los datos de asientos para poder modificarla.
|
||||||
|
const finalSeatData = [...seatData];
|
||||||
|
|
||||||
|
// Si hay un presidente y su partido tiene bancas, le quitamos una para asignarla.
|
||||||
|
if (presidenteBancada && presidenteBancada.color) {
|
||||||
|
// Encontramos el índice del último asiento que pertenece al partido del presidente.
|
||||||
|
const lastSeatIndex = finalSeatData.map(s => s.color).lastIndexOf(presidenteBancada.color);
|
||||||
|
|
||||||
|
if (lastSeatIndex !== -1) {
|
||||||
|
// Eliminamos ese asiento de la lista de asientos electorales.
|
||||||
|
finalSeatData.splice(lastSeatIndex, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const renderedElements = seatElements.map((child, index) => {
|
const renderedElements = seatElements.map((child, index) => {
|
||||||
if (index >= seatData.length) {
|
// El asiento presidencial sigue siendo un caso especial
|
||||||
|
if (index === PRESIDENTE_SEAT_INDEX) {
|
||||||
return React.cloneElement(child, {
|
return React.cloneElement(child, {
|
||||||
fill: '#E0E0E0',
|
fill: presidenteBancada?.color || '#A9A9A9',
|
||||||
stroke: '#ffffff',
|
stroke: '#000000',
|
||||||
strokeWidth: 1.5,
|
strokeWidth: 2,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// La lógica ahora es simple: el asiento en el índice X del SVG
|
||||||
|
// corresponde al asiento en el índice X de los datos.
|
||||||
const seat = seatData[index];
|
const seat = seatData[index];
|
||||||
const patternId = `stripes-${seat.color.replace('#', '')}`;
|
|
||||||
|
if (!seat) {
|
||||||
|
return React.cloneElement(child, { fill: '#E0E0E0', stroke: '#ffffff', strokeWidth: 1.5 });
|
||||||
|
}
|
||||||
|
|
||||||
return React.cloneElement(child, {
|
return React.cloneElement(child, {
|
||||||
fill: seat.isEnJuego ? `url(#${patternId})` : seat.color,
|
fill: seat.color,
|
||||||
stroke: '#ffffff',
|
stroke: '#ffffff',
|
||||||
strokeWidth: 1.5,
|
strokeWidth: 1.5,
|
||||||
|
'data-tooltip-id': seat.ocupante ? 'seat-tooltip' : undefined,
|
||||||
|
'data-tooltip-html': seat.ocupante
|
||||||
|
? `<div class="seat-tooltip"><img src="${seat.ocupante.fotoUrl || '/default-avatar.png'}" alt="${seat.ocupante.nombreOcupante}" /><p>${seat.ocupante.nombreOcupante}</p></div>`
|
||||||
|
: undefined,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -51,7 +51,6 @@ export const TelegramaWidget = () => {
|
|||||||
}
|
}
|
||||||
}, [selectedSeccion]);
|
}, [selectedSeccion]);
|
||||||
|
|
||||||
// Y así sucesivamente para los demás filtros...
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedMunicipio) {
|
if (selectedMunicipio) {
|
||||||
setCircuitos([]); setEstablecimientos([]); setMesas([]);
|
setCircuitos([]); setEstablecimientos([]); setMesas([]);
|
||||||
|
|||||||
181
Elecciones-Web/src/Elecciones.Api/Controllers/AdminController.cs
Normal file
181
Elecciones-Web/src/Elecciones.Api/Controllers/AdminController.cs
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
// src/Elecciones.Api/Controllers/AdminController.cs
|
||||||
|
using Elecciones.Database;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Elecciones.Core.DTOs.ApiRequests;
|
||||||
|
using Elecciones.Database.Entities;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Elecciones.Core.Enums;
|
||||||
|
|
||||||
|
namespace Elecciones.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[Authorize]
|
||||||
|
public class AdminController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly EleccionesDbContext _dbContext;
|
||||||
|
private readonly ILogger<AdminController> _logger;
|
||||||
|
|
||||||
|
public AdminController(EleccionesDbContext dbContext, ILogger<AdminController> logger)
|
||||||
|
{
|
||||||
|
_dbContext = dbContext;
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Endpoint para obtener todas las agrupaciones para el panel de admin
|
||||||
|
[HttpGet("agrupaciones")]
|
||||||
|
public async Task<IActionResult> GetAgrupaciones()
|
||||||
|
{
|
||||||
|
var agrupaciones = await _dbContext.AgrupacionesPoliticas
|
||||||
|
.AsNoTracking()
|
||||||
|
.OrderBy(a => a.Nombre)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Ok(agrupaciones);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("agrupaciones/{id}")]
|
||||||
|
public async Task<IActionResult> UpdateAgrupacion(string id, [FromBody] UpdateAgrupacionDto agrupacionDto)
|
||||||
|
{
|
||||||
|
// Buscamos la agrupación en la base de datos por su ID.
|
||||||
|
var agrupacion = await _dbContext.AgrupacionesPoliticas.FindAsync(id);
|
||||||
|
|
||||||
|
if (agrupacion == null)
|
||||||
|
{
|
||||||
|
// Si no existe, devolvemos un error 404 Not Found.
|
||||||
|
return NotFound(new { message = $"No se encontró la agrupación con ID {id}" });
|
||||||
|
}
|
||||||
|
|
||||||
|
// Actualizamos las propiedades de la entidad con los valores del DTO.
|
||||||
|
agrupacion.NombreCorto = agrupacionDto.NombreCorto;
|
||||||
|
agrupacion.Color = agrupacionDto.Color;
|
||||||
|
agrupacion.LogoUrl = agrupacionDto.LogoUrl;
|
||||||
|
|
||||||
|
// Guardamos los cambios en la base de datos.
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
_logger.LogInformation("Se actualizó la agrupación: {Id}", id);
|
||||||
|
|
||||||
|
// Devolvemos una respuesta 204 No Content, que es el estándar para un PUT exitoso sin devolver datos.
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("agrupaciones/orden-diputados")]
|
||||||
|
public async Task<IActionResult> UpdateDiputadosOrden([FromBody] List<string> idsAgrupacionesOrdenadas)
|
||||||
|
{
|
||||||
|
// Reseteamos solo el orden de diputados
|
||||||
|
await _dbContext.AgrupacionesPoliticas.ExecuteUpdateAsync(s => s.SetProperty(a => a.OrdenDiputados, (int?)null));
|
||||||
|
|
||||||
|
for (int i = 0; i < idsAgrupacionesOrdenadas.Count; i++)
|
||||||
|
{
|
||||||
|
var agrupacion = await _dbContext.AgrupacionesPoliticas.FindAsync(idsAgrupacionesOrdenadas[i]);
|
||||||
|
if (agrupacion != null) agrupacion.OrdenDiputados = i + 1;
|
||||||
|
}
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("agrupaciones/orden-senadores")]
|
||||||
|
public async Task<IActionResult> UpdateSenadoresOrden([FromBody] List<string> idsAgrupacionesOrdenadas)
|
||||||
|
{
|
||||||
|
// Reseteamos solo el orden de senadores
|
||||||
|
await _dbContext.AgrupacionesPoliticas.ExecuteUpdateAsync(s => s.SetProperty(a => a.OrdenSenadores, (int?)null));
|
||||||
|
|
||||||
|
for (int i = 0; i < idsAgrupacionesOrdenadas.Count; i++)
|
||||||
|
{
|
||||||
|
var agrupacion = await _dbContext.AgrupacionesPoliticas.FindAsync(idsAgrupacionesOrdenadas[i]);
|
||||||
|
if (agrupacion != null) agrupacion.OrdenSenadores = i + 1;
|
||||||
|
}
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
// LEER todas las configuraciones
|
||||||
|
[HttpGet("configuracion")]
|
||||||
|
public async Task<IActionResult> GetConfiguracion()
|
||||||
|
{
|
||||||
|
var configs = await _dbContext.Configuraciones.AsNoTracking().ToListAsync();
|
||||||
|
// Devolvemos un diccionario para que sea fácil de consumir en el frontend
|
||||||
|
return Ok(configs.ToDictionary(c => c.Clave, c => c.Valor));
|
||||||
|
}
|
||||||
|
|
||||||
|
// GUARDAR un conjunto de configuraciones
|
||||||
|
[HttpPut("configuracion")]
|
||||||
|
public async Task<IActionResult> UpdateConfiguracion([FromBody] Dictionary<string, string> nuevasConfiguraciones)
|
||||||
|
{
|
||||||
|
foreach (var kvp in nuevasConfiguraciones)
|
||||||
|
{
|
||||||
|
var config = await _dbContext.Configuraciones.FindAsync(kvp.Key);
|
||||||
|
if (config == null)
|
||||||
|
{
|
||||||
|
// Si no existe, la creamos
|
||||||
|
_dbContext.Configuraciones.Add(new Configuracion { Clave = kvp.Key, Valor = kvp.Value });
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Si existe, la actualizamos
|
||||||
|
config.Valor = kvp.Value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
|
||||||
|
// LEER: Obtener todas las bancadas para una cámara, con su partido y ocupante actual
|
||||||
|
[HttpGet("bancadas/{camara}")]
|
||||||
|
public async Task<IActionResult> GetBancadas(TipoCamara camara)
|
||||||
|
{
|
||||||
|
var bancadas = await _dbContext.Bancadas
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(b => b.AgrupacionPolitica)
|
||||||
|
.Include(b => b.Ocupante)
|
||||||
|
.Where(b => b.Camara == camara)
|
||||||
|
.OrderBy(b => b.Id) // Ordenar por ID para consistencia
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Ok(bancadas);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ACTUALIZAR: Asignar un partido y/o un ocupante a una bancada específica
|
||||||
|
[HttpPut("bancadas/{bancadaId}")]
|
||||||
|
public async Task<IActionResult> UpdateBancada(int bancadaId, [FromBody] UpdateBancadaDto dto)
|
||||||
|
{
|
||||||
|
var bancada = await _dbContext.Bancadas
|
||||||
|
.Include(b => b.Ocupante)
|
||||||
|
.FirstOrDefaultAsync(b => b.Id == bancadaId);
|
||||||
|
|
||||||
|
if (bancada == null)
|
||||||
|
{
|
||||||
|
return NotFound(new { message = "La bancada especificada no existe." });
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1. Actualizar la agrupación de la bancada
|
||||||
|
bancada.AgrupacionPoliticaId = dto.AgrupacionPoliticaId;
|
||||||
|
|
||||||
|
// 2. Lógica de "Upsert" (Update/Insert/Delete) para el ocupante
|
||||||
|
if (string.IsNullOrEmpty(dto.NombreOcupante))
|
||||||
|
{
|
||||||
|
// Si no se envía nombre, se elimina el ocupante existente
|
||||||
|
if (bancada.Ocupante != null)
|
||||||
|
{
|
||||||
|
_dbContext.OcupantesBancas.Remove(bancada.Ocupante);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Si se envía un nombre, se crea o actualiza el ocupante
|
||||||
|
if (bancada.Ocupante == null)
|
||||||
|
{
|
||||||
|
bancada.Ocupante = new OcupanteBanca(); // Crea uno nuevo si no existía
|
||||||
|
}
|
||||||
|
bancada.Ocupante.NombreOcupante = dto.NombreOcupante;
|
||||||
|
bancada.Ocupante.FotoUrl = dto.FotoUrl;
|
||||||
|
bancada.Ocupante.Periodo = dto.Periodo;
|
||||||
|
}
|
||||||
|
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
_logger.LogInformation("Se actualizó la bancada con ID: {BancadaId}", bancadaId);
|
||||||
|
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,64 @@
|
|||||||
|
using Elecciones.Core.Services;
|
||||||
|
using Elecciones.Database;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Elecciones.Api.Controllers;
|
||||||
|
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
public class AuthController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly EleccionesDbContext _context;
|
||||||
|
private readonly IPasswordHasher _passwordHasher;
|
||||||
|
private readonly IConfiguration _configuration;
|
||||||
|
|
||||||
|
public AuthController(EleccionesDbContext context, IPasswordHasher passwordHasher, IConfiguration configuration)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_passwordHasher = passwordHasher;
|
||||||
|
_configuration = configuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public record LoginRequest(string Username, string Password);
|
||||||
|
|
||||||
|
[HttpPost("login")]
|
||||||
|
public async Task<IActionResult> Login([FromBody] LoginRequest loginRequest)
|
||||||
|
{
|
||||||
|
var user = await _context.AdminUsers
|
||||||
|
.FirstOrDefaultAsync(u => u.Username == loginRequest.Username);
|
||||||
|
|
||||||
|
if (user == null || !_passwordHasher.VerifyPassword(loginRequest.Password, user.PasswordHash, user.PasswordSalt))
|
||||||
|
{
|
||||||
|
return Unauthorized(new { message = "Credenciales inválidas." });
|
||||||
|
}
|
||||||
|
|
||||||
|
var token = GenerateJwtToken(user);
|
||||||
|
return Ok(new { token });
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GenerateJwtToken(Database.Entities.AdminUser user)
|
||||||
|
{
|
||||||
|
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]!));
|
||||||
|
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
|
||||||
|
|
||||||
|
var claims = new[]
|
||||||
|
{
|
||||||
|
new Claim(JwtRegisteredClaimNames.Sub, user.Username),
|
||||||
|
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
|
||||||
|
};
|
||||||
|
|
||||||
|
var token = new JwtSecurityToken(
|
||||||
|
issuer: _configuration["Jwt:Issuer"],
|
||||||
|
audience: _configuration["Jwt:Audience"],
|
||||||
|
claims: claims,
|
||||||
|
expires: DateTime.UtcNow.AddHours(8), // El token expira en 8 horas
|
||||||
|
signingCredentials: credentials);
|
||||||
|
|
||||||
|
return new JwtSecurityTokenHandler().WriteToken(token);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,8 +2,6 @@ using Elecciones.Core.DTOs.ApiResponses;
|
|||||||
using Elecciones.Database;
|
using Elecciones.Database;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Elecciones.Api.Controllers;
|
namespace Elecciones.Api.Controllers;
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
// src/Elecciones.Api/Controllers/ResultadosController.cs
|
// src/Elecciones.Api/Controllers/ResultadosController.cs
|
||||||
using Elecciones.Core.DTOs.ApiResponses;
|
using Elecciones.Core.DTOs.ApiResponses;
|
||||||
using Elecciones.Database;
|
using Elecciones.Database;
|
||||||
|
using Elecciones.Database.Entities;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Elecciones.Core.DTOs.Configuration;
|
|
||||||
|
|
||||||
namespace Elecciones.Api.Controllers;
|
namespace Elecciones.Api.Controllers;
|
||||||
|
|
||||||
@@ -208,28 +204,23 @@ public class ResultadosController : ControllerBase
|
|||||||
});
|
});
|
||||||
|
|
||||||
var resultadosGanadores = await _dbContext.ResultadosVotos
|
var resultadosGanadores = await _dbContext.ResultadosVotos
|
||||||
.Join(
|
.Join(
|
||||||
maxVotosPorAmbito,
|
maxVotosPorAmbito,
|
||||||
voto => new { AmbitoId = voto.AmbitoGeograficoId, Votos = voto.CantidadVotos },
|
voto => new { AmbitoId = voto.AmbitoGeograficoId, Votos = voto.CantidadVotos },
|
||||||
max => new { AmbitoId = max.AmbitoId, Votos = max.MaxVotos },
|
max => new { AmbitoId = max.AmbitoId, Votos = max.MaxVotos },
|
||||||
(voto, max) => voto
|
(voto, max) => voto
|
||||||
)
|
)
|
||||||
.Include(rv => rv.AmbitoGeografico)
|
.Include(rv => rv.AmbitoGeografico)
|
||||||
.Where(rv => rv.AmbitoGeografico.NivelId == 30) // Aseguramos que solo sean los ámbitos de nivel 30
|
.Include(rv => rv.AgrupacionPolitica)
|
||||||
.Select(rv => new
|
.Where(rv => rv.AmbitoGeografico.NivelId == 30)
|
||||||
{
|
.Select(rv => new
|
||||||
// CORRECCIÓN CLAVE: Devolvemos los campos que el frontend necesita para funcionar.
|
{
|
||||||
|
AmbitoId = rv.AmbitoGeografico.Id,
|
||||||
// 1. El ID de la BD para hacer clic y pedir detalles.
|
DepartamentoNombre = rv.AmbitoGeografico.Nombre,
|
||||||
AmbitoId = rv.AmbitoGeografico.Id,
|
AgrupacionGanadoraId = rv.AgrupacionPoliticaId,
|
||||||
|
ColorGanador = rv.AgrupacionPolitica.Color
|
||||||
// 2. El NOMBRE del departamento/municipio para encontrar y colorear el polígono.
|
})
|
||||||
DepartamentoNombre = rv.AmbitoGeografico.Nombre,
|
.ToListAsync();
|
||||||
|
|
||||||
// 3. El ID del partido ganador.
|
|
||||||
AgrupacionGanadoraId = rv.AgrupacionPoliticaId
|
|
||||||
})
|
|
||||||
.ToListAsync();
|
|
||||||
|
|
||||||
return Ok(resultadosGanadores);
|
return Ok(resultadosGanadores);
|
||||||
}
|
}
|
||||||
@@ -298,18 +289,239 @@ public class ResultadosController : ControllerBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("composicion-congreso")]
|
[HttpGet("composicion-congreso")]
|
||||||
public IActionResult GetComposicionCongreso()
|
public async Task<IActionResult> GetComposicionCongreso()
|
||||||
{
|
{
|
||||||
// El framework .NET se encarga de leer appsettings.json y mapearlo a nuestras clases.
|
var config = await _dbContext.Configuraciones
|
||||||
var composicionConfig = _configuration.GetSection("ComposicionCongreso")
|
.AsNoTracking()
|
||||||
.Get<ComposicionCongresoConfig>();
|
.ToDictionaryAsync(c => c.Clave, c => c.Valor);
|
||||||
|
|
||||||
if (composicionConfig == null)
|
config.TryGetValue("UsarDatosDeBancadasOficiales", out var usarDatosOficialesValue);
|
||||||
|
bool usarDatosOficiales = usarDatosOficialesValue == "true";
|
||||||
|
|
||||||
|
if (usarDatosOficiales)
|
||||||
{
|
{
|
||||||
// Devolvemos un error si la sección no se encuentra en el archivo de configuración.
|
return await GetComposicionDesdeBancadasOficiales(config);
|
||||||
return NotFound("La configuración para la composición del congreso no fue encontrada.");
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return await GetComposicionDesdeProyecciones(config);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IActionResult> GetComposicionDesdeBancadasOficiales(Dictionary<string, string> config)
|
||||||
|
{
|
||||||
|
config.TryGetValue("MostrarOcupantes", out var mostrarOcupantesValue);
|
||||||
|
bool mostrarOcupantes = mostrarOcupantesValue == "true";
|
||||||
|
|
||||||
|
// Se declara la variable explícitamente como IQueryable<Bancada>
|
||||||
|
IQueryable<Bancada> bancadasQuery = _dbContext.Bancadas.AsNoTracking()
|
||||||
|
.Include(b => b.AgrupacionPolitica);
|
||||||
|
|
||||||
|
if (mostrarOcupantes)
|
||||||
|
{
|
||||||
|
// Ahora sí podemos añadir otro .Include() sin problemas de tipo
|
||||||
|
bancadasQuery = bancadasQuery.Include(b => b.Ocupante);
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(composicionConfig);
|
var bancadas = await bancadasQuery.ToListAsync();
|
||||||
|
|
||||||
|
// --- CAMBIO 2: Eliminar la carga manual de Ocupantes ---
|
||||||
|
// Ya no necesitamos 'ocupantesLookup'. Se puede borrar todo este bloque:
|
||||||
|
/*
|
||||||
|
var ocupantesLookup = new Dictionary<int, OcupanteBanca>();
|
||||||
|
if (mostrarOcupantes)
|
||||||
|
{
|
||||||
|
ocupantesLookup = (await _dbContext.OcupantesBancas.AsNoTracking()
|
||||||
|
.ToListAsync())
|
||||||
|
.ToDictionary(o => o.BancadaId);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
var bancasPorAgrupacion = bancadas
|
||||||
|
.Where(b => b.AgrupacionPoliticaId != null)
|
||||||
|
.GroupBy(b => new { b.AgrupacionPoliticaId, b.Camara })
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
Agrupacion = g.First().AgrupacionPolitica,
|
||||||
|
g.Key.Camara,
|
||||||
|
BancasTotales = g.Count()
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var presidenteDiputados = bancasPorAgrupacion
|
||||||
|
.Where(b => b.Camara == Core.Enums.TipoCamara.Diputados)
|
||||||
|
.OrderByDescending(b => b.BancasTotales)
|
||||||
|
.FirstOrDefault()?.Agrupacion;
|
||||||
|
|
||||||
|
config.TryGetValue("PresidenciaSenadores", out var idPartidoPresidenteSenadores);
|
||||||
|
var presidenteSenadores = await _dbContext.AgrupacionesPoliticas.FindAsync(idPartidoPresidenteSenadores);
|
||||||
|
|
||||||
|
object MapearPartidos(Core.Enums.TipoCamara camara)
|
||||||
|
{
|
||||||
|
// 1. Filtramos las bancadas que nos interesan (por cámara y que tengan partido).
|
||||||
|
var bancadasDeCamara = bancadas
|
||||||
|
.Where(b => b.Camara == camara && b.AgrupacionPolitica != null);
|
||||||
|
|
||||||
|
// 2. --- ¡EL CAMBIO CLAVE ESTÁ AQUÍ! ---
|
||||||
|
// Agrupamos por el ID de la Agrupación, no por el objeto.
|
||||||
|
// Esto garantiza que todas las bancadas del mismo partido terminen en el MISMO grupo.
|
||||||
|
var partidosDeCamara = bancadasDeCamara
|
||||||
|
.GroupBy(b => b.AgrupacionPolitica!.Id)
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
// La Agrupacion la podemos tomar del primer elemento del grupo,
|
||||||
|
// ya que todas las bancadas del grupo pertenecen al mismo partido.
|
||||||
|
Agrupacion = g.First().AgrupacionPolitica!,
|
||||||
|
// g ahora contiene la lista COMPLETA de bancadas para esta agrupación.
|
||||||
|
BancasDelPartido = g.ToList()
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. Ordenamos, como antes, pero ahora sobre una lista de grupos correcta.
|
||||||
|
var partidosOrdenados = (camara == Core.Enums.TipoCamara.Diputados)
|
||||||
|
? partidosDeCamara.OrderBy(p => p.Agrupacion.OrdenDiputados ?? 999)
|
||||||
|
: partidosDeCamara.OrderBy(p => p.Agrupacion.OrdenSenadores ?? 999);
|
||||||
|
|
||||||
|
// 4. Mapeamos al resultado final.
|
||||||
|
return partidosOrdenados
|
||||||
|
.ThenByDescending(p => p.BancasDelPartido.Count)
|
||||||
|
.Select(p =>
|
||||||
|
{
|
||||||
|
// Ahora 'p.BancasDelPartido' contiene TODAS las bancadas del partido (en tu caso, las 2).
|
||||||
|
// Cuando hagamos el .Select() aquí, recorrerá ambas y encontrará a los ocupantes.
|
||||||
|
var ocupantesDelPartido = p.BancasDelPartido
|
||||||
|
.Select(b => b.Ocupante)
|
||||||
|
.Where(o => o != null)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return new
|
||||||
|
{
|
||||||
|
p.Agrupacion.Id,
|
||||||
|
p.Agrupacion.Nombre,
|
||||||
|
p.Agrupacion.NombreCorto,
|
||||||
|
p.Agrupacion.Color,
|
||||||
|
BancasTotales = p.BancasDelPartido.Count,
|
||||||
|
// ¡Esta lista ahora debería contener a tus 2 ocupantes!
|
||||||
|
Ocupantes = mostrarOcupantes ? ocupantesDelPartido : new List<OcupanteBanca?>()
|
||||||
|
};
|
||||||
|
}).ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
// El resto del método permanece igual...
|
||||||
|
var diputados = new
|
||||||
|
{
|
||||||
|
CamaraNombre = "Cámara de Diputados",
|
||||||
|
TotalBancas = 92,
|
||||||
|
BancasEnJuego = 0,
|
||||||
|
Partidos = MapearPartidos(Core.Enums.TipoCamara.Diputados),
|
||||||
|
PresidenteBancada = presidenteDiputados != null ? new { presidenteDiputados.Color } : null
|
||||||
|
};
|
||||||
|
|
||||||
|
var senadores = new
|
||||||
|
{
|
||||||
|
CamaraNombre = "Cámara de Senadores",
|
||||||
|
TotalBancas = 46,
|
||||||
|
BancasEnJuego = 0,
|
||||||
|
Partidos = MapearPartidos(Core.Enums.TipoCamara.Senadores),
|
||||||
|
PresidenteBancada = presidenteSenadores != null ? new { presidenteSenadores.Color } : null
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(new { Diputados = diputados, Senadores = senadores });
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IActionResult> GetComposicionDesdeProyecciones(Dictionary<string, string> config)
|
||||||
|
{
|
||||||
|
var bancasPorAgrupacion = await _dbContext.ProyeccionesBancas
|
||||||
|
.AsNoTracking()
|
||||||
|
.GroupBy(p => new { p.AgrupacionPoliticaId, p.CategoriaId })
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
AgrupacionId = g.Key.AgrupacionPoliticaId,
|
||||||
|
CategoriaId = g.Key.CategoriaId,
|
||||||
|
BancasTotales = g.Sum(p => p.NroBancas)
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var todasAgrupaciones = await _dbContext.AgrupacionesPoliticas.AsNoTracking().ToDictionaryAsync(a => a.Id);
|
||||||
|
|
||||||
|
config.TryGetValue("PresidenciaSenadores", out var idPartidoPresidenteSenadores);
|
||||||
|
todasAgrupaciones.TryGetValue(idPartidoPresidenteSenadores ?? "", out var presidenteSenadores);
|
||||||
|
|
||||||
|
string? idPartidoPresidenteDiputados = bancasPorAgrupacion
|
||||||
|
.Where(b => b.CategoriaId == 6)
|
||||||
|
.OrderByDescending(b => b.BancasTotales)
|
||||||
|
.FirstOrDefault()?.AgrupacionId;
|
||||||
|
todasAgrupaciones.TryGetValue(idPartidoPresidenteDiputados ?? "", out var presidenteDiputados);
|
||||||
|
|
||||||
|
object MapearPartidos(int categoriaId)
|
||||||
|
{
|
||||||
|
var partidosDeCamara = bancasPorAgrupacion
|
||||||
|
.Where(b => b.CategoriaId == categoriaId && b.BancasTotales > 0)
|
||||||
|
.Select(b => new { Bancas = b, Agrupacion = todasAgrupaciones[b.AgrupacionId] });
|
||||||
|
|
||||||
|
if (categoriaId == 6) // Diputados
|
||||||
|
partidosDeCamara = partidosDeCamara.OrderBy(b => b.Agrupacion.OrdenDiputados ?? 999)
|
||||||
|
.ThenByDescending(b => b.Bancas.BancasTotales);
|
||||||
|
else // Senadores
|
||||||
|
partidosDeCamara = partidosDeCamara.OrderBy(b => b.Agrupacion.OrdenSenadores ?? 999)
|
||||||
|
.ThenByDescending(b => b.Bancas.BancasTotales);
|
||||||
|
|
||||||
|
return partidosDeCamara
|
||||||
|
.Select(b => new
|
||||||
|
{
|
||||||
|
b.Agrupacion.Id,
|
||||||
|
b.Agrupacion.Nombre,
|
||||||
|
b.Agrupacion.NombreCorto,
|
||||||
|
b.Agrupacion.Color,
|
||||||
|
b.Bancas.BancasTotales
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
}
|
||||||
|
|
||||||
|
var diputados = new
|
||||||
|
{
|
||||||
|
CamaraNombre = "Cámara de Diputados",
|
||||||
|
TotalBancas = 92,
|
||||||
|
BancasEnJuego = 46,
|
||||||
|
Partidos = MapearPartidos(6),
|
||||||
|
PresidenteBancada = presidenteDiputados != null ? new { presidenteDiputados.Color } : null
|
||||||
|
};
|
||||||
|
|
||||||
|
var senadores = new
|
||||||
|
{
|
||||||
|
CamaraNombre = "Cámara de Senadores",
|
||||||
|
TotalBancas = 46,
|
||||||
|
BancasEnJuego = 23,
|
||||||
|
Partidos = MapearPartidos(5),
|
||||||
|
PresidenteBancada = presidenteSenadores != null ? new { presidenteSenadores.Color } : null
|
||||||
|
};
|
||||||
|
|
||||||
|
return Ok(new { Diputados = diputados, Senadores = senadores });
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("bancadas-detalle")]
|
||||||
|
public async Task<IActionResult> GetBancadasConOcupantes()
|
||||||
|
{
|
||||||
|
var config = await _dbContext.Configuraciones.AsNoTracking().ToDictionaryAsync(c => c.Clave, c => c.Valor);
|
||||||
|
config.TryGetValue("MostrarOcupantes", out var mostrarOcupantesValue);
|
||||||
|
if (mostrarOcupantesValue != "true")
|
||||||
|
{
|
||||||
|
// Si la opción está desactivada, devolvemos un array vacío.
|
||||||
|
return Ok(new List<object>());
|
||||||
|
}
|
||||||
|
|
||||||
|
var bancadasConOcupantes = await _dbContext.Bancadas
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(b => b.Ocupante)
|
||||||
|
.Where(b => b.Ocupante != null) // Solo las que tienen un ocupante asignado
|
||||||
|
.Select(b => new
|
||||||
|
{
|
||||||
|
b.Id,
|
||||||
|
b.Camara,
|
||||||
|
b.AgrupacionPoliticaId,
|
||||||
|
Ocupante = b.Ocupante
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Ok(bancadasConOcupantes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,6 @@
|
|||||||
using Elecciones.Core.DTOs.ApiResponses;
|
|
||||||
using Elecciones.Database;
|
using Elecciones.Database;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
|
|
||||||
namespace Elecciones.Api.Controllers;
|
namespace Elecciones.Api.Controllers;
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="9.0.8" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.5" />
|
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.5" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.8">
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="9.0.8">
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
using Elecciones.Database;
|
using Elecciones.Database;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Serilog;
|
using Serilog;
|
||||||
|
using Elecciones.Core.Services;
|
||||||
|
using Elecciones.Infrastructure.Services;
|
||||||
|
using System.Text;
|
||||||
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
|
using Microsoft.IdentityModel.Tokens;
|
||||||
|
using Elecciones.Database.Entities;
|
||||||
|
using System.Text.Json.Serialization;
|
||||||
|
|
||||||
// Esta es la estructura estándar y recomendada.
|
// Esta es la estructura estándar y recomendada.
|
||||||
var builder = WebApplication.CreateBuilder(args);
|
var builder = WebApplication.CreateBuilder(args);
|
||||||
@@ -18,22 +25,44 @@ var connectionString = builder.Configuration.GetConnectionString("DefaultConnect
|
|||||||
builder.Services.AddDbContext<EleccionesDbContext>(options =>
|
builder.Services.AddDbContext<EleccionesDbContext>(options =>
|
||||||
options.UseSqlServer(connectionString));
|
options.UseSqlServer(connectionString));
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddScoped<IPasswordHasher, PasswordHasher>();
|
||||||
|
|
||||||
var allowedOrigins = builder.Configuration["AllowedOrigins"]?.Split(',') ?? Array.Empty<string>();
|
builder.Services.AddControllers().AddJsonOptions(options =>
|
||||||
|
{
|
||||||
|
// Esto le dice al serializador que maneje las referencias circulares
|
||||||
|
options.JsonSerializerOptions.ReferenceHandler = ReferenceHandler.IgnoreCycles;
|
||||||
|
});
|
||||||
|
|
||||||
|
var MyAllowSpecificOrigins = "_myAllowSpecificOrigins";
|
||||||
builder.Services.AddCors(options =>
|
builder.Services.AddCors(options =>
|
||||||
{
|
{
|
||||||
options.AddDefaultPolicy(policy =>
|
options.AddPolicy(name: MyAllowSpecificOrigins,
|
||||||
{
|
policy =>
|
||||||
if (allowedOrigins.Any())
|
{
|
||||||
{
|
policy.WithOrigins(
|
||||||
policy.WithOrigins(allowedOrigins)
|
"http://localhost:5173", // Para widgets
|
||||||
.AllowAnyHeader()
|
"http://localhost:5174" // Para admin
|
||||||
.AllowAnyMethod();
|
)
|
||||||
}
|
.AllowAnyHeader()
|
||||||
});
|
.AllowAnyMethod();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
|
||||||
|
.AddJwtBearer(options =>
|
||||||
|
{
|
||||||
|
options.TokenValidationParameters = new TokenValidationParameters
|
||||||
|
{
|
||||||
|
ValidateIssuer = true,
|
||||||
|
ValidateAudience = true,
|
||||||
|
ValidateLifetime = true,
|
||||||
|
ValidateIssuerSigningKey = true,
|
||||||
|
ValidIssuer = builder.Configuration["Jwt:Issuer"],
|
||||||
|
ValidAudience = builder.Configuration["Jwt:Audience"],
|
||||||
|
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]!))
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
builder.Services.AddSwaggerGen();
|
builder.Services.AddSwaggerGen();
|
||||||
|
|
||||||
@@ -41,7 +70,72 @@ builder.Services.AddSwaggerGen();
|
|||||||
// 3. Construir la aplicación.
|
// 3. Construir la aplicación.
|
||||||
var app = builder.Build();
|
var app = builder.Build();
|
||||||
|
|
||||||
// 4. Configurar el pipeline de peticiones HTTP.
|
// Seeder para el usuario admin
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var services = scope.ServiceProvider;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var context = services.GetRequiredService<EleccionesDbContext>();
|
||||||
|
var hasher = services.GetRequiredService<IPasswordHasher>();
|
||||||
|
if (!context.AdminUsers.Any())
|
||||||
|
{
|
||||||
|
var (hash, salt) = hasher.HashPassword("PTP847elec");
|
||||||
|
context.AdminUsers.Add(new Elecciones.Database.Entities.AdminUser
|
||||||
|
{
|
||||||
|
Username = "admin",
|
||||||
|
PasswordHash = hash,
|
||||||
|
PasswordSalt = salt
|
||||||
|
});
|
||||||
|
context.SaveChanges();
|
||||||
|
Console.WriteLine("--> Admin user seeded.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
var logger = services.GetRequiredService<ILogger<Program>>();
|
||||||
|
logger.LogError(ex, "An error occurred while seeding the database.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seeder para las bancas vacías
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var services = scope.ServiceProvider;
|
||||||
|
var context = services.GetRequiredService<EleccionesDbContext>();
|
||||||
|
if (!context.Bancadas.Any())
|
||||||
|
{
|
||||||
|
var bancas = new List<Bancada>();
|
||||||
|
// 92 bancas de diputados
|
||||||
|
for (int i = 0; i < 92; i++)
|
||||||
|
{
|
||||||
|
bancas.Add(new Bancada { Camara = Elecciones.Core.Enums.TipoCamara.Diputados });
|
||||||
|
}
|
||||||
|
// 46 bancas de senadores
|
||||||
|
for (int i = 0; i < 46; i++)
|
||||||
|
{
|
||||||
|
bancas.Add(new Bancada { Camara = Elecciones.Core.Enums.TipoCamara.Senadores });
|
||||||
|
}
|
||||||
|
context.Bancadas.AddRange(bancas);
|
||||||
|
context.SaveChanges();
|
||||||
|
Console.WriteLine("--> Seeded 138 empty bancas.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Seeder para las configuraciones por defecto
|
||||||
|
using (var scope = app.Services.CreateScope())
|
||||||
|
{
|
||||||
|
var services = scope.ServiceProvider;
|
||||||
|
var context = services.GetRequiredService<EleccionesDbContext>();
|
||||||
|
if (!context.Configuraciones.Any(c => c.Clave == "MostrarOcupantes"))
|
||||||
|
{
|
||||||
|
context.Configuraciones.Add(new Configuracion { Clave = "MostrarOcupantes", Valor = "true" });
|
||||||
|
context.SaveChanges();
|
||||||
|
Console.WriteLine("--> Seeded default configuration 'MostrarOcupantes'.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Configurar el pipeline de peticiones HTTP.
|
||||||
// Añadimos el logging de peticiones de Serilog aquí.
|
// Añadimos el logging de peticiones de Serilog aquí.
|
||||||
app.UseSerilogRequestLogging();
|
app.UseSerilogRequestLogging();
|
||||||
|
|
||||||
@@ -51,11 +145,27 @@ if (app.Environment.IsDevelopment())
|
|||||||
app.UseSwaggerUI();
|
app.UseSwaggerUI();
|
||||||
}
|
}
|
||||||
|
|
||||||
app.UseHttpsRedirection();
|
// 1. Redirección a HTTPS (si se usa)
|
||||||
app.UseCors();
|
//app.UseHttpsRedirection();
|
||||||
|
|
||||||
|
// 2. Middleware de Enrutamiento. ¡CLAVE!
|
||||||
|
// Determina a qué endpoint irá la petición.
|
||||||
|
app.UseRouting();
|
||||||
|
|
||||||
|
// 3. Middleware de CORS.
|
||||||
|
// Ahora se ejecuta sabiendo a qué endpoint se dirige la petición.
|
||||||
|
app.UseCors(MyAllowSpecificOrigins);
|
||||||
|
|
||||||
|
// 4. Middleware de Autenticación.
|
||||||
|
// Identifica quién es el usuario a partir del token.
|
||||||
|
app.UseAuthentication();
|
||||||
|
|
||||||
|
// 5. Middleware de Autorización.
|
||||||
|
// Verifica si el usuario identificado tiene permiso para acceder al endpoint.
|
||||||
app.UseAuthorization();
|
app.UseAuthorization();
|
||||||
|
|
||||||
|
// 6. Mapea los controladores a los endpoints que el enrutador descubrió.
|
||||||
app.MapControllers();
|
app.MapControllers();
|
||||||
|
|
||||||
// 5. Ejecutar la aplicación.
|
// 5. Ejecutar la aplicación.
|
||||||
// El try/catch/finally se puede omitir; el logging de Serilog ya se encarga de los errores fatales.
|
|
||||||
app.Run();
|
app.Run();
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.AspNetCore.Mvc.Filters;
|
||||||
|
|
||||||
|
namespace Elecciones.Api.Security;
|
||||||
|
|
||||||
|
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
|
||||||
|
public class ApiKeyAuthAttribute : Attribute, IAsyncActionFilter
|
||||||
|
{
|
||||||
|
private const string ApiKeyHeaderName = "X-Api-Key";
|
||||||
|
|
||||||
|
public async Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
|
||||||
|
{
|
||||||
|
var configuration = context.HttpContext.RequestServices.GetRequiredService<IConfiguration>();
|
||||||
|
var apiKey = configuration.GetValue<string>("ApiKey");
|
||||||
|
|
||||||
|
if (!context.HttpContext.Request.Headers.TryGetValue(ApiKeyHeaderName, out var potentialApiKey) || apiKey == null || !apiKey.Equals(potentialApiKey))
|
||||||
|
{
|
||||||
|
context.Result = new UnauthorizedResult();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
await next();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@
|
|||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedOrigins": "http://localhost:5173",
|
|
||||||
|
|
||||||
"ComposicionCongreso": {
|
"ComposicionCongreso": {
|
||||||
"Diputados": {
|
"Diputados": {
|
||||||
@@ -34,5 +33,11 @@
|
|||||||
{ "Id": "507_S", "Nombre": "CANDIDATURA 507", "BancasTotales": 5, "BancasEnJuego": 2, "Color": "#9467bd" }
|
{ "Id": "507_S", "Nombre": "CANDIDATURA 507", "BancasTotales": 5, "BancasEnJuego": 2, "Color": "#9467bd" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"ApiKey": "badb1a38d221c9e23bcf70958840ca7f5a5dc54f2047dadf7ce45b578b5bc3e2",
|
||||||
|
"Jwt": {
|
||||||
|
"Key": "badb1a38d221c9e23bcf70958840ca7f5a5dc54f2047dadf7ce45b578b5bc3e2",
|
||||||
|
"Issuer": "EleccionesApi",
|
||||||
|
"Audience": "AdminPanel"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Elecciones.Database": "1.0.0",
|
"Elecciones.Database": "1.0.0",
|
||||||
"Elecciones.Infrastructure": "1.0.0",
|
"Elecciones.Infrastructure": "1.0.0",
|
||||||
|
"Microsoft.AspNetCore.Authentication.JwtBearer": "9.0.8",
|
||||||
"Microsoft.AspNetCore.OpenApi": "9.0.5",
|
"Microsoft.AspNetCore.OpenApi": "9.0.5",
|
||||||
"Microsoft.EntityFrameworkCore.SqlServer": "9.0.8",
|
"Microsoft.EntityFrameworkCore.SqlServer": "9.0.8",
|
||||||
"Microsoft.EntityFrameworkCore.Tools": "9.0.8",
|
"Microsoft.EntityFrameworkCore.Tools": "9.0.8",
|
||||||
@@ -64,6 +65,17 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"Microsoft.AspNetCore.Authentication.JwtBearer/9.0.8": {
|
||||||
|
"dependencies": {
|
||||||
|
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.0.1"
|
||||||
|
},
|
||||||
|
"runtime": {
|
||||||
|
"lib/net9.0/Microsoft.AspNetCore.Authentication.JwtBearer.dll": {
|
||||||
|
"assemblyVersion": "9.0.8.0",
|
||||||
|
"fileVersion": "9.0.825.36808"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"Microsoft.AspNetCore.OpenApi/9.0.5": {
|
"Microsoft.AspNetCore.OpenApi/9.0.5": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.OpenApi": "1.6.23"
|
"Microsoft.OpenApi": "1.6.23"
|
||||||
@@ -371,14 +383,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Microsoft.CSharp/4.5.0": {},
|
|
||||||
"Microsoft.Data.SqlClient/5.1.6": {
|
"Microsoft.Data.SqlClient/5.1.6": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Azure.Identity": "1.11.4",
|
"Azure.Identity": "1.11.4",
|
||||||
"Microsoft.Data.SqlClient.SNI.runtime": "5.1.1",
|
"Microsoft.Data.SqlClient.SNI.runtime": "5.1.1",
|
||||||
"Microsoft.Identity.Client": "4.61.3",
|
"Microsoft.Identity.Client": "4.61.3",
|
||||||
"Microsoft.IdentityModel.JsonWebTokens": "6.35.0",
|
"Microsoft.IdentityModel.JsonWebTokens": "8.0.1",
|
||||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "6.35.0",
|
"Microsoft.IdentityModel.Protocols.OpenIdConnect": "8.0.1",
|
||||||
"Microsoft.SqlServer.Server": "1.0.0",
|
"Microsoft.SqlServer.Server": "1.0.0",
|
||||||
"System.Configuration.ConfigurationManager": "6.0.1",
|
"System.Configuration.ConfigurationManager": "6.0.1",
|
||||||
"System.Diagnostics.DiagnosticSource": "6.0.1",
|
"System.Diagnostics.DiagnosticSource": "6.0.1",
|
||||||
@@ -719,7 +730,7 @@
|
|||||||
},
|
},
|
||||||
"Microsoft.Identity.Client/4.61.3": {
|
"Microsoft.Identity.Client/4.61.3": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.IdentityModel.Abstractions": "6.35.0",
|
"Microsoft.IdentityModel.Abstractions": "8.0.1",
|
||||||
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
"System.Diagnostics.DiagnosticSource": "6.0.1"
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
@@ -741,78 +752,70 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.Abstractions/6.35.0": {
|
"Microsoft.IdentityModel.Abstractions/8.0.1": {
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"lib/net6.0/Microsoft.IdentityModel.Abstractions.dll": {
|
"lib/net9.0/Microsoft.IdentityModel.Abstractions.dll": {
|
||||||
"assemblyVersion": "6.35.0.0",
|
"assemblyVersion": "8.0.1.0",
|
||||||
"fileVersion": "6.35.0.41201"
|
"fileVersion": "8.0.1.50722"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.JsonWebTokens/6.35.0": {
|
"Microsoft.IdentityModel.JsonWebTokens/8.0.1": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.IdentityModel.Tokens": "6.35.0",
|
"Microsoft.IdentityModel.Tokens": "8.0.1"
|
||||||
"System.Text.Encoding": "4.3.0",
|
|
||||||
"System.Text.Encodings.Web": "6.0.0",
|
|
||||||
"System.Text.Json": "9.0.8"
|
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"lib/net6.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
|
"lib/net9.0/Microsoft.IdentityModel.JsonWebTokens.dll": {
|
||||||
"assemblyVersion": "6.35.0.0",
|
"assemblyVersion": "8.0.1.0",
|
||||||
"fileVersion": "6.35.0.41201"
|
"fileVersion": "8.0.1.50722"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.Logging/6.35.0": {
|
"Microsoft.IdentityModel.Logging/8.0.1": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.IdentityModel.Abstractions": "6.35.0"
|
"Microsoft.IdentityModel.Abstractions": "8.0.1"
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"lib/net6.0/Microsoft.IdentityModel.Logging.dll": {
|
"lib/net9.0/Microsoft.IdentityModel.Logging.dll": {
|
||||||
"assemblyVersion": "6.35.0.0",
|
"assemblyVersion": "8.0.1.0",
|
||||||
"fileVersion": "6.35.0.41201"
|
"fileVersion": "8.0.1.50722"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.Protocols/6.35.0": {
|
"Microsoft.IdentityModel.Protocols/8.0.1": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.IdentityModel.Logging": "6.35.0",
|
"Microsoft.IdentityModel.Tokens": "8.0.1"
|
||||||
"Microsoft.IdentityModel.Tokens": "6.35.0"
|
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"lib/net6.0/Microsoft.IdentityModel.Protocols.dll": {
|
"lib/net9.0/Microsoft.IdentityModel.Protocols.dll": {
|
||||||
"assemblyVersion": "6.35.0.0",
|
"assemblyVersion": "8.0.1.0",
|
||||||
"fileVersion": "6.35.0.41201"
|
"fileVersion": "8.0.1.50722"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect/6.35.0": {
|
"Microsoft.IdentityModel.Protocols.OpenIdConnect/8.0.1": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.IdentityModel.Protocols": "6.35.0",
|
"Microsoft.IdentityModel.Protocols": "8.0.1",
|
||||||
"System.IdentityModel.Tokens.Jwt": "6.35.0"
|
"System.IdentityModel.Tokens.Jwt": "8.0.1"
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"lib/net6.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll": {
|
"lib/net9.0/Microsoft.IdentityModel.Protocols.OpenIdConnect.dll": {
|
||||||
"assemblyVersion": "6.35.0.0",
|
"assemblyVersion": "8.0.1.0",
|
||||||
"fileVersion": "6.35.0.41201"
|
"fileVersion": "8.0.1.50722"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.Tokens/6.35.0": {
|
"Microsoft.IdentityModel.Tokens/8.0.1": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.CSharp": "4.5.0",
|
"Microsoft.IdentityModel.Logging": "8.0.1"
|
||||||
"Microsoft.IdentityModel.Logging": "6.35.0",
|
|
||||||
"System.Security.Cryptography.Cng": "5.0.0"
|
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"lib/net6.0/Microsoft.IdentityModel.Tokens.dll": {
|
"lib/net9.0/Microsoft.IdentityModel.Tokens.dll": {
|
||||||
"assemblyVersion": "6.35.0.0",
|
"assemblyVersion": "8.0.1.0",
|
||||||
"fileVersion": "6.35.0.41201"
|
"fileVersion": "8.0.1.50722"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Microsoft.NETCore.Platforms/1.1.0": {},
|
|
||||||
"Microsoft.NETCore.Targets/1.1.0": {},
|
|
||||||
"Microsoft.OpenApi/1.6.23": {
|
"Microsoft.OpenApi/1.6.23": {
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"lib/netstandard2.0/Microsoft.OpenApi.dll": {
|
"lib/netstandard2.0/Microsoft.OpenApi.dll": {
|
||||||
@@ -1134,15 +1137,15 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"System.IdentityModel.Tokens.Jwt/6.35.0": {
|
"System.IdentityModel.Tokens.Jwt/8.0.1": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"Microsoft.IdentityModel.JsonWebTokens": "6.35.0",
|
"Microsoft.IdentityModel.JsonWebTokens": "8.0.1",
|
||||||
"Microsoft.IdentityModel.Tokens": "6.35.0"
|
"Microsoft.IdentityModel.Tokens": "8.0.1"
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
"lib/net6.0/System.IdentityModel.Tokens.Jwt.dll": {
|
"lib/net9.0/System.IdentityModel.Tokens.Jwt.dll": {
|
||||||
"assemblyVersion": "6.35.0.0",
|
"assemblyVersion": "8.0.1.0",
|
||||||
"fileVersion": "6.35.0.41201"
|
"fileVersion": "8.0.1.50722"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1166,12 +1169,6 @@
|
|||||||
"System.Collections.Immutable": "7.0.0"
|
"System.Collections.Immutable": "7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"System.Runtime/4.3.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.NETCore.Platforms": "1.1.0",
|
|
||||||
"Microsoft.NETCore.Targets": "1.1.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.Runtime.Caching/6.0.0": {
|
"System.Runtime.Caching/6.0.0": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.Configuration.ConfigurationManager": "6.0.1"
|
"System.Configuration.ConfigurationManager": "6.0.1"
|
||||||
@@ -1227,13 +1224,6 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"System.Security.Principal.Windows/5.0.0": {},
|
"System.Security.Principal.Windows/5.0.0": {},
|
||||||
"System.Text.Encoding/4.3.0": {
|
|
||||||
"dependencies": {
|
|
||||||
"Microsoft.NETCore.Platforms": "1.1.0",
|
|
||||||
"Microsoft.NETCore.Targets": "1.1.0",
|
|
||||||
"System.Runtime": "4.3.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"System.Text.Encoding.CodePages/6.0.0": {
|
"System.Text.Encoding.CodePages/6.0.0": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
"System.Runtime.CompilerServices.Unsafe": "6.0.0"
|
||||||
@@ -1291,6 +1281,7 @@
|
|||||||
},
|
},
|
||||||
"Elecciones.Database/1.0.0": {
|
"Elecciones.Database/1.0.0": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"Elecciones.Core": "1.0.0",
|
||||||
"Microsoft.EntityFrameworkCore.SqlServer": "9.0.8"
|
"Microsoft.EntityFrameworkCore.SqlServer": "9.0.8"
|
||||||
},
|
},
|
||||||
"runtime": {
|
"runtime": {
|
||||||
@@ -1343,6 +1334,13 @@
|
|||||||
"path": "humanizer.core/2.14.1",
|
"path": "humanizer.core/2.14.1",
|
||||||
"hashPath": "humanizer.core.2.14.1.nupkg.sha512"
|
"hashPath": "humanizer.core.2.14.1.nupkg.sha512"
|
||||||
},
|
},
|
||||||
|
"Microsoft.AspNetCore.Authentication.JwtBearer/9.0.8": {
|
||||||
|
"type": "package",
|
||||||
|
"serviceable": true,
|
||||||
|
"sha512": "sha512-pEuE/xaXHk2Rr2YiTraS7i2MNoTXSnX79VlJcdKx9MczrhDfBO4tHdF4HWOo542WPbjSeZx2PFjmHygo0XnK3Q==",
|
||||||
|
"path": "microsoft.aspnetcore.authentication.jwtbearer/9.0.8",
|
||||||
|
"hashPath": "microsoft.aspnetcore.authentication.jwtbearer.9.0.8.nupkg.sha512"
|
||||||
|
},
|
||||||
"Microsoft.AspNetCore.OpenApi/9.0.5": {
|
"Microsoft.AspNetCore.OpenApi/9.0.5": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
@@ -1413,13 +1411,6 @@
|
|||||||
"path": "microsoft.codeanalysis.workspaces.msbuild/4.8.0",
|
"path": "microsoft.codeanalysis.workspaces.msbuild/4.8.0",
|
||||||
"hashPath": "microsoft.codeanalysis.workspaces.msbuild.4.8.0.nupkg.sha512"
|
"hashPath": "microsoft.codeanalysis.workspaces.msbuild.4.8.0.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"Microsoft.CSharp/4.5.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-kaj6Wb4qoMuH3HySFJhxwQfe8R/sJsNJnANrvv8WdFPMoNbKY5htfNscv+LHCu5ipz+49m2e+WQXpLXr9XYemQ==",
|
|
||||||
"path": "microsoft.csharp/4.5.0",
|
|
||||||
"hashPath": "microsoft.csharp.4.5.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.Data.SqlClient/5.1.6": {
|
"Microsoft.Data.SqlClient/5.1.6": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
@@ -1630,61 +1621,47 @@
|
|||||||
"path": "microsoft.identity.client.extensions.msal/4.61.3",
|
"path": "microsoft.identity.client.extensions.msal/4.61.3",
|
||||||
"hashPath": "microsoft.identity.client.extensions.msal.4.61.3.nupkg.sha512"
|
"hashPath": "microsoft.identity.client.extensions.msal.4.61.3.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.Abstractions/6.35.0": {
|
"Microsoft.IdentityModel.Abstractions/8.0.1": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
"sha512": "sha512-xuR8E4Rd96M41CnUSCiOJ2DBh+z+zQSmyrYHdYhD6K4fXBcQGVnRCFQ0efROUYpP+p0zC1BLKr0JRpVuujTZSg==",
|
"sha512": "sha512-OtlIWcyX01olfdevPKZdIPfBEvbcioDyBiE/Z2lHsopsMD7twcKtlN9kMevHmI5IIPhFpfwCIiR6qHQz1WHUIw==",
|
||||||
"path": "microsoft.identitymodel.abstractions/6.35.0",
|
"path": "microsoft.identitymodel.abstractions/8.0.1",
|
||||||
"hashPath": "microsoft.identitymodel.abstractions.6.35.0.nupkg.sha512"
|
"hashPath": "microsoft.identitymodel.abstractions.8.0.1.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.JsonWebTokens/6.35.0": {
|
"Microsoft.IdentityModel.JsonWebTokens/8.0.1": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
"sha512": "sha512-9wxai3hKgZUb4/NjdRKfQd0QJvtXKDlvmGMYACbEC8DFaicMFCFhQFZq9ZET1kJLwZahf2lfY5Gtcpsx8zYzbg==",
|
"sha512": "sha512-s6++gF9x0rQApQzOBbSyp4jUaAlwm+DroKfL8gdOHxs83k8SJfUXhuc46rDB3rNXBQ1MVRxqKUrqFhO/M0E97g==",
|
||||||
"path": "microsoft.identitymodel.jsonwebtokens/6.35.0",
|
"path": "microsoft.identitymodel.jsonwebtokens/8.0.1",
|
||||||
"hashPath": "microsoft.identitymodel.jsonwebtokens.6.35.0.nupkg.sha512"
|
"hashPath": "microsoft.identitymodel.jsonwebtokens.8.0.1.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.Logging/6.35.0": {
|
"Microsoft.IdentityModel.Logging/8.0.1": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
"sha512": "sha512-jePrSfGAmqT81JDCNSY+fxVWoGuJKt9e6eJ+vT7+quVS55nWl//jGjUQn4eFtVKt4rt5dXaleZdHRB9J9AJZ7Q==",
|
"sha512": "sha512-UCPF2exZqBXe7v/6sGNiM6zCQOUXXQ9+v5VTb9gPB8ZSUPnX53BxlN78v2jsbIvK9Dq4GovQxo23x8JgWvm/Qg==",
|
||||||
"path": "microsoft.identitymodel.logging/6.35.0",
|
"path": "microsoft.identitymodel.logging/8.0.1",
|
||||||
"hashPath": "microsoft.identitymodel.logging.6.35.0.nupkg.sha512"
|
"hashPath": "microsoft.identitymodel.logging.8.0.1.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.Protocols/6.35.0": {
|
"Microsoft.IdentityModel.Protocols/8.0.1": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
"sha512": "sha512-BPQhlDzdFvv1PzaUxNSk+VEPwezlDEVADIKmyxubw7IiELK18uJ06RQ9QKKkds30XI+gDu9n8j24XQ8w7fjWcg==",
|
"sha512": "sha512-uA2vpKqU3I2mBBEaeJAWPTjT9v1TZrGWKdgK6G5qJd03CLx83kdiqO9cmiK8/n1erkHzFBwU/RphP83aAe3i3g==",
|
||||||
"path": "microsoft.identitymodel.protocols/6.35.0",
|
"path": "microsoft.identitymodel.protocols/8.0.1",
|
||||||
"hashPath": "microsoft.identitymodel.protocols.6.35.0.nupkg.sha512"
|
"hashPath": "microsoft.identitymodel.protocols.8.0.1.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.Protocols.OpenIdConnect/6.35.0": {
|
"Microsoft.IdentityModel.Protocols.OpenIdConnect/8.0.1": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
"sha512": "sha512-LMtVqnECCCdSmyFoCOxIE5tXQqkOLrvGrL7OxHg41DIm1bpWtaCdGyVcTAfOQpJXvzND9zUKIN/lhngPkYR8vg==",
|
"sha512": "sha512-AQDbfpL+yzuuGhO/mQhKNsp44pm5Jv8/BI4KiFXR7beVGZoSH35zMV3PrmcfvSTsyI6qrcR898NzUauD6SRigg==",
|
||||||
"path": "microsoft.identitymodel.protocols.openidconnect/6.35.0",
|
"path": "microsoft.identitymodel.protocols.openidconnect/8.0.1",
|
||||||
"hashPath": "microsoft.identitymodel.protocols.openidconnect.6.35.0.nupkg.sha512"
|
"hashPath": "microsoft.identitymodel.protocols.openidconnect.8.0.1.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"Microsoft.IdentityModel.Tokens/6.35.0": {
|
"Microsoft.IdentityModel.Tokens/8.0.1": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
"sha512": "sha512-RN7lvp7s3Boucg1NaNAbqDbxtlLj5Qeb+4uSS1TeK5FSBVM40P4DKaTKChT43sHyKfh7V0zkrMph6DdHvyA4bg==",
|
"sha512": "sha512-kDimB6Dkd3nkW2oZPDkMkVHfQt3IDqO5gL0oa8WVy3OP4uE8Ij+8TXnqg9TOd9ufjsY3IDiGz7pCUbnfL18tjg==",
|
||||||
"path": "microsoft.identitymodel.tokens/6.35.0",
|
"path": "microsoft.identitymodel.tokens/8.0.1",
|
||||||
"hashPath": "microsoft.identitymodel.tokens.6.35.0.nupkg.sha512"
|
"hashPath": "microsoft.identitymodel.tokens.8.0.1.nupkg.sha512"
|
||||||
},
|
|
||||||
"Microsoft.NETCore.Platforms/1.1.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-kz0PEW2lhqygehI/d6XsPCQzD7ff7gUJaVGPVETX611eadGsA3A877GdSlU0LRVMCTH/+P3o2iDTak+S08V2+A==",
|
|
||||||
"path": "microsoft.netcore.platforms/1.1.0",
|
|
||||||
"hashPath": "microsoft.netcore.platforms.1.1.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"Microsoft.NETCore.Targets/1.1.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-aOZA3BWfz9RXjpzt0sRJJMjAscAUm3Hoa4UWAfceV9UTYxgwZ1lZt5nO2myFf+/jetYQo4uTP7zS8sJY67BBxg==",
|
|
||||||
"path": "microsoft.netcore.targets/1.1.0",
|
|
||||||
"hashPath": "microsoft.netcore.targets.1.1.0.nupkg.sha512"
|
|
||||||
},
|
},
|
||||||
"Microsoft.OpenApi/1.6.23": {
|
"Microsoft.OpenApi/1.6.23": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
@@ -1896,12 +1873,12 @@
|
|||||||
"path": "system.formats.asn1/9.0.8",
|
"path": "system.formats.asn1/9.0.8",
|
||||||
"hashPath": "system.formats.asn1.9.0.8.nupkg.sha512"
|
"hashPath": "system.formats.asn1.9.0.8.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"System.IdentityModel.Tokens.Jwt/6.35.0": {
|
"System.IdentityModel.Tokens.Jwt/8.0.1": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
"sha512": "sha512-yxGIQd3BFK7F6S62/7RdZk3C/mfwyVxvh6ngd1VYMBmbJ1YZZA9+Ku6suylVtso0FjI0wbElpJ0d27CdsyLpBQ==",
|
"sha512": "sha512-GJw3bYkWpOgvN3tJo5X4lYUeIFA2HD293FPUhKmp7qxS+g5ywAb34Dnd3cDAFLkcMohy5XTpoaZ4uAHuw0uSPQ==",
|
||||||
"path": "system.identitymodel.tokens.jwt/6.35.0",
|
"path": "system.identitymodel.tokens.jwt/8.0.1",
|
||||||
"hashPath": "system.identitymodel.tokens.jwt.6.35.0.nupkg.sha512"
|
"hashPath": "system.identitymodel.tokens.jwt.8.0.1.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"System.IO.Pipelines/7.0.0": {
|
"System.IO.Pipelines/7.0.0": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
@@ -1938,13 +1915,6 @@
|
|||||||
"path": "system.reflection.metadata/7.0.0",
|
"path": "system.reflection.metadata/7.0.0",
|
||||||
"hashPath": "system.reflection.metadata.7.0.0.nupkg.sha512"
|
"hashPath": "system.reflection.metadata.7.0.0.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"System.Runtime/4.3.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-JufQi0vPQ0xGnAczR13AUFglDyVYt4Kqnz1AZaiKZ5+GICq0/1MH/mO/eAJHt/mHW1zjKBJd7kV26SrxddAhiw==",
|
|
||||||
"path": "system.runtime/4.3.0",
|
|
||||||
"hashPath": "system.runtime.4.3.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.Runtime.Caching/6.0.0": {
|
"System.Runtime.Caching/6.0.0": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
@@ -1994,13 +1964,6 @@
|
|||||||
"path": "system.security.principal.windows/5.0.0",
|
"path": "system.security.principal.windows/5.0.0",
|
||||||
"hashPath": "system.security.principal.windows.5.0.0.nupkg.sha512"
|
"hashPath": "system.security.principal.windows.5.0.0.nupkg.sha512"
|
||||||
},
|
},
|
||||||
"System.Text.Encoding/4.3.0": {
|
|
||||||
"type": "package",
|
|
||||||
"serviceable": true,
|
|
||||||
"sha512": "sha512-BiIg+KWaSDOITze6jGQynxg64naAPtqGHBwDrLaCtixsa5bKiR8dpPOHA7ge3C0JJQizJE+sfkz1wV+BAKAYZw==",
|
|
||||||
"path": "system.text.encoding/4.3.0",
|
|
||||||
"hashPath": "system.text.encoding.4.3.0.nupkg.sha512"
|
|
||||||
},
|
|
||||||
"System.Text.Encoding.CodePages/6.0.0": {
|
"System.Text.Encoding.CodePages/6.0.0": {
|
||||||
"type": "package",
|
"type": "package",
|
||||||
"serviceable": true,
|
"serviceable": true,
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"AllowedOrigins": "http://localhost:5173",
|
|
||||||
|
|
||||||
"ComposicionCongreso": {
|
"ComposicionCongreso": {
|
||||||
"Diputados": {
|
"Diputados": {
|
||||||
@@ -34,5 +33,11 @@
|
|||||||
{ "Id": "507_S", "Nombre": "CANDIDATURA 507", "BancasTotales": 5, "BancasEnJuego": 2, "Color": "#9467bd" }
|
{ "Id": "507_S", "Nombre": "CANDIDATURA 507", "BancasTotales": 5, "BancasEnJuego": 2, "Color": "#9467bd" }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"ApiKey": "badb1a38d221c9e23bcf70958840ca7f5a5dc54f2047dadf7ce45b578b5bc3e2",
|
||||||
|
"Jwt": {
|
||||||
|
"Key": "badb1a38d221c9e23bcf70958840ca7f5a5dc54f2047dadf7ce45b578b5bc3e2",
|
||||||
|
"Issuer": "EleccionesApi",
|
||||||
|
"Audience": "AdminPanel"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -14,7 +14,7 @@ using System.Reflection;
|
|||||||
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")]
|
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")]
|
||||||
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
|
||||||
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
|
||||||
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+0d33db9e6dc7807fbb1853c621b81002ea764411")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+55954e18a797dce22f76f00b645832f361d97362")]
|
||||||
[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")]
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Elecciones
|
|||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Azure.Core.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Azure.Core.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Azure.Identity.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Azure.Identity.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Humanizer.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Humanizer.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.AspNetCore.Authentication.JwtBearer.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.AspNetCore.OpenApi.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.AspNetCore.OpenApi.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Bcl.AsyncInterfaces.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Bcl.AsyncInterfaces.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Build.Locator.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Build.Locator.dll
|
||||||
@@ -26,13 +27,19 @@ E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.
|
|||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.EntityFrameworkCore.SqlServer.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.EntityFrameworkCore.SqlServer.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Caching.Abstractions.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Caching.Abstractions.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Caching.Memory.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Caching.Memory.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.Abstractions.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Configuration.Abstractions.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.DependencyInjection.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.DependencyInjection.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.DependencyModel.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.DependencyModel.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.Logging.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Logging.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Logging.Abstractions.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Logging.Abstractions.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Options.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Options.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Primitives.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Extensions.Primitives.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Identity.Client.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Identity.Client.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Identity.Client.Extensions.Msal.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Identity.Client.Extensions.Msal.dll
|
||||||
@@ -46,6 +53,15 @@ E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.
|
|||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.SqlServer.Server.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.SqlServer.Server.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Win32.SystemEvents.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Microsoft.Win32.SystemEvents.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Mono.TextTemplating.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Mono.TextTemplating.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.AspNetCore.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Extensions.Hosting.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Extensions.Logging.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Formatting.Compact.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Settings.Configuration.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Sinks.Console.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Sinks.Debug.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Sinks.File.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Swashbuckle.AspNetCore.Swagger.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Swashbuckle.AspNetCore.Swagger.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Swashbuckle.AspNetCore.SwaggerGen.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Swashbuckle.AspNetCore.SwaggerGen.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Swashbuckle.AspNetCore.SwaggerUI.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Swashbuckle.AspNetCore.SwaggerUI.dll
|
||||||
@@ -65,6 +81,7 @@ E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Run
|
|||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Security.Cryptography.ProtectedData.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Security.Cryptography.ProtectedData.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Security.Permissions.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Security.Permissions.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Text.Json.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Text.Json.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Threading.RateLimiting.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Windows.Extensions.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Windows.Extensions.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\cs\Microsoft.CodeAnalysis.resources.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\cs\Microsoft.CodeAnalysis.resources.dll
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\de\Microsoft.CodeAnalysis.resources.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\de\Microsoft.CodeAnalysis.resources.dll
|
||||||
@@ -167,19 +184,3 @@ 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
|
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.dll
|
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.AspNetCore.dll
|
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Extensions.Hosting.dll
|
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Extensions.Logging.dll
|
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Formatting.Compact.dll
|
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Settings.Configuration.dll
|
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Sinks.Console.dll
|
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Sinks.Debug.dll
|
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\Serilog.Sinks.File.dll
|
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Api\bin\Debug\net9.0\System.Threading.RateLimiting.dll
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["FcPFHNuKs9rpM6p2fQ3PQFvYqx5ErYLwhh645T9bWO0=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","ZJX2c4LV\u002BYIn48VQilINT/Er9ydx\u002BF/pffY0J1mGFn4=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","HlaBteUK6BYZn6ZcnalIbUis9O08fQFj0pX7AkkgymQ="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","GeIeP3tog3JZwKJCFe6prPm1MG/MSEFptilJTMpLZdk=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","DfeTw\u002BIdhmMK9IhKuwlSfgckGaIOiGMaYzhCKVkysII="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||||
@@ -1 +1 @@
|
|||||||
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["FcPFHNuKs9rpM6p2fQ3PQFvYqx5ErYLwhh645T9bWO0=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","ZJX2c4LV\u002BYIn48VQilINT/Er9ydx\u002BF/pffY0J1mGFn4=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","HlaBteUK6BYZn6ZcnalIbUis9O08fQFj0pX7AkkgymQ="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","GeIeP3tog3JZwKJCFe6prPm1MG/MSEFptilJTMpLZdk=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","DfeTw\u002BIdhmMK9IhKuwlSfgckGaIOiGMaYzhCKVkysII="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||||
@@ -1 +1 @@
|
|||||||
{"GlobalPropertiesHash":"O7YawHw32G/Fh2bs+snZgm9O7okI0WYgTQmXM931znY=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["FcPFHNuKs9rpM6p2fQ3PQFvYqx5ErYLwhh645T9bWO0=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
{"GlobalPropertiesHash":"O7YawHw32G/Fh2bs+snZgm9O7okI0WYgTQmXM931znY=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||||
@@ -57,6 +57,10 @@
|
|||||||
"net9.0": {
|
"net9.0": {
|
||||||
"targetAlias": "net9.0",
|
"targetAlias": "net9.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"Microsoft.AspNetCore.Authentication.JwtBearer": {
|
||||||
|
"target": "Package",
|
||||||
|
"version": "[9.0.8, )"
|
||||||
|
},
|
||||||
"Microsoft.AspNetCore.OpenApi": {
|
"Microsoft.AspNetCore.OpenApi": {
|
||||||
"target": "Package",
|
"target": "Package",
|
||||||
"version": "[9.0.5, )"
|
"version": "[9.0.5, )"
|
||||||
@@ -199,7 +203,11 @@
|
|||||||
"frameworks": {
|
"frameworks": {
|
||||||
"net9.0": {
|
"net9.0": {
|
||||||
"targetAlias": "net9.0",
|
"targetAlias": "net9.0",
|
||||||
"projectReferences": {}
|
"projectReferences": {
|
||||||
|
"E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj": {
|
||||||
|
"projectPath": "E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"warningProperties": {
|
"warningProperties": {
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
// src/Elecciones.Core/DTOs/ApiResponses/ComposicionCalculadaDto.cs
|
||||||
|
|
||||||
|
using Elecciones.Core.Enums;
|
||||||
|
|
||||||
|
namespace Elecciones.Core.DTOs.ApiResponses;
|
||||||
|
|
||||||
|
public class ComposicionCalculadaDto
|
||||||
|
{
|
||||||
|
// Propiedades de la Agrupación
|
||||||
|
public string Id { get; set; } = null!;
|
||||||
|
public string Nombre { get; set; } = null!;
|
||||||
|
public string? NombreCorto { get; set; }
|
||||||
|
public string? Color { get; set; }
|
||||||
|
public int? OrdenDiputados { get; set; }
|
||||||
|
public int? OrdenSenadores { get; set; }
|
||||||
|
|
||||||
|
// Propiedades calculadas
|
||||||
|
public TipoCamara Camara { get; set; }
|
||||||
|
public int BancasTotales { get; set; }
|
||||||
|
public int BancasEnJuego { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
// src/Elecciones.Core/DTOs/ApiRequests/OcupanteBancaDto.cs
|
||||||
|
namespace Elecciones.Core.DTOs.ApiRequests;
|
||||||
|
|
||||||
|
public class OcupanteBancaDto
|
||||||
|
{
|
||||||
|
public string NombreOcupante { get; set; } = null!;
|
||||||
|
public string FotoUrl { get; set; } = null!;
|
||||||
|
public string Periodo { get; set; } = null!;
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
// src/Elecciones.Core/DTOs/ApiRequests/UpdateAgrupacionDto.cs
|
||||||
|
namespace Elecciones.Core.DTOs.ApiRequests;
|
||||||
|
|
||||||
|
public class UpdateAgrupacionDto
|
||||||
|
{
|
||||||
|
// Usamos strings que aceptan nulos (?) para permitir que el admin
|
||||||
|
// borre un valor si lo desea (ej. quitar un logo).
|
||||||
|
public string? NombreCorto { get; set; }
|
||||||
|
public string? Color { get; set; }
|
||||||
|
public string? LogoUrl { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
// src/Elecciones.Core/DTOs/ApiRequests/UpdateBancadaDto.cs
|
||||||
|
namespace Elecciones.Core.DTOs.ApiRequests;
|
||||||
|
|
||||||
|
public class UpdateBancadaDto
|
||||||
|
{
|
||||||
|
// El ID de la agrupación a la que se asigna la banca (puede ser null para dejarla vacante)
|
||||||
|
public string? AgrupacionPoliticaId { get; set; }
|
||||||
|
|
||||||
|
// Datos del ocupante (opcionales)
|
||||||
|
public string? NombreOcupante { get; set; }
|
||||||
|
public string? FotoUrl { get; set; }
|
||||||
|
public string? Periodo { get; set; }
|
||||||
|
}
|
||||||
4
Elecciones-Web/src/Elecciones.Core/Enums/TipoCamara.cs
Normal file
4
Elecciones-Web/src/Elecciones.Core/Enums/TipoCamara.cs
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
// src/Elecciones.Core/Enums/TipoCamara.cs
|
||||||
|
namespace Elecciones.Core.Enums;
|
||||||
|
|
||||||
|
public enum TipoCamara { Diputados, Senadores }
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace Elecciones.Core.Services;
|
||||||
|
|
||||||
|
public interface IPasswordHasher
|
||||||
|
{
|
||||||
|
(string hash, string salt) HashPassword(string password);
|
||||||
|
bool VerifyPassword(string password, string storedHash, string storedSalt);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// src/Elecciones.Infrastructure/Services/PasswordHasher.cs
|
||||||
|
using Elecciones.Core.Services;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Elecciones.Infrastructure.Services;
|
||||||
|
|
||||||
|
public class PasswordHasher : IPasswordHasher
|
||||||
|
{
|
||||||
|
private const int SaltSize = 16; // 128 bit
|
||||||
|
private const int KeySize = 32; // 256 bit
|
||||||
|
private const int Iterations = 10000;
|
||||||
|
private static readonly HashAlgorithmName _hashAlgorithm = HashAlgorithmName.SHA256;
|
||||||
|
|
||||||
|
public (string hash, string salt) HashPassword(string password)
|
||||||
|
{
|
||||||
|
var salt = RandomNumberGenerator.GetBytes(SaltSize);
|
||||||
|
var hash = Rfc2898DeriveBytes.Pbkdf2(
|
||||||
|
Encoding.UTF8.GetBytes(password),
|
||||||
|
salt,
|
||||||
|
Iterations,
|
||||||
|
_hashAlgorithm,
|
||||||
|
KeySize);
|
||||||
|
|
||||||
|
return (Convert.ToBase64String(hash), Convert.ToBase64String(salt));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool VerifyPassword(string password, string storedHash, string storedSalt)
|
||||||
|
{
|
||||||
|
var salt = Convert.FromBase64String(storedSalt);
|
||||||
|
var hashToCompare = Rfc2898DeriveBytes.Pbkdf2(
|
||||||
|
Encoding.UTF8.GetBytes(password),
|
||||||
|
salt,
|
||||||
|
Iterations,
|
||||||
|
_hashAlgorithm,
|
||||||
|
KeySize);
|
||||||
|
|
||||||
|
return CryptographicOperations.FixedTimeEquals(hashToCompare, Convert.FromBase64String(storedHash));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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+0d33db9e6dc7807fbb1853c621b81002ea764411")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+55954e18a797dce22f76f00b645832f361d97362")]
|
||||||
[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")]
|
||||||
|
|||||||
@@ -14,4 +14,8 @@
|
|||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="9.0.8" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Elecciones.Core\Elecciones.Core.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -15,11 +15,17 @@ public class EleccionesDbContext(DbContextOptions<EleccionesDbContext> options)
|
|||||||
public DbSet<ResumenVoto> ResumenesVotos { get; set; }
|
public DbSet<ResumenVoto> ResumenesVotos { get; set; }
|
||||||
public DbSet<EstadoRecuentoGeneral> EstadosRecuentosGenerales { get; set; }
|
public DbSet<EstadoRecuentoGeneral> EstadosRecuentosGenerales { get; set; }
|
||||||
public DbSet<CategoriaElectoral> CategoriasElectorales { get; set; }
|
public DbSet<CategoriaElectoral> CategoriasElectorales { get; set; }
|
||||||
|
public DbSet<AdminUser> AdminUsers { get; set; }
|
||||||
|
public DbSet<Configuracion> Configuraciones { get; set; }
|
||||||
|
public DbSet<Bancada> Bancadas { get; set; }
|
||||||
|
public DbSet<OcupanteBanca> OcupantesBancas { get; set; }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.UseCollation("Modern_Spanish_CI_AS");
|
||||||
|
|
||||||
modelBuilder.Entity<ResultadoVoto>()
|
modelBuilder.Entity<ResultadoVoto>()
|
||||||
.HasIndex(r => new { r.AmbitoGeograficoId, r.CategoriaId, r.AgrupacionPoliticaId })
|
.HasIndex(r => new { r.AmbitoGeograficoId, r.CategoriaId, r.AgrupacionPoliticaId })
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
@@ -43,19 +49,31 @@ public class EleccionesDbContext(DbContextOptions<EleccionesDbContext> options)
|
|||||||
.Property(e => e.VotosPorcentaje).HasPrecision(5, 2);
|
.Property(e => e.VotosPorcentaje).HasPrecision(5, 2);
|
||||||
|
|
||||||
modelBuilder.Entity<EstadoRecuentoGeneral>(entity =>
|
modelBuilder.Entity<EstadoRecuentoGeneral>(entity =>
|
||||||
{
|
{
|
||||||
// Le decimos a EF que la combinación única es (AmbitoGeograficoId, CategoriaId)
|
// Le decimos a EF que la combinación única es (AmbitoGeograficoId, CategoriaId)
|
||||||
entity.HasKey(e => new { e.AmbitoGeograficoId, e.CategoriaId });
|
entity.HasKey(e => new { e.AmbitoGeograficoId, e.CategoriaId });
|
||||||
|
|
||||||
// Mantener la configuración de precisión
|
// Mantener la configuración de precisión
|
||||||
entity.Property(e => e.MesasTotalizadasPorcentaje).HasPrecision(5, 2);
|
entity.Property(e => e.MesasTotalizadasPorcentaje).HasPrecision(5, 2);
|
||||||
entity.Property(e => e.ParticipacionPorcentaje).HasPrecision(5, 2);
|
entity.Property(e => e.ParticipacionPorcentaje).HasPrecision(5, 2);
|
||||||
});
|
});
|
||||||
modelBuilder.Entity<ProyeccionBanca>(entity =>
|
modelBuilder.Entity<ProyeccionBanca>(entity =>
|
||||||
{
|
{
|
||||||
// La combinación de ámbito, categoría y agrupación debe ser única.
|
// La combinación de ámbito, categoría y agrupación debe ser única.
|
||||||
entity.HasIndex(p => new { p.AmbitoGeograficoId, p.CategoriaId, p.AgrupacionPoliticaId })
|
entity.HasIndex(p => new { p.AmbitoGeograficoId, p.CategoriaId, p.AgrupacionPoliticaId })
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
});
|
});
|
||||||
|
modelBuilder.Entity<Bancada>(entity =>
|
||||||
|
{
|
||||||
|
// Define la relación uno a uno: una Bancada tiene un Ocupante.
|
||||||
|
entity.HasOne(b => b.Ocupante)
|
||||||
|
.WithOne(o => o.Bancada)
|
||||||
|
.HasForeignKey<OcupanteBanca>(o => o.BancadaId);
|
||||||
|
});
|
||||||
|
modelBuilder.Entity<OcupanteBanca>(entity =>
|
||||||
|
{
|
||||||
|
// Opcional: puede definir un índice
|
||||||
|
entity.HasIndex(o => o.BancadaId).IsUnique();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
20
Elecciones-Web/src/Elecciones.Database/Entities/AdminUser.cs
Normal file
20
Elecciones-Web/src/Elecciones.Database/Entities/AdminUser.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// src/Elecciones.Database/Entities/AdminUser.cs
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Entities;
|
||||||
|
|
||||||
|
public class AdminUser
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string Username { get; set; } = null!;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string PasswordHash { get; set; } = null!;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string PasswordSalt { get; set; } = null!;
|
||||||
|
}
|
||||||
@@ -10,4 +10,10 @@ public class AgrupacionPolitica
|
|||||||
public string IdTelegrama { get; set; } = null!;
|
public string IdTelegrama { get; set; } = null!;
|
||||||
[Required]
|
[Required]
|
||||||
public string Nombre { get; set; } = null!;
|
public string Nombre { get; set; } = null!;
|
||||||
|
public string? NombreCorto { get; set; } // Para leyendas y gráficos
|
||||||
|
public string? Color { get; set; } // Código hexadecimal, ej: "#1f77b4"
|
||||||
|
public string? LogoUrl { get; set; } // URL a la imagen del logo
|
||||||
|
// Puede ser nulo si una agrupación no tiene una posición definida.
|
||||||
|
public int? OrdenDiputados { get; set; }
|
||||||
|
public int? OrdenSenadores { get; set; }
|
||||||
}
|
}
|
||||||
23
Elecciones-Web/src/Elecciones.Database/Entities/Bancada.cs
Normal file
23
Elecciones-Web/src/Elecciones.Database/Entities/Bancada.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// src/Elecciones.Database/Entities/Bancada.cs
|
||||||
|
using Elecciones.Core.Enums;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Entities;
|
||||||
|
|
||||||
|
public class Bancada
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public TipoCamara Camara { get; set; }
|
||||||
|
|
||||||
|
public string? AgrupacionPoliticaId { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("AgrupacionPoliticaId")]
|
||||||
|
public AgrupacionPolitica? AgrupacionPolitica { get; set; }
|
||||||
|
|
||||||
|
// Relación uno a uno con OcupanteBanca
|
||||||
|
public OcupanteBanca? Ocupante { get; set; }
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// src/Elecciones.Database/Entities/Configuracion.cs
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Entities;
|
||||||
|
|
||||||
|
public class Configuracion
|
||||||
|
{
|
||||||
|
[Key] // La clave será un string, ej: "PresidenciaDiputados"
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string Clave { get; set; } = null!;
|
||||||
|
|
||||||
|
// El valor será el ID de la AgrupacionPolitica
|
||||||
|
[MaxLength(100)]
|
||||||
|
public string Valor { get; set; } = null!;
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
// src/Elecciones.Database/Entities/OcupanteBanca.cs
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Entities;
|
||||||
|
|
||||||
|
public class OcupanteBanca
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
// Esta será la clave primaria y foránea para la relación 1-a-1
|
||||||
|
public int BancadaId { get; set; }
|
||||||
|
|
||||||
|
[ForeignKey("BancadaId")]
|
||||||
|
public Bancada Bancada { get; set; } = null!;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string NombreOcupante { get; set; } = null!;
|
||||||
|
|
||||||
|
public string? FotoUrl { get; set; }
|
||||||
|
|
||||||
|
public string? Periodo { get; set; }
|
||||||
|
}
|
||||||
468
Elecciones-Web/src/Elecciones.Database/Migrations/20250825184951_AddConfigBancas.Designer.cs
generated
Normal file
468
Elecciones-Web/src/Elecciones.Database/Migrations/20250825184951_AddConfigBancas.Designer.cs
generated
Normal file
@@ -0,0 +1,468 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Elecciones.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(EleccionesDbContext))]
|
||||||
|
[Migration("20250825184951_AddConfigBancas")]
|
||||||
|
partial class AddConfigBancas
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.UseCollation("Modern_Spanish_CI_AS")
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("ComposicionBancada", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("BancasEnJuego")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("BancasTotales")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Camara")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.ToTable("ComposicionBancadas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Color")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("IdTelegrama")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreCorto")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AgrupacionesPoliticas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AmbitoGeografico", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CircuitoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("DistritoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("EstablecimientoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MesaId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MunicipioId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("NivelId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionProvincialId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AmbitosGeograficos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Orden")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CategoriasElectorales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosEnBlanco")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosEnBlancoPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosNulos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosNulosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosRecurridos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosRecurridosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.HasIndex("CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentosGenerales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("NroBancas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ProyeccionesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("CantidadVotos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("PorcentajeVotos")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ResultadosVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Votos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ResumenesVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Telegrama", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ContenidoBase64")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaEscaneo")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Telegramas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("ComposicionBancadaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("FotoUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreOcupante")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Periodo")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ComposicionBancadaId");
|
||||||
|
|
||||||
|
b.ToTable("OcupantesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("ComposicionBancada", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.CategoriaElectoral", "CategoriaElectoral")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CategoriaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("CategoriaElectoral");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("ComposicionBancada", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ComposicionBancadaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddConfigBancas : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterDatabase(
|
||||||
|
collation: "Modern_Spanish_CI_AS");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "Color",
|
||||||
|
table: "AgrupacionesPoliticas",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "LogoUrl",
|
||||||
|
table: "AgrupacionesPoliticas",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "NombreCorto",
|
||||||
|
table: "AgrupacionesPoliticas",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ComposicionBancadas",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
AgrupacionPoliticaId = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||||
|
Camara = table.Column<int>(type: "int", nullable: false),
|
||||||
|
BancasTotales = table.Column<int>(type: "int", nullable: false),
|
||||||
|
BancasEnJuego = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ComposicionBancadas", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ComposicionBancadas_AgrupacionesPoliticas_AgrupacionPoliticaId",
|
||||||
|
column: x => x.AgrupacionPoliticaId,
|
||||||
|
principalTable: "AgrupacionesPoliticas",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "OcupantesBancas",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
ComposicionBancadaId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
NombreOcupante = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
FotoUrl = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
Periodo = table.Column<string>(type: "nvarchar(max)", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_OcupantesBancas", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_OcupantesBancas_ComposicionBancadas_ComposicionBancadaId",
|
||||||
|
column: x => x.ComposicionBancadaId,
|
||||||
|
principalTable: "ComposicionBancadas",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ComposicionBancadas_AgrupacionPoliticaId",
|
||||||
|
table: "ComposicionBancadas",
|
||||||
|
column: "AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_OcupantesBancas_ComposicionBancadaId",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
column: "ComposicionBancadaId");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "OcupantesBancas");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ComposicionBancadas");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "Color",
|
||||||
|
table: "AgrupacionesPoliticas");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "LogoUrl",
|
||||||
|
table: "AgrupacionesPoliticas");
|
||||||
|
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "NombreCorto",
|
||||||
|
table: "AgrupacionesPoliticas");
|
||||||
|
|
||||||
|
migrationBuilder.AlterDatabase(
|
||||||
|
oldCollation: "Modern_Spanish_CI_AS");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
494
Elecciones-Web/src/Elecciones.Database/Migrations/20250826003245_AddAdminUserTable.Designer.cs
generated
Normal file
494
Elecciones-Web/src/Elecciones.Database/Migrations/20250826003245_AddAdminUserTable.Designer.cs
generated
Normal file
@@ -0,0 +1,494 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Elecciones.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(EleccionesDbContext))]
|
||||||
|
[Migration("20250826003245_AddAdminUserTable")]
|
||||||
|
partial class AddAdminUserTable
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.UseCollation("Modern_Spanish_CI_AS")
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("ComposicionBancada", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("BancasEnJuego")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("BancasTotales")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Camara")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.ToTable("ComposicionBancadas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AdminUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordSalt")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AdminUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Color")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("IdTelegrama")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreCorto")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AgrupacionesPoliticas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AmbitoGeografico", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CircuitoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("DistritoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("EstablecimientoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MesaId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MunicipioId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("NivelId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionProvincialId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AmbitosGeograficos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Orden")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CategoriasElectorales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosEnBlanco")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosEnBlancoPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosNulos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosNulosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosRecurridos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosRecurridosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.HasIndex("CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentosGenerales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("NroBancas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ProyeccionesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("CantidadVotos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("PorcentajeVotos")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ResultadosVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Votos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ResumenesVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Telegrama", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ContenidoBase64")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaEscaneo")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Telegramas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("ComposicionBancadaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("FotoUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreOcupante")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Periodo")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ComposicionBancadaId");
|
||||||
|
|
||||||
|
b.ToTable("OcupantesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("ComposicionBancada", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.CategoriaElectoral", "CategoriaElectoral")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CategoriaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("CategoriaElectoral");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("ComposicionBancada", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ComposicionBancadaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddAdminUserTable : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "AdminUsers",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
Username = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
|
PasswordHash = table.Column<string>(type: "nvarchar(max)", nullable: false),
|
||||||
|
PasswordSalt = table.Column<string>(type: "nvarchar(max)", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_AdminUsers", x => x.Id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "AdminUsers");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,497 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Elecciones.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(EleccionesDbContext))]
|
||||||
|
[Migration("20250826023006_AddOrdenIdeologicoToAgrupaciones")]
|
||||||
|
partial class AddOrdenIdeologicoToAgrupaciones
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.UseCollation("Modern_Spanish_CI_AS")
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("ComposicionBancada", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("BancasEnJuego")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("BancasTotales")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Camara")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.ToTable("ComposicionBancadas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AdminUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordSalt")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AdminUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Color")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("IdTelegrama")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreCorto")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int?>("OrdenIdeologico")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AgrupacionesPoliticas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AmbitoGeografico", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CircuitoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("DistritoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("EstablecimientoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MesaId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MunicipioId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("NivelId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionProvincialId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AmbitosGeograficos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Orden")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CategoriasElectorales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosEnBlanco")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosEnBlancoPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosNulos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosNulosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosRecurridos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosRecurridosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.HasIndex("CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentosGenerales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("NroBancas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ProyeccionesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("CantidadVotos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("PorcentajeVotos")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ResultadosVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Votos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ResumenesVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Telegrama", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ContenidoBase64")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaEscaneo")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Telegramas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("ComposicionBancadaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("FotoUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreOcupante")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Periodo")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ComposicionBancadaId");
|
||||||
|
|
||||||
|
b.ToTable("OcupantesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("ComposicionBancada", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.CategoriaElectoral", "CategoriaElectoral")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CategoriaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("CategoriaElectoral");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("ComposicionBancada", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ComposicionBancadaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddOrdenIdeologicoToAgrupaciones : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "OrdenIdeologico",
|
||||||
|
table: "AgrupacionesPoliticas",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "OrdenIdeologico",
|
||||||
|
table: "AgrupacionesPoliticas");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,500 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Elecciones.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(EleccionesDbContext))]
|
||||||
|
[Migration("20250826155219_AddOrdenPorCamaraToAgrupaciones")]
|
||||||
|
partial class AddOrdenPorCamaraToAgrupaciones
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.UseCollation("Modern_Spanish_CI_AS")
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AdminUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordSalt")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AdminUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Color")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("IdTelegrama")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreCorto")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int?>("OrdenDiputados")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("OrdenSenadores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AgrupacionesPoliticas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AmbitoGeografico", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CircuitoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("DistritoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("EstablecimientoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MesaId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MunicipioId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("NivelId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionProvincialId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AmbitosGeograficos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Orden")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CategoriasElectorales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ComposicionBancada", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("BancasEnJuego")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("BancasTotales")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Camara")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.ToTable("ComposicionBancadas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosEnBlanco")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosEnBlancoPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosNulos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosNulosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosRecurridos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosRecurridosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.HasIndex("CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentosGenerales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("NroBancas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ProyeccionesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("CantidadVotos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("PorcentajeVotos")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ResultadosVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Votos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ResumenesVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Telegrama", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ContenidoBase64")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaEscaneo")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Telegramas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("ComposicionBancadaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("FotoUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreOcupante")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Periodo")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ComposicionBancadaId");
|
||||||
|
|
||||||
|
b.ToTable("OcupantesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ComposicionBancada", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.CategoriaElectoral", "CategoriaElectoral")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CategoriaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("CategoriaElectoral");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.ComposicionBancada", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ComposicionBancadaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddOrdenPorCamaraToAgrupaciones : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "OrdenIdeologico",
|
||||||
|
table: "AgrupacionesPoliticas",
|
||||||
|
newName: "OrdenSenadores");
|
||||||
|
|
||||||
|
migrationBuilder.AddColumn<int>(
|
||||||
|
name: "OrdenDiputados",
|
||||||
|
table: "AgrupacionesPoliticas",
|
||||||
|
type: "int",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "OrdenDiputados",
|
||||||
|
table: "AgrupacionesPoliticas");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "OrdenSenadores",
|
||||||
|
table: "AgrupacionesPoliticas",
|
||||||
|
newName: "OrdenIdeologico");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
516
Elecciones-Web/src/Elecciones.Database/Migrations/20250827152442_AddConfiguracionTable.Designer.cs
generated
Normal file
516
Elecciones-Web/src/Elecciones.Database/Migrations/20250827152442_AddConfiguracionTable.Designer.cs
generated
Normal file
@@ -0,0 +1,516 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Elecciones.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(EleccionesDbContext))]
|
||||||
|
[Migration("20250827152442_AddConfiguracionTable")]
|
||||||
|
partial class AddConfiguracionTable
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.UseCollation("Modern_Spanish_CI_AS")
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AdminUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordSalt")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AdminUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Color")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("IdTelegrama")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreCorto")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int?>("OrdenDiputados")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("OrdenSenadores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AgrupacionesPoliticas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AmbitoGeografico", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CircuitoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("DistritoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("EstablecimientoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MesaId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MunicipioId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("NivelId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionProvincialId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AmbitosGeograficos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Orden")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CategoriasElectorales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ComposicionBancada", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("BancasEnJuego")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("BancasTotales")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("Camara")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.ToTable("ComposicionBancadas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Configuracion", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Clave")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<string>("Valor")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Clave");
|
||||||
|
|
||||||
|
b.ToTable("Configuraciones");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosEnBlanco")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosEnBlancoPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosNulos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosNulosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosRecurridos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosRecurridosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.HasIndex("CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentosGenerales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("NroBancas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ProyeccionesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("CantidadVotos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("PorcentajeVotos")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ResultadosVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Votos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ResumenesVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Telegrama", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ContenidoBase64")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaEscaneo")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Telegramas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("ComposicionBancadaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("FotoUrl")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreOcupante")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Periodo")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("ComposicionBancadaId");
|
||||||
|
|
||||||
|
b.ToTable("OcupantesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ComposicionBancada", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.CategoriaElectoral", "CategoriaElectoral")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CategoriaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("CategoriaElectoral");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.ComposicionBancada", null)
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("ComposicionBancadaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddConfiguracionTable : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Configuraciones",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Clave = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false),
|
||||||
|
Valor = table.Column<string>(type: "nvarchar(100)", maxLength: 100, nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Configuraciones", x => x.Clave);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Configuraciones");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,513 @@
|
|||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Elecciones.Database;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Metadata;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(EleccionesDbContext))]
|
||||||
|
[Migration("20250828174425_AddBancadasAndOcupantesSchema")]
|
||||||
|
partial class AddBancadasAndOcupantesSchema
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.UseCollation("Modern_Spanish_CI_AS")
|
||||||
|
.HasAnnotation("ProductVersion", "9.0.8")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AdminUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordSalt")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AdminUsers");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Color")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("IdTelegrama")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreCorto")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int?>("OrdenDiputados")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("OrdenSenadores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AgrupacionesPoliticas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AmbitoGeografico", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("CircuitoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("DistritoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("EstablecimientoId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MesaId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("MunicipioId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("NivelId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("SeccionProvincialId")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AmbitosGeograficos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("Camara")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.ToTable("Bancadas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("Nombre")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("Orden")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("CategoriasElectorales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Configuracion", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Clave")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<string>("Valor")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Clave");
|
||||||
|
|
||||||
|
b.ToTable("Configuraciones");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosEnBlanco")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosEnBlancoPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosNulos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosNulosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.Property<long>("VotosRecurridos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosRecurridosPorcentaje")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadElectores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CantidadVotantes")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("MesasEsperadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("MesasTotalizadas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("MesasTotalizadasPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.Property<decimal>("ParticipacionPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("AmbitoGeograficoId", "CategoriaId");
|
||||||
|
|
||||||
|
b.HasIndex("CategoriaId");
|
||||||
|
|
||||||
|
b.ToTable("EstadosRecuentosGenerales");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("BancadaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("FotoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreOcupante")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Periodo")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BancadaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("OcupantesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<int>("NroBancas")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ProyeccionesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<long>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<long>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("CantidadVotos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<int>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<decimal>("PorcentajeVotos")
|
||||||
|
.HasPrecision(18, 4)
|
||||||
|
.HasColumnType("decimal(18,4)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.HasIndex("AmbitoGeograficoId", "CategoriaId", "AgrupacionPoliticaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("ResultadosVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<long>("Votos")
|
||||||
|
.HasColumnType("bigint");
|
||||||
|
|
||||||
|
b.Property<decimal>("VotosPorcentaje")
|
||||||
|
.HasPrecision(5, 2)
|
||||||
|
.HasColumnType("decimal(5,2)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("ResumenesVotos");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Telegrama", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Id")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("ContenidoBase64")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaEscaneo")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.Property<DateTime>("FechaTotalizacion")
|
||||||
|
.HasColumnType("datetime2");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("Telegramas");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuentoGeneral", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.CategoriaElectoral", "CategoriaElectoral")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("CategoriaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("CategoriaElectoral");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.Bancada", "Bancada")
|
||||||
|
.WithOne("Ocupante")
|
||||||
|
.HasForeignKey("Elecciones.Database.Entities.OcupanteBanca", "BancadaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Bancada");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResultadoVoto", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AmbitoGeograficoId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
|
||||||
|
b.Navigation("AmbitoGeografico");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Ocupante");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,164 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddBancadasAndOcupantesSchema : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_OcupantesBancas_ComposicionBancadas_ComposicionBancadaId",
|
||||||
|
table: "OcupantesBancas");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "ComposicionBancadas");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_OcupantesBancas_ComposicionBancadaId",
|
||||||
|
table: "OcupantesBancas");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "ComposicionBancadaId",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
newName: "BancadaId");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Periodo",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "nvarchar(max)");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "FotoUrl",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "nvarchar(max)");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "Bancadas",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
Camara = table.Column<int>(type: "int", nullable: false),
|
||||||
|
AgrupacionPoliticaId = table.Column<string>(type: "nvarchar(450)", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_Bancadas", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_Bancadas_AgrupacionesPoliticas_AgrupacionPoliticaId",
|
||||||
|
column: x => x.AgrupacionPoliticaId,
|
||||||
|
principalTable: "AgrupacionesPoliticas",
|
||||||
|
principalColumn: "Id");
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_OcupantesBancas_BancadaId",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
column: "BancadaId",
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_Bancadas_AgrupacionPoliticaId",
|
||||||
|
table: "Bancadas",
|
||||||
|
column: "AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_OcupantesBancas_Bancadas_BancadaId",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
column: "BancadaId",
|
||||||
|
principalTable: "Bancadas",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_OcupantesBancas_Bancadas_BancadaId",
|
||||||
|
table: "OcupantesBancas");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "Bancadas");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_OcupantesBancas_BancadaId",
|
||||||
|
table: "OcupantesBancas");
|
||||||
|
|
||||||
|
migrationBuilder.RenameColumn(
|
||||||
|
name: "BancadaId",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
newName: "ComposicionBancadaId");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "Periodo",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "",
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "nvarchar(max)",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "FotoUrl",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: false,
|
||||||
|
defaultValue: "",
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "nvarchar(max)",
|
||||||
|
oldNullable: true);
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "ComposicionBancadas",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<int>(type: "int", nullable: false)
|
||||||
|
.Annotation("SqlServer:Identity", "1, 1"),
|
||||||
|
AgrupacionPoliticaId = table.Column<string>(type: "nvarchar(450)", nullable: false),
|
||||||
|
BancasEnJuego = table.Column<int>(type: "int", nullable: false),
|
||||||
|
BancasTotales = table.Column<int>(type: "int", nullable: false),
|
||||||
|
Camara = table.Column<int>(type: "int", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_ComposicionBancadas", x => x.Id);
|
||||||
|
table.ForeignKey(
|
||||||
|
name: "FK_ComposicionBancadas_AgrupacionesPoliticas_AgrupacionPoliticaId",
|
||||||
|
column: x => x.AgrupacionPoliticaId,
|
||||||
|
principalTable: "AgrupacionesPoliticas",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_OcupantesBancas_ComposicionBancadaId",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
column: "ComposicionBancadaId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ComposicionBancadas_AgrupacionPoliticaId",
|
||||||
|
table: "ComposicionBancadas",
|
||||||
|
column: "AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_OcupantesBancas_ComposicionBancadas_ComposicionBancadaId",
|
||||||
|
table: "OcupantesBancas",
|
||||||
|
column: "ComposicionBancadaId",
|
||||||
|
principalTable: "ComposicionBancadas",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -17,24 +17,66 @@ namespace Elecciones.Database.Migrations
|
|||||||
{
|
{
|
||||||
#pragma warning disable 612, 618
|
#pragma warning disable 612, 618
|
||||||
modelBuilder
|
modelBuilder
|
||||||
|
.UseCollation("Modern_Spanish_CI_AS")
|
||||||
.HasAnnotation("ProductVersion", "9.0.8")
|
.HasAnnotation("ProductVersion", "9.0.8")
|
||||||
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
.HasAnnotation("Relational:MaxIdentifierLength", 128);
|
||||||
|
|
||||||
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.AdminUser", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordSalt")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Username")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.ToTable("AdminUsers");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b =>
|
modelBuilder.Entity("Elecciones.Database.Entities.AgrupacionPolitica", b =>
|
||||||
{
|
{
|
||||||
b.Property<string>("Id")
|
b.Property<string>("Id")
|
||||||
.HasColumnType("nvarchar(450)");
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<string>("Color")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
b.Property<string>("IdTelegrama")
|
b.Property<string>("IdTelegrama")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
b.Property<string>("Nombre")
|
b.Property<string>("Nombre")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreCorto")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<int?>("OrdenDiputados")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<int?>("OrdenSenadores")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
b.ToTable("AgrupacionesPoliticas");
|
b.ToTable("AgrupacionesPoliticas");
|
||||||
@@ -81,6 +123,27 @@ namespace Elecciones.Database.Migrations
|
|||||||
b.ToTable("AmbitosGeograficos");
|
b.ToTable("AmbitosGeograficos");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
|
b.Property<int>("Camara")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.ToTable("Bancadas");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b =>
|
modelBuilder.Entity("Elecciones.Database.Entities.CategoriaElectoral", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -98,6 +161,22 @@ namespace Elecciones.Database.Migrations
|
|||||||
b.ToTable("CategoriasElectorales");
|
b.ToTable("CategoriasElectorales");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Configuracion", b =>
|
||||||
|
{
|
||||||
|
b.Property<string>("Clave")
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.Property<string>("Valor")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(100)
|
||||||
|
.HasColumnType("nvarchar(100)");
|
||||||
|
|
||||||
|
b.HasKey("Clave");
|
||||||
|
|
||||||
|
b.ToTable("Configuraciones");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("AmbitoGeograficoId")
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
@@ -193,6 +272,35 @@ namespace Elecciones.Database.Migrations
|
|||||||
b.ToTable("EstadosRecuentosGenerales");
|
b.ToTable("EstadosRecuentosGenerales");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.Property<int>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
SqlServerPropertyBuilderExtensions.UseIdentityColumn(b.Property<int>("Id"));
|
||||||
|
|
||||||
|
b.Property<int>("BancadaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("FotoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("NombreOcupante")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.Property<string>("Periodo")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("BancadaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("OcupantesBancas");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -312,6 +420,15 @@ namespace Elecciones.Database.Migrations
|
|||||||
b.ToTable("Telegramas");
|
b.ToTable("Telegramas");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
modelBuilder.Entity("Elecciones.Database.Entities.EstadoRecuento", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
b.HasOne("Elecciones.Database.Entities.AmbitoGeografico", "AmbitoGeografico")
|
||||||
@@ -334,6 +451,17 @@ namespace Elecciones.Database.Migrations
|
|||||||
b.Navigation("CategoriaElectoral");
|
b.Navigation("CategoriaElectoral");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.OcupanteBanca", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.Bancada", "Bancada")
|
||||||
|
.WithOne("Ocupante")
|
||||||
|
.HasForeignKey("Elecciones.Database.Entities.OcupanteBanca", "BancadaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("Bancada");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
modelBuilder.Entity("Elecciones.Database.Entities.ProyeccionBanca", b =>
|
||||||
{
|
{
|
||||||
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
@@ -371,6 +499,11 @@ namespace Elecciones.Database.Migrations
|
|||||||
|
|
||||||
b.Navigation("AmbitoGeografico");
|
b.Navigation("AmbitoGeografico");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Ocupante");
|
||||||
|
});
|
||||||
#pragma warning restore 612, 618
|
#pragma warning restore 612, 618
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
".NETCoreApp,Version=v9.0": {
|
".NETCoreApp,Version=v9.0": {
|
||||||
"Elecciones.Database/1.0.0": {
|
"Elecciones.Database/1.0.0": {
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"Elecciones.Core": "1.0.0",
|
||||||
"Microsoft.EntityFrameworkCore.Design": "9.0.8",
|
"Microsoft.EntityFrameworkCore.Design": "9.0.8",
|
||||||
"Microsoft.EntityFrameworkCore.SqlServer": "9.0.8"
|
"Microsoft.EntityFrameworkCore.SqlServer": "9.0.8"
|
||||||
},
|
},
|
||||||
@@ -1001,6 +1002,14 @@
|
|||||||
"fileVersion": "6.0.21.52210"
|
"fileVersion": "6.0.21.52210"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"Elecciones.Core/1.0.0": {
|
||||||
|
"runtime": {
|
||||||
|
"Elecciones.Core.dll": {
|
||||||
|
"assemblyVersion": "1.0.0.0",
|
||||||
|
"fileVersion": "1.0.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -1555,6 +1564,11 @@
|
|||||||
"sha512": "sha512-IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==",
|
"sha512": "sha512-IXoJOXIqc39AIe+CIR7koBtRGMiCt/LPM3lI+PELtDIy9XdyeSrwXFdWV9dzJ2Awl0paLWUaknLxFQ5HpHZUog==",
|
||||||
"path": "system.windows.extensions/6.0.0",
|
"path": "system.windows.extensions/6.0.0",
|
||||||
"hashPath": "system.windows.extensions.6.0.0.nupkg.sha512"
|
"hashPath": "system.windows.extensions.6.0.0.nupkg.sha512"
|
||||||
|
},
|
||||||
|
"Elecciones.Core/1.0.0": {
|
||||||
|
"type": "project",
|
||||||
|
"serviceable": false,
|
||||||
|
"sha512": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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+0d33db9e6dc7807fbb1853c621b81002ea764411")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+55954e18a797dce22f76f00b645832f361d97362")]
|
||||||
[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")]
|
||||||
|
|||||||
@@ -12,3 +12,6 @@ E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Debug\net9.0\refin
|
|||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Debug\net9.0\Elecciones.Database.pdb
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Debug\net9.0\Elecciones.Database.pdb
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Debug\net9.0\Elecciones.Database.genruntimeconfig.cache
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Debug\net9.0\Elecciones.Database.genruntimeconfig.cache
|
||||||
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Debug\net9.0\ref\Elecciones.Database.dll
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Debug\net9.0\ref\Elecciones.Database.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\bin\Debug\net9.0\Elecciones.Core.dll
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\bin\Debug\net9.0\Elecciones.Core.pdb
|
||||||
|
E:\Elecciones-2025\Elecciones-Web\src\Elecciones.Database\obj\Debug\net9.0\Eleccion.FD0E0EFF.Up2Date
|
||||||
|
|||||||
@@ -4,6 +4,71 @@
|
|||||||
"E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Database\\Elecciones.Database.csproj": {}
|
"E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Database\\Elecciones.Database.csproj": {}
|
||||||
},
|
},
|
||||||
"projects": {
|
"projects": {
|
||||||
|
"E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"restore": {
|
||||||
|
"projectUniqueName": "E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj",
|
||||||
|
"projectName": "Elecciones.Core",
|
||||||
|
"projectPath": "E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj",
|
||||||
|
"packagesPath": "C:\\Users\\dmolinari\\.nuget\\packages\\",
|
||||||
|
"outputPath": "E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\obj\\",
|
||||||
|
"projectStyle": "PackageReference",
|
||||||
|
"fallbackFolders": [
|
||||||
|
"D:\\Microsoft\\VisualStudio\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||||
|
],
|
||||||
|
"configFilePaths": [
|
||||||
|
"C:\\Users\\dmolinari\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||||
|
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||||
|
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||||
|
],
|
||||||
|
"originalTargetFrameworks": [
|
||||||
|
"net9.0"
|
||||||
|
],
|
||||||
|
"sources": {
|
||||||
|
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||||
|
"https://api.nuget.org/v3/index.json": {}
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"net9.0": {
|
||||||
|
"targetAlias": "net9.0",
|
||||||
|
"projectReferences": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"warningProperties": {
|
||||||
|
"warnAsError": [
|
||||||
|
"NU1605"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"restoreAuditProperties": {
|
||||||
|
"enableAudit": "true",
|
||||||
|
"auditLevel": "low",
|
||||||
|
"auditMode": "direct"
|
||||||
|
},
|
||||||
|
"SdkAnalysisLevel": "9.0.300"
|
||||||
|
},
|
||||||
|
"frameworks": {
|
||||||
|
"net9.0": {
|
||||||
|
"targetAlias": "net9.0",
|
||||||
|
"imports": [
|
||||||
|
"net461",
|
||||||
|
"net462",
|
||||||
|
"net47",
|
||||||
|
"net471",
|
||||||
|
"net472",
|
||||||
|
"net48",
|
||||||
|
"net481"
|
||||||
|
],
|
||||||
|
"assetTargetFallback": true,
|
||||||
|
"warn": true,
|
||||||
|
"frameworkReferences": {
|
||||||
|
"Microsoft.NETCore.App": {
|
||||||
|
"privateAssets": "all"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.300/PortableRuntimeIdentifierGraph.json"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Database\\Elecciones.Database.csproj": {
|
"E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Database\\Elecciones.Database.csproj": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"restore": {
|
"restore": {
|
||||||
@@ -31,7 +96,11 @@
|
|||||||
"frameworks": {
|
"frameworks": {
|
||||||
"net9.0": {
|
"net9.0": {
|
||||||
"targetAlias": "net9.0",
|
"targetAlias": "net9.0",
|
||||||
"projectReferences": {}
|
"projectReferences": {
|
||||||
|
"E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj": {
|
||||||
|
"projectPath": "E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"warningProperties": {
|
"warningProperties": {
|
||||||
|
|||||||
@@ -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+0d33db9e6dc7807fbb1853c621b81002ea764411")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+55954e18a797dce22f76f00b645832f361d97362")]
|
||||||
[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")]
|
||||||
|
|||||||
@@ -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+18e6e8d3c0a378a172ad8e8afd31109673460717")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+55954e18a797dce22f76f00b645832f361d97362")]
|
||||||
[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")]
|
||||||
|
|||||||
@@ -96,7 +96,11 @@
|
|||||||
"frameworks": {
|
"frameworks": {
|
||||||
"net9.0": {
|
"net9.0": {
|
||||||
"targetAlias": "net9.0",
|
"targetAlias": "net9.0",
|
||||||
"projectReferences": {}
|
"projectReferences": {
|
||||||
|
"E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj": {
|
||||||
|
"projectPath": "E:\\Elecciones-2025\\Elecciones-Web\\src\\Elecciones.Core\\Elecciones.Core.csproj"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"warningProperties": {
|
"warningProperties": {
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
/**
|
|
||||||
* PDF.js worker entry file.
|
|
||||||
*
|
|
||||||
* This file is identical to Mozilla's pdf.worker.entry.js, with one exception being placed inside
|
|
||||||
* this bundle, not theirs.
|
|
||||||
*/
|
|
||||||
(typeof window !== 'undefined' ? window : {}).pdfjsWorker =
|
|
||||||
// @ts-expect-error - pdfjs-dist does not ship with types
|
|
||||||
await import('pdfjs-dist/build/pdf.worker.mjs');
|
|
||||||
export {};
|
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
// reconcile_ids.js
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const http = require('http');
|
|
||||||
|
|
||||||
// --- CONFIGURACIÓN ---
|
|
||||||
const API_URL = 'http://localhost:5217/api/catalogos/municipios'; // ¡Asegúrate que tu API esté corriendo en este puerto!
|
|
||||||
const GEOJSON_PATH = path.join(__dirname, 'Elecciones-Web', 'frontend', 'public', 'buenos-aires-municipios.geojson');
|
|
||||||
const OUTPUT_PATH = path.join(__dirname, 'Elecciones-Web', 'frontend', 'public', 'municipioIdMap.json');
|
|
||||||
|
|
||||||
const normalizeString = (str) => {
|
|
||||||
if (!str) return '';
|
|
||||||
return str.normalize("NFD").replace(/[\u0300-\u036f]/g, "").toLowerCase();
|
|
||||||
};
|
|
||||||
|
|
||||||
async function reconcile() {
|
|
||||||
console.log('Iniciando el script de reconciliación de IDs...');
|
|
||||||
|
|
||||||
try {
|
|
||||||
const apiData = await new Promise((resolve, reject) => {
|
|
||||||
http.get(API_URL, res => {
|
|
||||||
const { statusCode } = res;
|
|
||||||
if (statusCode !== 200) {
|
|
||||||
reject(new Error(`La petición a la API falló con el código de estado: ${statusCode}`));
|
|
||||||
res.resume();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let data = '';
|
|
||||||
res.on('data', chunk => data += chunk);
|
|
||||||
res.on('end', () => resolve(JSON.parse(data)));
|
|
||||||
}).on('error', reject);
|
|
||||||
});
|
|
||||||
console.log(`Se obtuvieron ${apiData.length} municipios desde la API.`);
|
|
||||||
|
|
||||||
const apiNameMap = new Map(apiData.map(m => [normalizeString(m.nombre), m.id]));
|
|
||||||
|
|
||||||
const geoJsonRaw = fs.readFileSync(GEOJSON_PATH, 'utf8');
|
|
||||||
const geoJsonData = JSON.parse(geoJsonRaw);
|
|
||||||
console.log(`Se leyeron ${geoJsonData.features.length} features desde el GeoJSON.`);
|
|
||||||
|
|
||||||
const finalIdMap = {};
|
|
||||||
let matches = 0;
|
|
||||||
const notFound = [];
|
|
||||||
|
|
||||||
// --- CAMBIO CLAVE: YA NO NECESITAMOS ALIAS MANUALES ---
|
|
||||||
|
|
||||||
for (const feature of geoJsonData.features) {
|
|
||||||
const geoJsonId = feature.properties.cca;
|
|
||||||
const nombreGeoJson = normalizeString(feature.properties.nam);
|
|
||||||
|
|
||||||
if (apiNameMap.has(nombreGeoJson)) {
|
|
||||||
const apiId = apiNameMap.get(nombreGeoJson);
|
|
||||||
finalIdMap[geoJsonId] = apiId;
|
|
||||||
matches++;
|
|
||||||
} else {
|
|
||||||
notFound.push(feature.properties.nam);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`\n--- RESULTADOS ---`);
|
|
||||||
console.log(`Coincidencias encontradas: ${matches} de ${geoJsonData.features.length}`);
|
|
||||||
if (notFound.length > 0) {
|
|
||||||
console.warn(`\nNo se encontró coincidencia para los siguientes ${notFound.length} municipios del GeoJSON:`);
|
|
||||||
console.warn(notFound.join(', '));
|
|
||||||
}
|
|
||||||
|
|
||||||
fs.writeFileSync(OUTPUT_PATH, JSON.stringify(finalIdMap, null, 2));
|
|
||||||
console.log(`\n¡Éxito! El mapa de IDs se ha guardado en: ${OUTPUT_PATH}`);
|
|
||||||
|
|
||||||
} catch (error) {
|
|
||||||
console.error('\nOcurrió un error:', error.message);
|
|
||||||
if(error.code === 'ECONNREFUSED') {
|
|
||||||
console.error('Asegúrate de que tu servicio de API esté corriendo en la URL especificada.');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
reconcile();
|
|
||||||
Reference in New Issue
Block a user