Feat Widgets
This commit is contained in:
@@ -1,113 +1,133 @@
|
|||||||
// src/components/AgrupacionesManager.tsx
|
// src/components/AgrupacionesManager.tsx
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { getAgrupaciones, updateAgrupacion } from '../services/apiService';
|
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
||||||
import type { AgrupacionPolitica, UpdateAgrupacionData } from '../types';
|
import { getAgrupaciones, updateAgrupacion, getLogos, updateLogos } from '../services/apiService';
|
||||||
|
import type { AgrupacionPolitica, LogoAgrupacionCategoria } from '../types';
|
||||||
import './AgrupacionesManager.css';
|
import './AgrupacionesManager.css';
|
||||||
|
|
||||||
|
const SENADORES_ID = 5;
|
||||||
|
const DIPUTADOS_ID = 6;
|
||||||
|
const CONCEJALES_ID = 7;
|
||||||
|
|
||||||
export const AgrupacionesManager = () => {
|
export const AgrupacionesManager = () => {
|
||||||
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
const queryClient = useQueryClient();
|
||||||
const [loading, setLoading] = useState(true);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [editedAgrupaciones, setEditedAgrupaciones] = useState<Record<string, Partial<AgrupacionPolitica>>>({});
|
||||||
const [editingId, setEditingId] = useState<string | null>(null);
|
const [editedLogos, setEditedLogos] = useState<LogoAgrupacionCategoria[]>([]);
|
||||||
const [formData, setFormData] = useState<UpdateAgrupacionData>({
|
|
||||||
nombreCorto: '',
|
// Query 1: Obtener agrupaciones
|
||||||
color: '#000000',
|
const { data: agrupaciones = [], isLoading: isLoadingAgrupaciones } = useQuery<AgrupacionPolitica[]>({
|
||||||
logoUrl: '',
|
queryKey: ['agrupaciones'],
|
||||||
|
queryFn: getAgrupaciones,
|
||||||
});
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
// Query 2: Obtener logos
|
||||||
fetchAgrupaciones();
|
const { data: logos = [], isLoading: isLoadingLogos } = useQuery<LogoAgrupacionCategoria[]>({
|
||||||
}, []);
|
queryKey: ['logos'],
|
||||||
|
queryFn: getLogos,
|
||||||
|
});
|
||||||
|
|
||||||
const fetchAgrupaciones = async () => {
|
// Usamos useEffect para reaccionar cuando los datos de 'logos' se cargan o cambian.
|
||||||
try {
|
useEffect(() => {
|
||||||
setLoading(true);
|
if (logos) {
|
||||||
const data = await getAgrupaciones();
|
setEditedLogos(logos);
|
||||||
setAgrupaciones(data);
|
|
||||||
} catch (err) {
|
|
||||||
setError('No se pudieron cargar las agrupaciones.');
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
}
|
||||||
|
}, [logos]);
|
||||||
|
|
||||||
|
// Usamos otro useEffect para reaccionar a los datos de 'agrupaciones'.
|
||||||
|
useEffect(() => {
|
||||||
|
if (agrupaciones) {
|
||||||
|
const initialEdits = Object.fromEntries(agrupaciones.map(a => [a.id, {}]));
|
||||||
|
setEditedAgrupaciones(initialEdits);
|
||||||
|
}
|
||||||
|
}, [agrupaciones]);
|
||||||
|
|
||||||
|
const handleInputChange = (id: string, field: 'nombreCorto' | 'color', value: string) => {
|
||||||
|
setEditedAgrupaciones(prev => ({
|
||||||
|
...prev,
|
||||||
|
[id]: { ...prev[id], [field]: value }
|
||||||
|
}));
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleEdit = (agrupacion: AgrupacionPolitica) => {
|
const handleLogoChange = (agrupacionId: string, categoriaId: number, value: string) => {
|
||||||
setEditingId(agrupacion.id);
|
setEditedLogos(prev => {
|
||||||
setFormData({
|
const newLogos = [...prev];
|
||||||
nombreCorto: agrupacion.nombreCorto || '',
|
const existing = newLogos.find(l => l.agrupacionPoliticaId === agrupacionId && l.categoriaId === categoriaId);
|
||||||
color: agrupacion.color || '#000000',
|
if (existing) {
|
||||||
logoUrl: agrupacion.logoUrl || '',
|
existing.logoUrl = value;
|
||||||
|
} else {
|
||||||
|
newLogos.push({ id: 0, agrupacionPoliticaId: agrupacionId, categoriaId, logoUrl: value });
|
||||||
|
}
|
||||||
|
return newLogos;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleCancel = () => {
|
const handleSaveAll = async () => {
|
||||||
setEditingId(null);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleSave = async (id: string) => {
|
|
||||||
try {
|
try {
|
||||||
await updateAgrupacion(id, formData);
|
const agrupacionPromises = Object.entries(editedAgrupaciones).map(([id, changes]) => {
|
||||||
setEditingId(null);
|
if (Object.keys(changes).length > 0) {
|
||||||
fetchAgrupaciones(); // Recargar datos para ver los cambios
|
const original = agrupaciones.find(a => a.id === id);
|
||||||
|
if (original) { // Chequeo de seguridad
|
||||||
|
return updateAgrupacion(id, { ...original, ...changes });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.resolve();
|
||||||
|
});
|
||||||
|
|
||||||
|
const logoPromise = updateLogos(editedLogos);
|
||||||
|
|
||||||
|
await Promise.all([...agrupacionPromises, logoPromise]);
|
||||||
|
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['agrupaciones'] });
|
||||||
|
queryClient.invalidateQueries({ queryKey: ['logos'] });
|
||||||
|
|
||||||
|
alert('¡Todos los cambios han sido guardados!');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
alert('Error al guardar los cambios.');
|
console.error("Error al guardar todo:", err);
|
||||||
|
alert("Ocurrió un error al guardar los cambios.");
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
const isLoading = isLoadingAgrupaciones || isLoadingLogos;
|
||||||
setFormData({ ...formData, [e.target.name]: e.target.value });
|
|
||||||
|
const getLogoUrl = (agrupacionId: string, categoriaId: number) => {
|
||||||
|
return editedLogos.find(l => l.agrupacionPoliticaId === agrupacionId && l.categoriaId === categoriaId)?.logoUrl || '';
|
||||||
};
|
};
|
||||||
|
|
||||||
if (loading) return <p>Cargando agrupaciones...</p>;
|
|
||||||
if (error) return <p style={{ color: 'red' }}>{error}</p>;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="admin-module">
|
<div className="admin-module">
|
||||||
<h3>Gestión de Agrupaciones Políticas</h3>
|
<h3>Gestión de Agrupaciones y Logos</h3>
|
||||||
<table>
|
{isLoading ? <p>Cargando...</p> : (
|
||||||
<thead>
|
<>
|
||||||
<tr>
|
<table>
|
||||||
<th>Nombre</th>
|
<thead>
|
||||||
<th>Nombre Corto</th>
|
<tr>
|
||||||
<th>Color</th>
|
<th>Nombre</th>
|
||||||
<th>Logo URL</th>
|
<th>Nombre Corto</th>
|
||||||
<th>Acciones</th>
|
<th>Color</th>
|
||||||
</tr>
|
<th>Logo Senadores</th>
|
||||||
</thead>
|
<th>Logo Diputados</th>
|
||||||
<tbody>
|
<th>Logo Concejales</th>
|
||||||
{agrupaciones.map((agrupacion) => (
|
</tr>
|
||||||
<tr key={agrupacion.id}>
|
</thead>
|
||||||
{editingId === agrupacion.id ? (
|
<tbody>
|
||||||
<>
|
{agrupaciones.map(agrupacion => (
|
||||||
|
<tr key={agrupacion.id}>
|
||||||
<td>{agrupacion.nombre}</td>
|
<td>{agrupacion.nombre}</td>
|
||||||
<td><input type="text" name="nombreCorto" value={formData.nombreCorto || ''} onChange={handleChange} /></td>
|
<td><input type="text" value={editedAgrupaciones[agrupacion.id]?.nombreCorto ?? agrupacion.nombreCorto ?? ''} onChange={(e) => handleInputChange(agrupacion.id, 'nombreCorto', e.target.value)} /></td>
|
||||||
<td><input type="color" name="color" value={formData.color || '#000000'} onChange={handleChange} /></td>
|
<td><input type="color" value={editedAgrupaciones[agrupacion.id]?.color ?? agrupacion.color ?? '#000000'} onChange={(e) => handleInputChange(agrupacion.id, 'color', e.target.value)} /></td>
|
||||||
<td><input type="text" name="logoUrl" value={formData.logoUrl || ''} onChange={handleChange} /></td>
|
<td><input type="text" placeholder="URL de la imagen" value={getLogoUrl(agrupacion.id, SENADORES_ID)} onChange={(e) => handleLogoChange(agrupacion.id, SENADORES_ID, e.target.value)} /></td>
|
||||||
<td>
|
<td><input type="text" placeholder="URL de la imagen" value={getLogoUrl(agrupacion.id, DIPUTADOS_ID)} onChange={(e) => handleLogoChange(agrupacion.id, DIPUTADOS_ID, e.target.value)} /></td>
|
||||||
<button onClick={() => handleSave(agrupacion.id)}>Guardar</button>
|
<td><input type="text" placeholder="URL de la imagen" value={getLogoUrl(agrupacion.id, CONCEJALES_ID)} onChange={(e) => handleLogoChange(agrupacion.id, CONCEJALES_ID, e.target.value)} /></td>
|
||||||
<button onClick={handleCancel}>Cancelar</button>
|
</tr>
|
||||||
</td>
|
))}
|
||||||
</>
|
</tbody>
|
||||||
) : (
|
</table>
|
||||||
<>
|
<button onClick={handleSaveAll} style={{ marginTop: '1rem' }}>
|
||||||
<td>{agrupacion.nombre}</td>
|
Guardar Todos los Cambios
|
||||||
<td>{agrupacion.nombreCorto}</td>
|
</button>
|
||||||
<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>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -10,6 +10,8 @@ export const ConfiguracionGeneral = () => {
|
|||||||
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
const [agrupaciones, setAgrupaciones] = useState<AgrupacionPolitica[]>([]);
|
||||||
const [loading, setLoading] = useState(true);
|
const [loading, setLoading] = useState(true);
|
||||||
const [error, setError] = useState<string | null>(null);
|
const [error, setError] = useState<string | null>(null);
|
||||||
|
const [tickerCantidad, setTickerCantidad] = useState('3');
|
||||||
|
const [concejalesCantidad, setConcejalesCantidad] = useState('5');
|
||||||
|
|
||||||
const [presidenciaSenadoId, setPresidenciaSenadoId] = useState<string>('');
|
const [presidenciaSenadoId, setPresidenciaSenadoId] = useState<string>('');
|
||||||
// Renombramos el estado para mayor claridad
|
// Renombramos el estado para mayor claridad
|
||||||
@@ -24,6 +26,8 @@ export const ConfiguracionGeneral = () => {
|
|||||||
setAgrupaciones(agrupacionesData);
|
setAgrupaciones(agrupacionesData);
|
||||||
setPresidenciaSenadoId(configData.PresidenciaSenadores || '');
|
setPresidenciaSenadoId(configData.PresidenciaSenadores || '');
|
||||||
setModoOficialActivo(configData.UsarDatosDeBancadasOficiales === 'true');
|
setModoOficialActivo(configData.UsarDatosDeBancadasOficiales === 'true');
|
||||||
|
setTickerCantidad(configData.TickerResultadosCantidad || '3');
|
||||||
|
setConcejalesCantidad(configData.ConcejalesResultadosCantidad || '5');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error("Error al cargar datos de configuración:", err);
|
console.error("Error al cargar datos de configuración:", err);
|
||||||
setError("No se pudieron cargar los datos necesarios para la configuración.");
|
setError("No se pudieron cargar los datos necesarios para la configuración.");
|
||||||
@@ -36,7 +40,9 @@ export const ConfiguracionGeneral = () => {
|
|||||||
try {
|
try {
|
||||||
await updateConfiguracion({
|
await updateConfiguracion({
|
||||||
"PresidenciaSenadores": presidenciaSenadoId,
|
"PresidenciaSenadores": presidenciaSenadoId,
|
||||||
"UsarDatosDeBancadasOficiales": modoOficialActivo.toString()
|
"UsarDatosDeBancadasOficiales": modoOficialActivo.toString(),
|
||||||
|
"TickerResultadosCantidad": tickerCantidad,
|
||||||
|
"ConcejalesResultadosCantidad": concejalesCantidad
|
||||||
});
|
});
|
||||||
await queryClient.invalidateQueries({ queryKey: ['composicionCongreso'] });
|
await queryClient.invalidateQueries({ queryKey: ['composicionCongreso'] });
|
||||||
await queryClient.invalidateQueries({ queryKey: ['bancadasDetalle'] });
|
await queryClient.invalidateQueries({ queryKey: ['bancadasDetalle'] });
|
||||||
@@ -89,7 +95,7 @@ export const ConfiguracionGeneral = () => {
|
|||||||
Seleccione el partido político al que pertenece el Vicegobernador. El asiento presidencial del Senado se pintará con el color de este partido.
|
Seleccione el partido político al que pertenece el Vicegobernador. El asiento presidencial del Senado se pintará con el color de este partido.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div style={{ marginTop: '1rem' }}>
|
<div style={{ marginTop: '1rem', borderBottom: '2px solid #eee' }}>
|
||||||
<p style={{ fontWeight: 'bold', margin: 0 }}>
|
<p style={{ fontWeight: 'bold', margin: 0 }}>
|
||||||
Presidencia Cámara de Diputados
|
Presidencia Cámara de Diputados
|
||||||
</p>
|
</p>
|
||||||
@@ -97,6 +103,19 @@ export const ConfiguracionGeneral = () => {
|
|||||||
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.
|
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>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
<div className="form-group" style={{ marginTop: '2rem' }}>
|
||||||
|
<label htmlFor="ticker-cantidad">Cantidad en Ticker (Dip/Sen)</label>
|
||||||
|
<input id="ticker-cantidad" type="number" value={tickerCantidad} onChange={e => setTickerCantidad(e.target.value)} />
|
||||||
|
</div>
|
||||||
|
<div className="form-group" style={{ marginTop: '2rem' }}>
|
||||||
|
<label htmlFor="concejales-cantidad">Cantidad en Widget Concejales</label>
|
||||||
|
<input
|
||||||
|
id="concejales-cantidad"
|
||||||
|
type="number"
|
||||||
|
value={concejalesCantidad}
|
||||||
|
onChange={e => setConcejalesCantidad(e.target.value)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<button onClick={handleSave} style={{ marginTop: '1.5rem' }}>
|
<button onClick={handleSave} style={{ marginTop: '1.5rem' }}>
|
||||||
Guardar Configuración
|
Guardar Configuración
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
// src/services/apiService.ts
|
// src/services/apiService.ts
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { triggerLogout } from '../context/authUtils';
|
import { triggerLogout } from '../context/authUtils';
|
||||||
import type { AgrupacionPolitica, UpdateAgrupacionData, Bancada } from '../types';
|
import type { AgrupacionPolitica, UpdateAgrupacionData, Bancada, LogoAgrupacionCategoria } from '../types';
|
||||||
|
|
||||||
const AUTH_API_URL = 'http://localhost:5217/api/auth';
|
const AUTH_API_URL = 'http://localhost:5217/api/auth';
|
||||||
const ADMIN_API_URL = 'http://localhost:5217/api/admin';
|
const ADMIN_API_URL = 'http://localhost:5217/api/admin';
|
||||||
@@ -94,4 +94,13 @@ export const getConfiguracion = async (): Promise<ConfiguracionResponse> => {
|
|||||||
|
|
||||||
export const updateConfiguracion = async (data: Record<string, string>): Promise<void> => {
|
export const updateConfiguracion = async (data: Record<string, string>): Promise<void> => {
|
||||||
await adminApiClient.put('/configuracion', data);
|
await adminApiClient.put('/configuracion', data);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getLogos = async (): Promise<LogoAgrupacionCategoria[]> => {
|
||||||
|
const response = await adminApiClient.get('/logos');
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateLogos = async (data: LogoAgrupacionCategoria[]): Promise<void> => {
|
||||||
|
await adminApiClient.put('/logos', data);
|
||||||
};
|
};
|
||||||
@@ -6,7 +6,6 @@ export interface AgrupacionPolitica {
|
|||||||
nombre: string;
|
nombre: string;
|
||||||
nombreCorto: string | null;
|
nombreCorto: string | null;
|
||||||
color: string | null;
|
color: string | null;
|
||||||
logoUrl: string | null;
|
|
||||||
ordenDiputados: number | null;
|
ordenDiputados: number | null;
|
||||||
ordenSenadores: number | null;
|
ordenSenadores: number | null;
|
||||||
}
|
}
|
||||||
@@ -14,7 +13,6 @@ export interface AgrupacionPolitica {
|
|||||||
export interface UpdateAgrupacionData {
|
export interface UpdateAgrupacionData {
|
||||||
nombreCorto: string | null;
|
nombreCorto: string | null;
|
||||||
color: string | null;
|
color: string | null;
|
||||||
logoUrl: string | null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TipoCamara = {
|
export const TipoCamara = {
|
||||||
@@ -40,4 +38,11 @@ export interface Bancada {
|
|||||||
agrupacionPoliticaId: string | null;
|
agrupacionPoliticaId: string | null;
|
||||||
agrupacionPolitica: AgrupacionPolitica | null;
|
agrupacionPolitica: AgrupacionPolitica | null;
|
||||||
ocupante: OcupanteBanca | null;
|
ocupante: OcupanteBanca | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LogoAgrupacionCategoria {
|
||||||
|
id: number;
|
||||||
|
agrupacionPoliticaId: string;
|
||||||
|
categoriaId: number;
|
||||||
|
logoUrl: string | null;
|
||||||
}
|
}
|
||||||
@@ -5,6 +5,7 @@ import { CongresoWidget } from './components/CongresoWidget'
|
|||||||
import MapaBsAs from './components/MapaBsAs'
|
import MapaBsAs from './components/MapaBsAs'
|
||||||
import { TickerWidget } from './components/TickerWidget'
|
import { TickerWidget } from './components/TickerWidget'
|
||||||
import { TelegramaWidget } from './components/TelegramaWidget'
|
import { TelegramaWidget } from './components/TelegramaWidget'
|
||||||
|
import { ConcejalesWidget } from './components/ConcejalesWidget'
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
return (
|
return (
|
||||||
@@ -12,6 +13,7 @@ function App() {
|
|||||||
<h1>Resultados Electorales - Provincia de Buenos Aires</h1>
|
<h1>Resultados Electorales - Provincia de Buenos Aires</h1>
|
||||||
<main>
|
<main>
|
||||||
<TickerWidget />
|
<TickerWidget />
|
||||||
|
<ConcejalesWidget />
|
||||||
<CongresoWidget />
|
<CongresoWidget />
|
||||||
<BancasWidget />
|
<BancasWidget />
|
||||||
<MapaBsAs />
|
<MapaBsAs />
|
||||||
|
|||||||
@@ -1,6 +1,13 @@
|
|||||||
// src/apiService.ts
|
// src/apiService.ts
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import type { ResumenProvincial, ProyeccionBancas, MunicipioSimple, TelegramaData, CatalogoItem } from './types/types';
|
import type { ProyeccionBancas, MunicipioSimple, TelegramaData, CatalogoItem, CategoriaResumen, ResultadoTicker } from './types/types';
|
||||||
|
|
||||||
|
const API_BASE_URL = 'http://localhost:5217/api';
|
||||||
|
|
||||||
|
const apiClient = axios.create({
|
||||||
|
baseURL: API_BASE_URL,
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
});
|
||||||
|
|
||||||
interface PartidoData {
|
interface PartidoData {
|
||||||
id: string;
|
id: string;
|
||||||
@@ -47,14 +54,13 @@ export interface BancadaDetalle {
|
|||||||
ocupante: OcupanteBanca | null;
|
ocupante: OcupanteBanca | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const API_BASE_URL = 'http://localhost:5217/api';
|
export interface ConfiguracionPublica {
|
||||||
|
TickerResultadosCantidad?: string;
|
||||||
|
ConcejalesResultadosCantidad?: string;
|
||||||
|
// ... otras claves públicas que pueda añadir en el futuro
|
||||||
|
}
|
||||||
|
|
||||||
const apiClient = axios.create({
|
export const getResumenProvincial = async (): Promise<CategoriaResumen[]> => {
|
||||||
baseURL: API_BASE_URL,
|
|
||||||
headers: { 'Content-Type': 'application/json' },
|
|
||||||
});
|
|
||||||
|
|
||||||
export const getResumenProvincial = async (): Promise<ResumenProvincial> => {
|
|
||||||
const response = await apiClient.get('/resultados/provincia/02');
|
const response = await apiClient.get('/resultados/provincia/02');
|
||||||
return response.data;
|
return response.data;
|
||||||
};
|
};
|
||||||
@@ -113,4 +119,14 @@ export const getComposicionCongreso = async (): Promise<ComposicionData> => {
|
|||||||
export const getBancadasDetalle = async (): Promise<BancadaDetalle[]> => {
|
export const getBancadasDetalle = async (): Promise<BancadaDetalle[]> => {
|
||||||
const response = await apiClient.get('/resultados/bancadas-detalle');
|
const response = await apiClient.get('/resultados/bancadas-detalle');
|
||||||
return response.data;
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getConfiguracionPublica = async (): Promise<ConfiguracionPublica> => {
|
||||||
|
const response = await apiClient.get('/resultados/configuracion-publica');
|
||||||
|
return response.data;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getResultadosConcejales = async (seccionId: string): Promise<ResultadoTicker[]> => {
|
||||||
|
const response = await apiClient.get(`/resultados/concejales/${seccionId}`);
|
||||||
|
return response.data;
|
||||||
};
|
};
|
||||||
103
Elecciones-Web/frontend/src/components/ConcejalesWidget.tsx
Normal file
103
Elecciones-Web/frontend/src/components/ConcejalesWidget.tsx
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
// src/components/ConcejalesWidget.tsx
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
import { useQuery } from '@tanstack/react-query';
|
||||||
|
import { getSeccionesElectorales, getResultadosConcejales, getConfiguracionPublica } from '../apiService';
|
||||||
|
import type { MunicipioSimple, ResultadoTicker } from '../types/types';
|
||||||
|
import { ImageWithFallback } from './ImageWithFallback';
|
||||||
|
import './TickerWidget.css'; // Reutilizamos los estilos del ticker
|
||||||
|
|
||||||
|
const formatPercent = (num: number) => `${(num || 0).toFixed(2).replace('.', ',')}%`;
|
||||||
|
|
||||||
|
export const ConcejalesWidget = () => {
|
||||||
|
const [secciones, setSecciones] = useState<MunicipioSimple[]>([]);
|
||||||
|
const [seccionActualId, setSeccionActualId] = useState<string>('');
|
||||||
|
|
||||||
|
// Query para la configuración (para saber cuántos resultados mostrar)
|
||||||
|
const { data: configData } = useQuery({
|
||||||
|
queryKey: ['configuracionPublica'],
|
||||||
|
queryFn: getConfiguracionPublica,
|
||||||
|
staleTime: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
// Calculamos la cantidad a mostrar desde la configuración
|
||||||
|
const cantidadAMostrar = parseInt(configData?.ConcejalesResultadosCantidad || '5', 10) + 1;
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
getSeccionesElectorales().then(seccionesData => {
|
||||||
|
if (seccionesData && seccionesData.length > 0) {
|
||||||
|
const orden = new Map([
|
||||||
|
['Capital', 0], ['Primera', 1], ['Segunda', 2], ['Tercera', 3],
|
||||||
|
['Cuarta', 4], ['Quinta', 5], ['Sexta', 6], ['Séptima', 7]
|
||||||
|
]);
|
||||||
|
const getOrden = (nombre: string) => {
|
||||||
|
const match = nombre.match(/Capital|Primera|Segunda|Tercera|Cuarta|Quinta|Sexta|Séptima/);
|
||||||
|
return match ? orden.get(match[0]) ?? 99 : 99;
|
||||||
|
};
|
||||||
|
seccionesData.sort((a, b) => getOrden(a.nombre) - getOrden(b.nombre));
|
||||||
|
setSecciones(seccionesData);
|
||||||
|
// Al estar los datos ya ordenados, el [0] será "Sección Capital"
|
||||||
|
setSeccionActualId(seccionesData[0].id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, []); // El array de dependencias vacío asegura que esto solo se ejecute una vez
|
||||||
|
|
||||||
|
// Query para obtener los resultados de la sección seleccionada
|
||||||
|
const { data: resultados, isLoading } = useQuery<ResultadoTicker[]>({
|
||||||
|
queryKey: ['resultadosConcejales', seccionActualId],
|
||||||
|
queryFn: () => getResultadosConcejales(seccionActualId),
|
||||||
|
enabled: !!seccionActualId,
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- INICIO DE LA LÓGICA DE PROCESAMIENTO "OTROS" ---
|
||||||
|
let displayResults: ResultadoTicker[] = resultados || [];
|
||||||
|
if (resultados && resultados.length > cantidadAMostrar) {
|
||||||
|
const topParties = resultados.slice(0, cantidadAMostrar - 1);
|
||||||
|
const otherParties = resultados.slice(cantidadAMostrar - 1);
|
||||||
|
const otrosPorcentaje = otherParties.reduce((sum, party) => sum + (party.votosPorcentaje || 0), 0);
|
||||||
|
|
||||||
|
const otrosEntry: ResultadoTicker = {
|
||||||
|
id: `otros-concejales-${seccionActualId}`,
|
||||||
|
nombre: 'Otros',
|
||||||
|
nombreCorto: 'Otros',
|
||||||
|
color: '#888888',
|
||||||
|
logoUrl: null,
|
||||||
|
votos: 0, // No es relevante para la visualización del porcentaje
|
||||||
|
votosPorcentaje: otrosPorcentaje,
|
||||||
|
};
|
||||||
|
displayResults = [...topParties, otrosEntry];
|
||||||
|
} else if (resultados) {
|
||||||
|
displayResults = resultados.slice(0, cantidadAMostrar);
|
||||||
|
}
|
||||||
|
// --- FIN DE LA LÓGICA DE PROCESAMIENTO "OTROS" ---
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="ticker-card" style={{ gridColumn: '1 / -1' }}>
|
||||||
|
<div className="ticker-header">
|
||||||
|
<h3>CONCEJALES - LA PLATA</h3>
|
||||||
|
<select value={seccionActualId} onChange={e => setSeccionActualId(e.target.value)} disabled={secciones.length === 0}>
|
||||||
|
{secciones.map(s => <option key={s.id} value={s.id}>{s.nombre}</option>)}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div className="ticker-results">
|
||||||
|
{isLoading ? <p>Cargando...</p> :
|
||||||
|
displayResults.map(partido => (
|
||||||
|
<div key={partido.id} className="ticker-party">
|
||||||
|
<div className="party-logo">
|
||||||
|
<ImageWithFallback src={partido.logoUrl || undefined} fallbackSrc="/default-avatar.png" alt={`Logo de ${partido.nombre}`} />
|
||||||
|
</div>
|
||||||
|
<div className="party-details">
|
||||||
|
<div className="party-info">
|
||||||
|
<span className="party-name">{partido.nombreCorto || partido.nombre}</span>
|
||||||
|
<span className="party-percent">{formatPercent(partido.votosPorcentaje)}</span>
|
||||||
|
</div>
|
||||||
|
<div className="party-bar-background">
|
||||||
|
<div className="party-bar-foreground" style={{ width: `${partido.votosPorcentaje}%`, backgroundColor: partido.color || '#888' }}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -80,17 +80,13 @@ export const CongresoWidget = () => {
|
|||||||
{camaraActiva === 'diputados' ? (
|
{camaraActiva === 'diputados' ? (
|
||||||
<ParliamentLayout
|
<ParliamentLayout
|
||||||
seatData={seatFillData}
|
seatData={seatFillData}
|
||||||
// --- INICIO DE LA CORRECCIÓN ---
|
|
||||||
// Solo pasamos la prop 'presidenteBancada' si NO estamos en modo oficial
|
// Solo pasamos la prop 'presidenteBancada' si NO estamos en modo oficial
|
||||||
presidenteBancada={!esModoOficial ? datosCamaraActual.presidenteBancada : undefined}
|
presidenteBancada={!esModoOficial ? datosCamaraActual.presidenteBancada : undefined}
|
||||||
// --- FIN DE LA CORRECCIÓN ---
|
|
||||||
/>
|
/>
|
||||||
) : (
|
) : (
|
||||||
<SenateLayout
|
<SenateLayout
|
||||||
seatData={seatFillData}
|
seatData={seatFillData}
|
||||||
// --- INICIO DE LA CORRECCIÓN ---
|
|
||||||
presidenteBancada={!esModoOficial ? datosCamaraActual.presidenteBancada : undefined}
|
presidenteBancada={!esModoOficial ? datosCamaraActual.presidenteBancada : undefined}
|
||||||
// --- FIN DE LA CORRECCIÓN ---
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
28
Elecciones-Web/frontend/src/components/ImageWithFallback.tsx
Normal file
28
Elecciones-Web/frontend/src/components/ImageWithFallback.tsx
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// src/components/ImageWithFallback.tsx
|
||||||
|
import { useState, useEffect } from 'react';
|
||||||
|
|
||||||
|
interface Props extends React.ImgHTMLAttributes<HTMLImageElement> {
|
||||||
|
fallbackSrc: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ImageWithFallback = ({ src, fallbackSrc, ...props }: Props) => {
|
||||||
|
const [imgSrc, setImgSrc] = useState(src);
|
||||||
|
const [error, setError] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setError(false);
|
||||||
|
setImgSrc(src);
|
||||||
|
}, [src]);
|
||||||
|
|
||||||
|
const handleError = () => {
|
||||||
|
setError(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<img
|
||||||
|
src={error || !imgSrc ? fallbackSrc : imgSrc}
|
||||||
|
onError={handleError}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
@@ -87,7 +87,7 @@ export const TelegramaWidget = () => {
|
|||||||
.finally(() => setLoading(false));
|
.finally(() => setLoading(false));
|
||||||
}
|
}
|
||||||
}, [selectedMesa]);
|
}, [selectedMesa]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="telegrama-container">
|
<div className="telegrama-container">
|
||||||
<h4>Consulta de Telegramas por Ubicación</h4>
|
<h4>Consulta de Telegramas por Ubicación</h4>
|
||||||
|
|||||||
@@ -1,22 +1,20 @@
|
|||||||
/* src/components/TickerWidget.css */
|
/* src/components/TickerWidget.css */
|
||||||
.ticker-container {
|
.ticker-wrapper {
|
||||||
/* Se cambia a un fondo claro con borde y sombra sutil */
|
display: grid;
|
||||||
background-color: #ffffff;
|
grid-template-columns: repeat(auto-fit, minmax(350px, 1fr));
|
||||||
border: 1px solid #e0e0e0;
|
gap: 1.5rem;
|
||||||
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
|
width: 100%;
|
||||||
padding: 15px 20px;
|
max-width: 1280px;
|
||||||
border-radius: 8px;
|
margin: 20px auto;
|
||||||
max-width: 800px;
|
|
||||||
margin: 20px auto;
|
|
||||||
font-family: "Public Sans", system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
||||||
color: #333333; /* Color de texto por defecto */
|
|
||||||
}
|
}
|
||||||
|
.ticker-card {
|
||||||
.ticker-container.loading, .ticker-container.error {
|
background-color: #ffffff;
|
||||||
text-align: center;
|
border: 1px solid #e0e0e0;
|
||||||
padding: 30px;
|
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.05);
|
||||||
font-style: italic;
|
padding: 15px 20px;
|
||||||
color: #757575; /* Color de texto atenuado */
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.ticker-header {
|
.ticker-header {
|
||||||
@@ -48,9 +46,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.ticker-results {
|
.ticker-results {
|
||||||
display: grid;
|
display: flex;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
flex-direction: column;
|
||||||
gap: 20px;
|
gap: 12px; /* Espacio entre partidos */
|
||||||
}
|
}
|
||||||
|
|
||||||
.ticker-party .party-info {
|
.ticker-party .party-info {
|
||||||
@@ -84,4 +82,31 @@
|
|||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
transition: width 0.5s ease-in-out;
|
transition: width 0.5s ease-in-out;
|
||||||
/* El color de fondo se sigue aplicando desde el componente, esto es correcto */
|
/* El color de fondo se sigue aplicando desde el componente, esto es correcto */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ticker-results {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); /* Aumentamos el tamaño mínimo */
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.ticker-party {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 10px; /* Espacio entre logo y detalles */
|
||||||
|
}
|
||||||
|
.party-logo {
|
||||||
|
flex-shrink: 0;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
}
|
||||||
|
.party-logo img {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
object-fit: cover;
|
||||||
|
border-radius: 4px;
|
||||||
|
border: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
.party-details {
|
||||||
|
flex-grow: 1;
|
||||||
|
min-width: 0; /* Previene que el flex item se desborde */
|
||||||
}
|
}
|
||||||
@@ -1,78 +1,92 @@
|
|||||||
// src/components/TickerWidget.tsx
|
// src/components/TickerWidget.tsx
|
||||||
import { useState, useEffect } from 'react';
|
import { useQuery } from '@tanstack/react-query';
|
||||||
import { getResumenProvincial } from '../apiService';
|
import { getResumenProvincial, getConfiguracionPublica } from '../apiService';
|
||||||
import type { ResumenProvincial } from '../types/types';
|
import type { CategoriaResumen, ResultadoTicker } from '../types/types';
|
||||||
|
import { ImageWithFallback } from './ImageWithFallback';
|
||||||
import './TickerWidget.css';
|
import './TickerWidget.css';
|
||||||
|
|
||||||
const formatPercent = (num: number) => `${num.toFixed(2).replace('.', ',')}%`;
|
const formatPercent = (num: number) => `${(num || 0).toFixed(2).replace('.', ',')}%`;
|
||||||
const COLORS = [
|
|
||||||
"#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
|
|
||||||
"#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf"
|
|
||||||
];
|
|
||||||
|
|
||||||
export const TickerWidget = () => {
|
export const TickerWidget = () => {
|
||||||
const [data, setData] = useState<ResumenProvincial | null>(null);
|
const { data: categorias, isLoading, error } = useQuery<CategoriaResumen[]>({
|
||||||
const [loading, setLoading] = useState(true);
|
queryKey: ['resumenProvincial'],
|
||||||
// Se añade un nuevo estado para manejar errores de forma explícita
|
queryFn: getResumenProvincial,
|
||||||
const [error, setError] = useState<string | null>(null);
|
refetchInterval: 30000,
|
||||||
|
});
|
||||||
|
|
||||||
useEffect(() => {
|
const { data: configData } = useQuery({
|
||||||
const fetchData = async () => {
|
queryKey: ['configuracionPublica'],
|
||||||
// Se resetea el error en cada intento de carga
|
queryFn: getConfiguracionPublica,
|
||||||
setError(null);
|
staleTime: 0,
|
||||||
try {
|
});
|
||||||
const result = await getResumenProvincial();
|
|
||||||
setData(result);
|
|
||||||
} catch (err) {
|
|
||||||
console.error("Error cargando resumen provincial:", err);
|
|
||||||
// Se guarda el mensaje de error para mostrarlo en la UI
|
|
||||||
setError("No se pudo conectar con el servidor para obtener el resumen provincial.");
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
fetchData(); // Carga inicial
|
const cantidadAMostrar = parseInt(configData?.TickerResultadosCantidad || '5', 10) + 1;
|
||||||
const intervalId = setInterval(fetchData, 30000); // Actualiza cada 30 segundos
|
|
||||||
|
|
||||||
return () => clearInterval(intervalId); // Limpia el intervalo al desmontar el componente
|
if (isLoading) return <div className="ticker-wrapper loading">Cargando resumen...</div>;
|
||||||
}, []);
|
if (error || !categorias) return <div className="ticker-wrapper error">No hay datos disponibles.</div>;
|
||||||
|
|
||||||
if (loading) {
|
const categoriasFiltradas = categorias.filter(c => c.categoriaId !== 7);
|
||||||
return <div className="ticker-container loading">Cargando resultados provinciales...</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Si hay un error, se muestra el mensaje correspondiente
|
|
||||||
if (error) {
|
|
||||||
return <div className="ticker-container error">{error}</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!data) {
|
|
||||||
return <div className="ticker-container error">No hay datos disponibles.</div>;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="ticker-container">
|
<div className="ticker-wrapper">
|
||||||
<div className="ticker-header">
|
{categoriasFiltradas.map(categoria => {
|
||||||
<h3>PROVINCIA BS. AS.</h3>
|
|
||||||
<div className="ticker-stats">
|
let displayResults: ResultadoTicker[] = categoria.resultados;
|
||||||
<span>Mesas Escrutadas: <strong>{formatPercent(data.porcentajeEscrutado)}</strong></span>
|
|
||||||
<span>Participación Total: <strong>{formatPercent(data.porcentajeParticipacion)}</strong></span>
|
if (categoria.resultados.length > cantidadAMostrar) {
|
||||||
</div>
|
const topParties = categoria.resultados.slice(0, cantidadAMostrar - 1);
|
||||||
</div>
|
const otherParties = categoria.resultados.slice(cantidadAMostrar - 1);
|
||||||
<div className="ticker-results">
|
const otrosPorcentaje = otherParties.reduce((sum, party) => sum + party.votosPorcentaje, 0);
|
||||||
{data.resultados.slice(0, 3).map((partido, index) => (
|
|
||||||
<div key={`${partido.nombre}-${index}`} className="ticker-party">
|
const otrosEntry: ResultadoTicker = {
|
||||||
<div className="party-info">
|
id: `otros-${categoria.categoriaId}`,
|
||||||
<span className="party-name">{partido.nombre}</span>
|
nombre: 'Otros',
|
||||||
<span className="party-percent">{formatPercent(partido.porcentaje)}</span>
|
nombreCorto: 'Otros',
|
||||||
|
color: '#888888',
|
||||||
|
logoUrl: null,
|
||||||
|
votos: 0,
|
||||||
|
votosPorcentaje: otrosPorcentaje,
|
||||||
|
};
|
||||||
|
|
||||||
|
displayResults = [...topParties, otrosEntry];
|
||||||
|
} else {
|
||||||
|
displayResults = categoria.resultados.slice(0, cantidadAMostrar);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div key={categoria.categoriaId} className="ticker-card">
|
||||||
|
<div className="ticker-header">
|
||||||
|
<h3>{categoria.categoriaNombre}</h3>
|
||||||
|
<div className="ticker-stats">
|
||||||
|
<span>Mesas: <strong>{formatPercent(categoria.estadoRecuento?.mesasTotalizadasPorcentaje ?? 0)}</strong></span>
|
||||||
|
<span>Part: <strong>{formatPercent(categoria.estadoRecuento?.participacionPorcentaje ?? 0)}</strong></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="party-bar-background">
|
<div className="ticker-results">
|
||||||
<div className="party-bar-foreground" style={{ width: `${partido.porcentaje}%`, backgroundColor:COLORS[index % COLORS.length] }}></div>
|
{displayResults.map(partido => (
|
||||||
|
<div key={partido.id} className="ticker-party">
|
||||||
|
<div className="party-logo">
|
||||||
|
<ImageWithFallback
|
||||||
|
src={partido.logoUrl || undefined}
|
||||||
|
fallbackSrc="/default-avatar.png"
|
||||||
|
alt={`Logo de ${partido.nombre}`}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div className="party-details">
|
||||||
|
<div className="party-info">
|
||||||
|
<span className="party-name">{partido.nombreCorto || partido.nombre}</span>
|
||||||
|
<span className="party-percent">{formatPercent(partido.votosPorcentaje)}</span>
|
||||||
|
</div>
|
||||||
|
<div className="party-bar-background">
|
||||||
|
<div className="party-bar-foreground" style={{ width: `${partido.votosPorcentaje}%`, backgroundColor: partido.color || '#888' }}></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
);
|
||||||
</div>
|
})}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -40,22 +40,46 @@ export interface GeographyObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface MunicipioSimple { id: string; nombre: string; }
|
export interface MunicipioSimple { id: string; nombre: string; }
|
||||||
export interface AgrupacionResultado { nombre: string; votos: number; porcentaje: number; }
|
|
||||||
|
export interface ResultadoTicker {
|
||||||
|
id: string;
|
||||||
|
nombre: string;
|
||||||
|
nombreCorto: string | null;
|
||||||
|
color: string | null;
|
||||||
|
logoUrl: string | null;
|
||||||
|
votos: number;
|
||||||
|
votosPorcentaje: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface EstadoRecuentoTicker {
|
||||||
|
mesasTotalizadasPorcentaje: number;
|
||||||
|
participacionPorcentaje: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CategoriaResumen {
|
||||||
|
categoriaId: number;
|
||||||
|
categoriaNombre: string;
|
||||||
|
estadoRecuento: EstadoRecuentoTicker | null;
|
||||||
|
resultados: ResultadoTicker[];
|
||||||
|
}
|
||||||
|
|
||||||
export interface VotosAdicionales { enBlanco: number; nulos: number; recurridos: number; }
|
export interface VotosAdicionales { enBlanco: number; nulos: number; recurridos: number; }
|
||||||
|
|
||||||
export interface MunicipioDetalle {
|
export interface MunicipioDetalle {
|
||||||
municipioNombre: string;
|
municipioNombre: string;
|
||||||
ultimaActualizacion: string;
|
ultimaActualizacion: string;
|
||||||
porcentajeEscrutado: number;
|
porcentajeEscrutado: number;
|
||||||
porcentajeParticipacion: number;
|
porcentajeParticipacion: number;
|
||||||
resultados: AgrupacionResultado[];
|
resultados: CategoriaResumen[];
|
||||||
votosAdicionales: VotosAdicionales;
|
votosAdicionales: VotosAdicionales;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResumenProvincial {
|
export interface ResumenProvincial {
|
||||||
provinciaNombre: string;
|
provinciaNombre: string;
|
||||||
ultimaActualizacion: string;
|
ultimaActualizacion: string;
|
||||||
porcentajeEscrutado: number;
|
porcentajeEscrutado: number;
|
||||||
porcentajeParticipacion: number;
|
porcentajeParticipacion: number;
|
||||||
resultados: AgrupacionResultado[];
|
resultados: CategoriaResumen[];
|
||||||
votosAdicionales: VotosAdicionales;
|
votosAdicionales: VotosAdicionales;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -50,7 +50,6 @@ public class AdminController : ControllerBase
|
|||||||
// Actualizamos las propiedades de la entidad con los valores del DTO.
|
// Actualizamos las propiedades de la entidad con los valores del DTO.
|
||||||
agrupacion.NombreCorto = agrupacionDto.NombreCorto;
|
agrupacion.NombreCorto = agrupacionDto.NombreCorto;
|
||||||
agrupacion.Color = agrupacionDto.Color;
|
agrupacion.Color = agrupacionDto.Color;
|
||||||
agrupacion.LogoUrl = agrupacionDto.LogoUrl;
|
|
||||||
|
|
||||||
// Guardamos los cambios en la base de datos.
|
// Guardamos los cambios en la base de datos.
|
||||||
await _dbContext.SaveChangesAsync();
|
await _dbContext.SaveChangesAsync();
|
||||||
@@ -178,4 +177,32 @@ public class AdminController : ControllerBase
|
|||||||
|
|
||||||
return NoContent();
|
return NoContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[HttpGet("logos")]
|
||||||
|
public async Task<IActionResult> GetLogos()
|
||||||
|
{
|
||||||
|
return Ok(await _dbContext.LogosAgrupacionesCategorias.AsNoTracking().ToListAsync());
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPut("logos")]
|
||||||
|
public async Task<IActionResult> UpdateLogos([FromBody] List<LogoAgrupacionCategoria> logos)
|
||||||
|
{
|
||||||
|
// Lógica de "Upsert"
|
||||||
|
foreach (var logo in logos)
|
||||||
|
{
|
||||||
|
var logoExistente = await _dbContext.LogosAgrupacionesCategorias
|
||||||
|
.FirstOrDefaultAsync(l => l.AgrupacionPoliticaId == logo.AgrupacionPoliticaId && l.CategoriaId == logo.CategoriaId);
|
||||||
|
|
||||||
|
if (logoExistente != null)
|
||||||
|
{
|
||||||
|
logoExistente.LogoUrl = logo.LogoUrl;
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(logo.LogoUrl))
|
||||||
|
{
|
||||||
|
_dbContext.LogosAgrupacionesCategorias.Add(logo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await _dbContext.SaveChangesAsync();
|
||||||
|
return NoContent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -92,59 +92,69 @@ public class ResultadosController : ControllerBase
|
|||||||
[HttpGet("provincia/{distritoId}")]
|
[HttpGet("provincia/{distritoId}")]
|
||||||
public async Task<IActionResult> GetResultadosProvinciales(string distritoId)
|
public async Task<IActionResult> GetResultadosProvinciales(string distritoId)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Solicitud de resultados para la provincia con distritoId: {DistritoId}", distritoId);
|
|
||||||
|
|
||||||
// PASO 1: Encontrar el ámbito geográfico de la provincia.
|
|
||||||
var provincia = await _dbContext.AmbitosGeograficos.AsNoTracking()
|
var provincia = await _dbContext.AmbitosGeograficos.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(a => a.DistritoId == distritoId && a.NivelId == 10);
|
.FirstOrDefaultAsync(a => a.DistritoId == distritoId && a.NivelId == 10);
|
||||||
|
|
||||||
if (provincia == null)
|
var todosLosResumenes = await _dbContext.ResumenesVotos.AsNoTracking()
|
||||||
{
|
.Include(r => r.AgrupacionPolitica)
|
||||||
_logger.LogWarning("No se encontró la provincia con distritoId: {DistritoId}", distritoId);
|
|
||||||
return NotFound(new { message = $"No se encontró la provincia con distritoId {distritoId}" });
|
|
||||||
}
|
|
||||||
|
|
||||||
// PASO 2: Obtener el estado general del recuento para la provincia.
|
|
||||||
// Como las estadísticas generales (mesas, participación) son las mismas para todas las categorías,
|
|
||||||
// simplemente tomamos la primera que encontremos para este ámbito.
|
|
||||||
var estadoGeneral = await _dbContext.EstadosRecuentosGenerales.AsNoTracking()
|
|
||||||
.FirstOrDefaultAsync(e => e.AmbitoGeograficoId == provincia.Id);
|
|
||||||
|
|
||||||
// PASO 3: Obtener el resumen de votos por agrupación para la provincia.
|
|
||||||
// Hacemos un JOIN manual entre ResumenesVotos y AgrupacionesPoliticas para obtener los nombres.
|
|
||||||
var resultados = await _dbContext.ResumenesVotos
|
|
||||||
.AsNoTracking()
|
|
||||||
.Where(r => r.AmbitoGeograficoId == provincia.Id)
|
|
||||||
.Join(
|
|
||||||
_dbContext.AgrupacionesPoliticas.AsNoTracking(),
|
|
||||||
resumen => resumen.AgrupacionPoliticaId,
|
|
||||||
agrupacion => agrupacion.Id,
|
|
||||||
(resumen, agrupacion) => new AgrupacionResultadoDto
|
|
||||||
{
|
|
||||||
Nombre = agrupacion.Nombre,
|
|
||||||
Votos = resumen.Votos,
|
|
||||||
Porcentaje = resumen.VotosPorcentaje
|
|
||||||
})
|
|
||||||
.OrderByDescending(r => r.Votos)
|
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
||||||
// PASO 4: Construir el objeto de respuesta (DTO).
|
// OBTENER TODOS LOS LOGOS EN UNA SOLA CONSULTA
|
||||||
// Si no hay datos de recuento aún, usamos valores por defecto para evitar errores en el frontend.
|
var logosLookup = (await _dbContext.LogosAgrupacionesCategorias.AsNoTracking().ToListAsync())
|
||||||
var respuestaDto = new ResumenProvincialDto
|
.ToLookup(l => $"{l.AgrupacionPoliticaId}-{l.CategoriaId}");
|
||||||
{
|
|
||||||
ProvinciaNombre = provincia.Nombre,
|
|
||||||
UltimaActualizacion = estadoGeneral?.FechaTotalizacion ?? DateTime.UtcNow,
|
|
||||||
PorcentajeEscrutado = estadoGeneral?.MesasTotalizadasPorcentaje ?? 0,
|
|
||||||
PorcentajeParticipacion = estadoGeneral?.ParticipacionPorcentaje ?? 0,
|
|
||||||
Resultados = resultados,
|
|
||||||
// NOTA: Los votos adicionales (nulos, en blanco) no están en la tabla de resumen provincial.
|
|
||||||
// Esto es una mejora pendiente en el Worker. Por ahora, devolvemos 0.
|
|
||||||
VotosAdicionales = new VotosAdicionalesDto { EnBlanco = 0, Nulos = 0, Recurridos = 0 }
|
|
||||||
};
|
|
||||||
|
|
||||||
_logger.LogInformation("Devolviendo {NumResultados} resultados de agrupaciones para la provincia.", respuestaDto.Resultados.Count);
|
if (provincia == null) return NotFound($"No se encontró la provincia con distritoId {distritoId}");
|
||||||
|
|
||||||
return Ok(respuestaDto);
|
var estadosPorCategoria = await _dbContext.EstadosRecuentosGenerales.AsNoTracking()
|
||||||
|
.Include(e => e.CategoriaElectoral)
|
||||||
|
.Where(e => e.AmbitoGeograficoId == provincia.Id)
|
||||||
|
.ToDictionaryAsync(e => e.CategoriaId);
|
||||||
|
|
||||||
|
var resultadosPorMunicipio = await _dbContext.ResultadosVotos
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(r => r.AgrupacionPolitica)
|
||||||
|
.Where(r => r.AmbitoGeografico.NivelId == 30)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var resultadosAgrupados = resultadosPorMunicipio
|
||||||
|
.GroupBy(r => r.CategoriaId)
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
CategoriaId = g.Key,
|
||||||
|
TotalVotosCategoria = g.Sum(r => r.CantidadVotos),
|
||||||
|
// Agrupamos por el ID de la agrupación, no por el objeto
|
||||||
|
Resultados = g.GroupBy(r => r.AgrupacionPoliticaId)
|
||||||
|
.Select(partidoGroup => new
|
||||||
|
{
|
||||||
|
// El objeto Agrupacion lo tomamos del primer elemento del grupo
|
||||||
|
Agrupacion = partidoGroup.First().AgrupacionPolitica,
|
||||||
|
Votos = partidoGroup.Sum(r => r.CantidadVotos)
|
||||||
|
})
|
||||||
|
.ToList()
|
||||||
|
})
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
g.CategoriaId,
|
||||||
|
CategoriaNombre = estadosPorCategoria.ContainsKey(g.CategoriaId) ? estadosPorCategoria[g.CategoriaId].CategoriaElectoral.Nombre : "Desconocido",
|
||||||
|
EstadoRecuento = estadosPorCategoria.GetValueOrDefault(g.CategoriaId),
|
||||||
|
Resultados = g.Resultados
|
||||||
|
.Select(r => new
|
||||||
|
{
|
||||||
|
r.Agrupacion.Id,
|
||||||
|
r.Agrupacion.Nombre,
|
||||||
|
r.Agrupacion.NombreCorto,
|
||||||
|
r.Agrupacion.Color,
|
||||||
|
LogoUrl = logosLookup[$"{r.Agrupacion.Id}-{g.CategoriaId}"].FirstOrDefault()?.LogoUrl,
|
||||||
|
r.Votos,
|
||||||
|
VotosPorcentaje = g.TotalVotosCategoria > 0 ? ((decimal)r.Votos * 100 / g.TotalVotosCategoria) : 0
|
||||||
|
})
|
||||||
|
.OrderByDescending(r => r.Votos)
|
||||||
|
.ToList()
|
||||||
|
})
|
||||||
|
.OrderBy(c => c.CategoriaId)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return Ok(resultadosAgrupados);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -503,4 +513,77 @@ public class ResultadosController : ControllerBase
|
|||||||
|
|
||||||
return Ok(bancadasConOcupantes);
|
return Ok(bancadasConOcupantes);
|
||||||
}
|
}
|
||||||
|
[HttpGet("configuracion-publica")]
|
||||||
|
public async Task<IActionResult> GetConfiguracionPublica()
|
||||||
|
{
|
||||||
|
// Definimos una lista de las claves de configuración que son seguras para el público.
|
||||||
|
// De esta manera, si en el futuro añadimos claves sensibles (como contraseñas de API, etc.),
|
||||||
|
// nunca se expondrán accidentalmente.
|
||||||
|
var clavesPublicas = new List<string>
|
||||||
|
{
|
||||||
|
"TickerResultadosCantidad",
|
||||||
|
"ConcejalesResultadosCantidad"
|
||||||
|
// "OtraClavePublica"
|
||||||
|
};
|
||||||
|
|
||||||
|
var configuracionPublica = await _dbContext.Configuraciones
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(c => clavesPublicas.Contains(c.Clave))
|
||||||
|
.ToDictionaryAsync(c => c.Clave, c => c.Valor);
|
||||||
|
|
||||||
|
return Ok(configuracionPublica);
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("concejales/{seccionId}")]
|
||||||
|
public async Task<IActionResult> GetResultadosConcejalesPorSeccion(string seccionId)
|
||||||
|
{
|
||||||
|
// 1. Encontrar todos los municipios (Nivel 30) que pertenecen a la sección dada (Nivel 20)
|
||||||
|
var municipiosDeLaSeccion = await _dbContext.AmbitosGeograficos
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(a => a.NivelId == 30 && a.SeccionProvincialId == seccionId)
|
||||||
|
.Select(a => a.Id) // Solo necesitamos sus IDs
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
if (!municipiosDeLaSeccion.Any())
|
||||||
|
{
|
||||||
|
return Ok(new List<object>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Obtener todos los resultados de la categoría Concejales (ID 7) para esos municipios
|
||||||
|
var resultadosMunicipales = await _dbContext.ResultadosVotos
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(r => r.AgrupacionPolitica)
|
||||||
|
.Where(r => r.CategoriaId == 7 && municipiosDeLaSeccion.Contains(r.AmbitoGeograficoId))
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
var logosConcejales = await _dbContext.LogosAgrupacionesCategorias
|
||||||
|
.AsNoTracking()
|
||||||
|
.Where(l => l.CategoriaId == 7)
|
||||||
|
.ToDictionaryAsync(l => l.AgrupacionPoliticaId);
|
||||||
|
|
||||||
|
// 3. Agrupar y sumar en memoria para obtener el total por partido para la sección
|
||||||
|
var totalVotosSeccion = resultadosMunicipales.Sum(r => r.CantidadVotos);
|
||||||
|
|
||||||
|
var resultadosFinales = resultadosMunicipales
|
||||||
|
.GroupBy(r => r.AgrupacionPolitica)
|
||||||
|
.Select(g => new
|
||||||
|
{
|
||||||
|
Agrupacion = g.Key,
|
||||||
|
Votos = g.Sum(r => r.CantidadVotos)
|
||||||
|
})
|
||||||
|
.OrderByDescending(r => r.Votos)
|
||||||
|
.Select(r => new
|
||||||
|
{
|
||||||
|
r.Agrupacion.Id,
|
||||||
|
r.Agrupacion.Nombre,
|
||||||
|
r.Agrupacion.NombreCorto,
|
||||||
|
r.Agrupacion.Color,
|
||||||
|
LogoUrl = logosConcejales.GetValueOrDefault(r.Agrupacion.Id)?.LogoUrl,
|
||||||
|
r.Votos,
|
||||||
|
votosPorcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0
|
||||||
|
})
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return Ok(resultadosFinales);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -141,6 +141,13 @@ using (var scope = app.Services.CreateScope())
|
|||||||
context.SaveChanges();
|
context.SaveChanges();
|
||||||
Console.WriteLine("--> Seeded default configuration 'MostrarOcupantes'.");
|
Console.WriteLine("--> Seeded default configuration 'MostrarOcupantes'.");
|
||||||
}
|
}
|
||||||
|
if (!context.Configuraciones.Any(c => c.Clave == "TickerResultadosCantidad"))
|
||||||
|
{
|
||||||
|
context.Configuraciones.Add(new Configuracion { Clave = "TickerResultadosCantidad", Valor = "3" });
|
||||||
|
context.Configuraciones.Add(new Configuracion { Clave = "ConcejalesResultadosCantidad", Valor = "5" });
|
||||||
|
context.SaveChanges();
|
||||||
|
Console.WriteLine("--> Seeded default configuration 'TickerResultadosCantidad'.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Configurar el pipeline de peticiones HTTP.
|
// Configurar el pipeline de peticiones HTTP.
|
||||||
|
|||||||
@@ -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+3b8c6bf754cff6ace486ae8fe850ed4d69233280")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+608ae655bedf6c59be5fec1e14fc308871d2fd62")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","BlOQCaw/bt9UsCnDEIqO6LwzwEh4i0OxBfeIZgKDR4U=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","2x9HRdaMF3CjEHo\u002BFx\u002BfhG7CTomq/ExTkOKw2bUeHms="],"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=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","khGrM2Rl22MsVh9N6\u002B7todRrMuJ6o3ljuHxZF/aubqE=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","6xYke/2SzNspypSwIgizeNUH7b\u002Bfoz3wYfKk6z1tMsw="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||||
@@ -1 +1 @@
|
|||||||
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","BlOQCaw/bt9UsCnDEIqO6LwzwEh4i0OxBfeIZgKDR4U=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","2x9HRdaMF3CjEHo\u002BFx\u002BfhG7CTomq/ExTkOKw2bUeHms="],"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=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","khGrM2Rl22MsVh9N6\u002B7todRrMuJ6o3ljuHxZF/aubqE=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","6xYke/2SzNspypSwIgizeNUH7b\u002Bfoz3wYfKk6z1tMsw="],"CachedAssets":{},"CachedCopyCandidates":{}}
|
||||||
@@ -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+3b8c6bf754cff6ace486ae8fe850ed4d69233280")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+608ae655bedf6c59be5fec1e14fc308871d2fd62")]
|
||||||
[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")]
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ public class EleccionesDbContext(DbContextOptions<EleccionesDbContext> options)
|
|||||||
public DbSet<Configuracion> Configuraciones { get; set; }
|
public DbSet<Configuracion> Configuraciones { get; set; }
|
||||||
public DbSet<Bancada> Bancadas { get; set; }
|
public DbSet<Bancada> Bancadas { get; set; }
|
||||||
public DbSet<OcupanteBanca> OcupantesBancas { get; set; }
|
public DbSet<OcupanteBanca> OcupantesBancas { get; set; }
|
||||||
|
public DbSet<LogoAgrupacionCategoria> LogosAgrupacionesCategorias { get; set; }
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
@@ -75,5 +76,9 @@ public class EleccionesDbContext(DbContextOptions<EleccionesDbContext> options)
|
|||||||
// Opcional: puede definir un índice
|
// Opcional: puede definir un índice
|
||||||
entity.HasIndex(o => o.BancadaId).IsUnique();
|
entity.HasIndex(o => o.BancadaId).IsUnique();
|
||||||
});
|
});
|
||||||
|
modelBuilder.Entity<LogoAgrupacionCategoria>(entity =>
|
||||||
|
{
|
||||||
|
entity.HasIndex(l => new { l.AgrupacionPoliticaId, l.CategoriaId }).IsUnique();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,8 +12,6 @@ public class AgrupacionPolitica
|
|||||||
public string Nombre { get; set; } = null!;
|
public string Nombre { get; set; } = null!;
|
||||||
public string? NombreCorto { get; set; } // Para leyendas y gráficos
|
public string? NombreCorto { get; set; } // Para leyendas y gráficos
|
||||||
public string? Color { get; set; } // Código hexadecimal, ej: "#1f77b4"
|
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? OrdenDiputados { get; set; }
|
||||||
public int? OrdenSenadores { get; set; }
|
public int? OrdenSenadores { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// src/Elecciones.Database/Entities/LogoAgrupacionCategoria.cs
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Entities;
|
||||||
|
|
||||||
|
public class LogoAgrupacionCategoria
|
||||||
|
{
|
||||||
|
[Key]
|
||||||
|
public int Id { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public string AgrupacionPoliticaId { get; set; } = null!;
|
||||||
|
|
||||||
|
[Required]
|
||||||
|
public int CategoriaId { get; set; }
|
||||||
|
|
||||||
|
public string? LogoUrl { get; set; }
|
||||||
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// src/Elecciones.Database/Entities/ResumenVoto.cs
|
||||||
using System.ComponentModel.DataAnnotations;
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.ComponentModel.DataAnnotations.Schema;
|
using System.ComponentModel.DataAnnotations.Schema;
|
||||||
|
|
||||||
@@ -9,11 +10,18 @@ public class ResumenVoto
|
|||||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
// El ámbito donde se resume (siempre provincial en este caso)
|
[Required]
|
||||||
public int AmbitoGeograficoId { get; set; }
|
public int AmbitoGeograficoId { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
public string AgrupacionPoliticaId { get; set; } = null!;
|
public string AgrupacionPoliticaId { get; set; } = null!;
|
||||||
|
|
||||||
|
[ForeignKey("AgrupacionPoliticaId")]
|
||||||
|
public AgrupacionPolitica AgrupacionPolitica { get; set; } = null!;
|
||||||
|
|
||||||
|
[Required]
|
||||||
public long Votos { get; set; }
|
public long Votos { get; set; }
|
||||||
|
|
||||||
|
[Required]
|
||||||
public decimal VotosPorcentaje { get; set; }
|
public decimal VotosPorcentaje { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,555 @@
|
|||||||
|
// <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("20250901163255_AddLogoAgrupacionCategoriaTable")]
|
||||||
|
partial class AddLogoAgrupacionCategoriaTable
|
||||||
|
{
|
||||||
|
/// <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.Property<int>("NumeroBanca")
|
||||||
|
.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.LogoAgrupacionCategoria", 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>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId", "CategoriaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("LogosAgrupacionesCategorias");
|
||||||
|
});
|
||||||
|
|
||||||
|
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(450)");
|
||||||
|
|
||||||
|
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.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
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.ResumenVoto", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Ocupante");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,79 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddLogoAgrupacionCategoriaTable : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "AgrupacionPoliticaId",
|
||||||
|
table: "ResumenesVotos",
|
||||||
|
type: "nvarchar(450)",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "nvarchar(max)");
|
||||||
|
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "LogosAgrupacionesCategorias",
|
||||||
|
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),
|
||||||
|
CategoriaId = table.Column<int>(type: "int", nullable: false),
|
||||||
|
LogoUrl = table.Column<string>(type: "nvarchar(max)", nullable: true)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_LogosAgrupacionesCategorias", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_ResumenesVotos_AgrupacionPoliticaId",
|
||||||
|
table: "ResumenesVotos",
|
||||||
|
column: "AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_LogosAgrupacionesCategorias_AgrupacionPoliticaId_CategoriaId",
|
||||||
|
table: "LogosAgrupacionesCategorias",
|
||||||
|
columns: new[] { "AgrupacionPoliticaId", "CategoriaId" },
|
||||||
|
unique: true);
|
||||||
|
|
||||||
|
migrationBuilder.AddForeignKey(
|
||||||
|
name: "FK_ResumenesVotos_AgrupacionesPoliticas_AgrupacionPoliticaId",
|
||||||
|
table: "ResumenesVotos",
|
||||||
|
column: "AgrupacionPoliticaId",
|
||||||
|
principalTable: "AgrupacionesPoliticas",
|
||||||
|
principalColumn: "Id",
|
||||||
|
onDelete: ReferentialAction.Cascade);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropForeignKey(
|
||||||
|
name: "FK_ResumenesVotos_AgrupacionesPoliticas_AgrupacionPoliticaId",
|
||||||
|
table: "ResumenesVotos");
|
||||||
|
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "LogosAgrupacionesCategorias");
|
||||||
|
|
||||||
|
migrationBuilder.DropIndex(
|
||||||
|
name: "IX_ResumenesVotos_AgrupacionPoliticaId",
|
||||||
|
table: "ResumenesVotos");
|
||||||
|
|
||||||
|
migrationBuilder.AlterColumn<string>(
|
||||||
|
name: "AgrupacionPoliticaId",
|
||||||
|
table: "ResumenesVotos",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: false,
|
||||||
|
oldClrType: typeof(string),
|
||||||
|
oldType: "nvarchar(450)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,552 @@
|
|||||||
|
// <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("20250901163521_RemoveLogoUrlFromAgrupacionPolitica")]
|
||||||
|
partial class RemoveLogoUrlFromAgrupacionPolitica
|
||||||
|
{
|
||||||
|
/// <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>("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.Property<int>("NumeroBanca")
|
||||||
|
.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.LogoAgrupacionCategoria", 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>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId", "CategoriaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("LogosAgrupacionesCategorias");
|
||||||
|
});
|
||||||
|
|
||||||
|
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(450)");
|
||||||
|
|
||||||
|
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.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
|
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.ResumenVoto", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b =>
|
||||||
|
{
|
||||||
|
b.Navigation("Ocupante");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace Elecciones.Database.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class RemoveLogoUrlFromAgrupacionPolitica : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropColumn(
|
||||||
|
name: "LogoUrl",
|
||||||
|
table: "AgrupacionesPoliticas");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.AddColumn<string>(
|
||||||
|
name: "LogoUrl",
|
||||||
|
table: "AgrupacionesPoliticas",
|
||||||
|
type: "nvarchar(max)",
|
||||||
|
nullable: true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -61,9 +61,6 @@ namespace Elecciones.Database.Migrations
|
|||||||
.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)");
|
||||||
@@ -275,6 +272,32 @@ namespace Elecciones.Database.Migrations
|
|||||||
b.ToTable("EstadosRecuentosGenerales");
|
b.ToTable("EstadosRecuentosGenerales");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.LogoAgrupacionCategoria", 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>("CategoriaId")
|
||||||
|
.HasColumnType("int");
|
||||||
|
|
||||||
|
b.Property<string>("LogoUrl")
|
||||||
|
.HasColumnType("nvarchar(max)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId", "CategoriaId")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("LogosAgrupacionesCategorias");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Elecciones.Database.Entities.OcupanteBanca", b =>
|
modelBuilder.Entity("Elecciones.Database.Entities.OcupanteBanca", b =>
|
||||||
{
|
{
|
||||||
b.Property<int>("Id")
|
b.Property<int>("Id")
|
||||||
@@ -383,7 +406,7 @@ namespace Elecciones.Database.Migrations
|
|||||||
|
|
||||||
b.Property<string>("AgrupacionPoliticaId")
|
b.Property<string>("AgrupacionPoliticaId")
|
||||||
.IsRequired()
|
.IsRequired()
|
||||||
.HasColumnType("nvarchar(max)");
|
.HasColumnType("nvarchar(450)");
|
||||||
|
|
||||||
b.Property<int>("AmbitoGeograficoId")
|
b.Property<int>("AmbitoGeograficoId")
|
||||||
.HasColumnType("int");
|
.HasColumnType("int");
|
||||||
@@ -397,6 +420,8 @@ namespace Elecciones.Database.Migrations
|
|||||||
|
|
||||||
b.HasKey("Id");
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("AgrupacionPoliticaId");
|
||||||
|
|
||||||
b.ToTable("ResumenesVotos");
|
b.ToTable("ResumenesVotos");
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -503,6 +528,17 @@ namespace Elecciones.Database.Migrations
|
|||||||
b.Navigation("AmbitoGeografico");
|
b.Navigation("AmbitoGeografico");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("Elecciones.Database.Entities.ResumenVoto", b =>
|
||||||
|
{
|
||||||
|
b.HasOne("Elecciones.Database.Entities.AgrupacionPolitica", "AgrupacionPolitica")
|
||||||
|
.WithMany()
|
||||||
|
.HasForeignKey("AgrupacionPoliticaId")
|
||||||
|
.OnDelete(DeleteBehavior.Cascade)
|
||||||
|
.IsRequired();
|
||||||
|
|
||||||
|
b.Navigation("AgrupacionPolitica");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b =>
|
modelBuilder.Entity("Elecciones.Database.Entities.Bancada", b =>
|
||||||
{
|
{
|
||||||
b.Navigation("Ocupante");
|
b.Navigation("Ocupante");
|
||||||
|
|||||||
@@ -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+3b8c6bf754cff6ace486ae8fe850ed4d69233280")]
|
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+608ae655bedf6c59be5fec1e14fc308871d2fd62")]
|
||||||
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")]
|
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")]
|
||||||
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")]
|
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")]
|
||||||
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]
|
||||||
|
|||||||
Reference in New Issue
Block a user