diff --git a/.env b/.env new file mode 100644 index 0000000..29caaf7 --- /dev/null +++ b/.env @@ -0,0 +1,33 @@ +# ======================================================= +# == Fichero de Entorno para la Aplicación de Mercados == +# ======================================================= +# Este fichero debe estar en /opt/mercados-app/.env en el servidor. +# Contiene todos los secretos y configuraciones específicas del entorno. + +# --- Conexión a la Base de Datos --- +# Cadena de conexión para SQL Server. +# IMPORTANTE: El 'Server' debe ser el nombre del servicio de la base de datos en la red Docker compartida. +ConnectionStrings__DefaultConnection="Server=;Database=;User ID=;Password=;TrustServerCertificate=True;Encrypt=False;" + +# --- Horarios de Ejecución del Worker (formato Cron) --- +Schedules__MercadoAgroganadero="0 10,12,15,18 * * 1-5" +Schedules__BCR="30 11 * * 1-5" +Schedules__Bolsas="10 11-17 * * 1-5" + +# --- Claves de APIs Externas --- +ApiKeys__Finnhub="" +ApiKeys__Bcr__Key="" +ApiKeys__Bcr__Secret="" + +# --- Configuración de Email para Alertas (SMTP) --- +SmtpSettings__Host="" +SmtpSettings__Port="" +SmtpSettings__User="" +SmtpSettings__Pass="" +SmtpSettings__SenderName="Servicio de Mercados" +SmtpSettings__Recipient="" + +# --- Configuración del Entorno de ASP.NET Core --- +# Esto asegura que la aplicación se ejecute en modo Producción, +# desactivando páginas de error detalladas, etc. +ASPNETCORE_ENVIRONMENT="Production" diff --git a/Widgets-ELDIA-1.1.pdf b/Widgets-ELDIA-1.1.pdf new file mode 100644 index 0000000..53d3ec5 Binary files /dev/null and b/Widgets-ELDIA-1.1.pdf differ diff --git a/docker-compose.yml b/docker-compose.yml index d103aa4..5bc0f3a 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ services: # Servicio del Backend API mercados-api: build: - context: ./Mercados-Web # Asumiendo que clonaste el repo en esta carpeta + context: ./Mercados-Web dockerfile: src/Mercados.Api/Dockerfile container_name: mercados-api restart: always @@ -60,4 +60,4 @@ networks: driver: bridge shared-net: - external: true \ No newline at end of file + external: true diff --git a/frontend/src/components/raw-data/RawBolsaLocalTable.tsx b/frontend/src/components/raw-data/RawBolsaLocalTable.tsx index 05c236f..7779bd6 100644 --- a/frontend/src/components/raw-data/RawBolsaLocalTable.tsx +++ b/frontend/src/components/raw-data/RawBolsaLocalTable.tsx @@ -14,12 +14,12 @@ const toTSV = (data: CotizacionBolsa[]) => { // Formateamos el nombre para que quede como "GGAL.BA (GRUPO FINANCIERO GALICIA)" const nombreCompleto = `${row.ticker} (${row.nombreEmpresa || ''})`; const precio = `$${formatCurrency(row.precioActual)}` - const cambio = `${row.porcentajeCambio.toFixed(2)}%` + const cambio = `${formatCurrency(row.porcentajeCambio)}%` //`${row.porcentajeCambio.toFixed(2)}%` // Unimos los campos con un carácter de tabulación '\t' return [nombreCompleto, precio, cambio].join('\t'); }); - + // Unimos todas las filas con un salto de línea return dataRows.join('\n'); }; @@ -32,14 +32,14 @@ export const RawBolsaLocalTable = () => { // Separamos los datos en prioritarios y el resto const priorityData = data?.filter(d => TICKERS_PRIORITARIOS_LOCAL.includes(d.ticker)) - .sort((a, b) => TICKERS_PRIORITARIOS_LOCAL.indexOf(a.ticker) - TICKERS_PRIORITARIOS_LOCAL.indexOf(b.ticker)); // Mantenemos el orden - + .sort((a, b) => TICKERS_PRIORITARIOS_LOCAL.indexOf(a.ticker) - TICKERS_PRIORITARIOS_LOCAL.indexOf(b.ticker)); // Mantenemos el orden + const otherData = data?.filter(d => !TICKERS_PRIORITARIOS_LOCAL.includes(d.ticker)); const handleCopy = () => { if (!priorityData) return; const tsvData = toTSV(priorityData); - + copyToClipboard(tsvData) .then(() => alert('Datos prioritarios copiados al portapapeles.')) .catch(err => { @@ -81,7 +81,7 @@ export const RawBolsaLocalTable = () => { ({row.nombreEmpresa}) ${formatCurrency(row.precioActual)} - {row.porcentajeCambio.toFixed(2)}% + {formatCurrency(row.porcentajeCambio)}% ))} @@ -98,17 +98,20 @@ export const RawBolsaLocalTable = () => { - Ticker - Nombre - Precio + Símbolo (Nombre) + Precio Actual + % Cambio {otherData.map(row => ( - {row.ticker} - {row.nombreEmpresa} + + {row.ticker} + ({row.nombreEmpresa}) + ${formatCurrency(row.precioActual)} + {formatCurrency(row.porcentajeCambio)}% ))} diff --git a/frontend/src/components/raw-data/RawBolsaUsaTable.tsx b/frontend/src/components/raw-data/RawBolsaUsaTable.tsx index 4553184..4e70d41 100644 --- a/frontend/src/components/raw-data/RawBolsaUsaTable.tsx +++ b/frontend/src/components/raw-data/RawBolsaUsaTable.tsx @@ -18,7 +18,7 @@ const toTSV = (data: CotizacionBolsa[]) => { // Formateamos los datos según los requisitos de redacción const nombreCompleto = `${row.ticker} (${row.nombreEmpresa || ''})`; const precio = `$${formatCurrency(row.precioActual)}`; - const cambio = `${row.porcentajeCambio.toFixed(2)}%`; + const cambio = `${formatCurrency(row.porcentajeCambio)}%`; return [nombreCompleto, precio, cambio].join('\t'); }); @@ -35,14 +35,14 @@ export const RawBolsaUsaTable = () => { // Separamos los datos en prioritarios y el resto, manteniendo el orden de la lista const priorityData = data?.filter(d => TICKERS_PRIORITARIOS_USA.includes(d.ticker)) - .sort((a, b) => TICKERS_PRIORITARIOS_USA.indexOf(a.ticker) - TICKERS_PRIORITARIOS_USA.indexOf(b.ticker)); - + .sort((a, b) => TICKERS_PRIORITARIOS_USA.indexOf(a.ticker) - TICKERS_PRIORITARIOS_USA.indexOf(b.ticker)); + const otherData = data?.filter(d => !TICKERS_PRIORITARIOS_USA.includes(d.ticker)); const handleCopy = () => { if (!priorityData) return; const tsvData = toTSV(priorityData); - + copyToClipboard(tsvData) .then(() => alert('Datos prioritarios copiados al portapapeles!')) .catch(err => { @@ -91,8 +91,8 @@ export const RawBolsaUsaTable = () => { {row.ticker}({row.nombreEmpresa}) - {formatCurrency(row.precioActual, 'USD')} - {row.porcentajeCambio.toFixed(2)}% + ${formatCurrency(row.precioActual)} + {formatCurrency(row.porcentajeCambio)}% ))} @@ -109,17 +109,20 @@ export const RawBolsaUsaTable = () => {
- Ticker - Nombre - Precio + Símbolo (Nombre) + Precio Actual + % Cambio {otherData.map(row => ( - {row.ticker} - {row.nombreEmpresa} - {formatCurrency(row.precioActual, 'USD')} + + {row.ticker} + ({row.nombreEmpresa}) + + ${formatCurrency(row.precioActual)} + {formatCurrency(row.porcentajeCambio)}% ))}