feat: Add visual summary cards for Agro/Grains and implement 24h time format
This commit is contained in:
@@ -12,12 +12,12 @@ namespace Mercados.Api.Controllers
|
||||
private readonly ICotizacionGranoRepository _granoRepo;
|
||||
private readonly ICotizacionGanadoRepository _ganadoRepo;
|
||||
private readonly ILogger<MercadosController> _logger;
|
||||
|
||||
|
||||
// Inyectamos TODOS los repositorios que necesita el controlador.
|
||||
public MercadosController(
|
||||
ICotizacionBolsaRepository bolsaRepo,
|
||||
ICotizacionGranoRepository granoRepo,
|
||||
ICotizacionGanadoRepository ganadoRepo,
|
||||
ICotizacionBolsaRepository bolsaRepo,
|
||||
ICotizacionGranoRepository granoRepo,
|
||||
ICotizacionGanadoRepository ganadoRepo,
|
||||
ILogger<MercadosController> logger)
|
||||
{
|
||||
_bolsaRepo = bolsaRepo;
|
||||
@@ -61,7 +61,7 @@ namespace Mercados.Api.Controllers
|
||||
return StatusCode(500, "Ocurrió un error interno en el servidor.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- Endpoints de Bolsa ---
|
||||
[HttpGet("bolsa/eeuu")]
|
||||
[ProducesResponseType(typeof(IEnumerable<CotizacionBolsa>), StatusCodes.Status200OK)]
|
||||
@@ -96,5 +96,22 @@ namespace Mercados.Api.Controllers
|
||||
return StatusCode(500, "Ocurrió un error interno en el servidor.");
|
||||
}
|
||||
}
|
||||
|
||||
[HttpGet("bolsa/history/{ticker}")]
|
||||
[ProducesResponseType(typeof(IEnumerable<CotizacionBolsa>), StatusCodes.Status200OK)]
|
||||
[ProducesResponseType(StatusCodes.Status500InternalServerError)]
|
||||
public async Task<IActionResult> GetBolsaHistory(string ticker, [FromQuery] string mercado = "Local", [FromQuery] int dias = 30)
|
||||
{
|
||||
try
|
||||
{
|
||||
var data = await _bolsaRepo.ObtenerHistorialPorTickerAsync(ticker, mercado, dias);
|
||||
return Ok(data);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error al obtener historial para el ticker {Ticker}.", ticker);
|
||||
return StatusCode(500, "Ocurrió un error interno en el servidor.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
@Mercados.Api_HostAddress = http://localhost:5045
|
||||
@Mercados.Api_HostAddress = http://192.168.10.78:5045
|
||||
|
||||
GET {{Mercados.Api_HostAddress}}/weatherforecast/
|
||||
Accept: application/json
|
||||
|
||||
###
|
||||
###
|
||||
@@ -16,7 +16,7 @@ builder.Services.AddCors(options =>
|
||||
options.AddPolicy(name: MyAllowSpecificOrigins,
|
||||
policy =>
|
||||
{
|
||||
policy.WithOrigins("http://localhost:5173")
|
||||
policy.WithOrigins("http://localhost:5173", "http://192.168.10.78:5173")
|
||||
.AllowAnyHeader()
|
||||
.AllowAnyMethod();
|
||||
});
|
||||
@@ -47,7 +47,6 @@ builder.Services
|
||||
|
||||
// Add services to the container.
|
||||
builder.Services.AddControllers();
|
||||
// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle
|
||||
builder.Services.AddEndpointsApiExplorer();
|
||||
builder.Services.AddSwaggerGen();
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:5045",
|
||||
"applicationUrl": "http://0.0.0.0:5045",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "https://localhost:7256;http://localhost:5045",
|
||||
"applicationUrl": "https://0.0.0.0:7256;http://0.0.0.0:5045",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
|
||||
@@ -23,12 +23,12 @@ namespace Mercados.Infrastructure.Persistence.Repositories
|
||||
|
||||
await connection.ExecuteAsync(sql, cotizaciones);
|
||||
}
|
||||
|
||||
|
||||
public async Task<IEnumerable<CotizacionBolsa>> ObtenerUltimasPorMercadoAsync(string mercado)
|
||||
{
|
||||
using IDbConnection connection = _connectionFactory.CreateConnection();
|
||||
|
||||
// Esta consulta SQL es un poco más avanzada. Usa una "Common Table Expression" (CTE)
|
||||
// Esta consulta usa una "Common Table Expression" (CTE)
|
||||
// y la función ROW_NUMBER() para obtener el registro más reciente para cada Ticker
|
||||
// dentro del mercado especificado. Es extremadamente eficiente.
|
||||
const string sql = @"
|
||||
@@ -50,5 +50,24 @@ namespace Mercados.Infrastructure.Persistence.Repositories
|
||||
|
||||
return await connection.QueryAsync<CotizacionBolsa>(sql, new { Mercado = mercado });
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<CotizacionBolsa>> ObtenerHistorialPorTickerAsync(string ticker, string mercado, int dias)
|
||||
{
|
||||
using IDbConnection connection = _connectionFactory.CreateConnection();
|
||||
|
||||
const string sql = @"
|
||||
SELECT
|
||||
Id, Ticker, Mercado, PrecioActual, Apertura, CierreAnterior, PorcentajeCambio, FechaRegistro
|
||||
FROM
|
||||
CotizacionesBolsa
|
||||
WHERE
|
||||
Ticker = @Ticker
|
||||
AND Mercado = @Mercado
|
||||
AND FechaRegistro >= DATEADD(day, -@Dias, GETUTCDATE())
|
||||
ORDER BY
|
||||
FechaRegistro ASC;"; // ASC es importante para dibujar la línea del gráfico
|
||||
|
||||
return await connection.QueryAsync<CotizacionBolsa>(sql, new { Ticker = ticker, Mercado = mercado, Dias = dias });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,5 +6,6 @@ namespace Mercados.Infrastructure.Persistence.Repositories
|
||||
{
|
||||
Task GuardarMuchosAsync(IEnumerable<CotizacionBolsa> cotizaciones);
|
||||
Task<IEnumerable<CotizacionBolsa>> ObtenerUltimasPorMercadoAsync(string mercado);
|
||||
Task<IEnumerable<CotizacionBolsa>> ObtenerHistorialPorTickerAsync(string ticker, string mercado, int dias);
|
||||
}
|
||||
}
|
||||
@@ -35,7 +35,7 @@ IHost host = Host.CreateDefaultBuilder(args)
|
||||
// que todos implementan la interfaz IDataFetcher.
|
||||
services.AddScoped<IDataFetcher, MercadoAgroFetcher>();
|
||||
services.AddScoped<IDataFetcher, BcrDataFetcher>();
|
||||
//services.AddScoped<IDataFetcher, FinnhubDataFetcher>();
|
||||
services.AddScoped<IDataFetcher, FinnhubDataFetcher>();
|
||||
services.AddScoped<IDataFetcher, YahooFinanceDataFetcher>();
|
||||
|
||||
// El cliente HTTP es fundamental para hacer llamadas a APIs externas.
|
||||
|
||||
Reference in New Issue
Block a user