diff --git a/.env b/.env deleted file mode 100644 index dea7adf..0000000 --- a/.env +++ /dev/null @@ -1,15 +0,0 @@ -# --- Conexión a la Base de Datos --- -ConnectionStrings__DefaultConnection="Server=TECNICA3;Database=MercadosDb;User Id=mercadosuser;Password=@mercados1351@;Trusted_Connection=False;Encrypt=False;" - -# --- Claves de APIs Externas --- -ApiKeys__Finnhub="cuvhr0hr01qs9e81st2gcuvhr0hr01qs9e81st30" -ApiKeys__Bcr__Key="D1782A51-A5FD-EF11-9445-00155D09E201" -ApiKeys__Bcr__Secret="da96378186bc5a256fa821fbe79261ec7172dec283214da0aacca41c640f80e3" - -# --- Configuración de Email para Alertas --- -SMTP_HOST="mail.eldia.com" -SMTP_PORT="587" -SMTP_USER="alertas@eldia.com" -SMTP_PASS="@Alertas713550@" -EMAIL_SENDER_NAME="Servicio de Mercados" -EMAIL_RECIPIENT="dmolinari@eldia.com" \ No newline at end of file diff --git a/src/Mercados.Api/Mercados.Api.csproj b/src/Mercados.Api/Mercados.Api.csproj index a586c48..1942c04 100644 --- a/src/Mercados.Api/Mercados.Api.csproj +++ b/src/Mercados.Api/Mercados.Api.csproj @@ -1,13 +1,13 @@ - + net9.0 enable enable + 28c6a673-1f1e-4140-aa75-a0d894d1fbc4 - diff --git a/src/Mercados.Api/Program.cs b/src/Mercados.Api/Program.cs index 6207ff6..b2bfde6 100644 --- a/src/Mercados.Api/Program.cs +++ b/src/Mercados.Api/Program.cs @@ -1,19 +1,9 @@ -using DotNetEnv; using FluentMigrator.Runner; using Mercados.Database.Migrations; using Mercados.Infrastructure; using Mercados.Infrastructure.Persistence; using Mercados.Infrastructure.Persistence.Repositories; -using DotNetEnv.Configuration; - - -var envFilePath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../../../.env")); - -// Cargamos el archivo .env desde la ruta explícita. -if (!Env.Load(envFilePath).Any()) -{ - Console.WriteLine($"ADVERTENCIA: No se pudo encontrar el archivo .env en la ruta: {envFilePath}"); -} +using Mercados.Api.Utils; var builder = WebApplication.CreateBuilder(args); @@ -50,7 +40,14 @@ builder.Services .ScanIn(typeof(CreateInitialTables).Assembly).For.Migrations()) .AddLogging(lb => lb.AddFluentMigratorConsole()); -// Servicios del contenedor estándar (perfecto) + +builder.Services.AddControllers() + .AddJsonOptions(options => + { + // Añadimos nuestro convertidor personalizado para manejar las fechas. + options.JsonSerializerOptions.Converters.Add(new UtcDateTimeConverter()); + }); + builder.Services.AddControllers(); builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); diff --git a/src/Mercados.Api/Utils/UtcDateTimeConverter.cs b/src/Mercados.Api/Utils/UtcDateTimeConverter.cs new file mode 100644 index 0000000..ac37274 --- /dev/null +++ b/src/Mercados.Api/Utils/UtcDateTimeConverter.cs @@ -0,0 +1,27 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace Mercados.Api.Utils +{ + /// + /// Un convertidor de JSON personalizado para asegurar que los objetos DateTime + /// se serialicen al formato ISO 8601 en UTC (con el designador 'Z'). + /// + public class UtcDateTimeConverter : JsonConverter + { + public override DateTime Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + // Al leer un string de fecha, nos aseguramos de que se interprete como UTC + return reader.GetDateTime().ToUniversalTime(); + } + + public override void Write(Utf8JsonWriter writer, DateTime value, JsonSerializerOptions options) + { + // Antes de escribir el string, especificamos que el 'Kind' es Utc. + // Si ya es Utc, no hace nada. Si es Local o Unspecified, lo trata como si fuera Utc. + // Esto es seguro porque sabemos que todas nuestras fechas en la BD son UTC. + var utcValue = DateTime.SpecifyKind(value, DateTimeKind.Utc); + writer.WriteStringValue(utcValue); + } + } +} \ No newline at end of file diff --git a/src/Mercados.Api/appsettings.json b/src/Mercados.Api/appsettings.json index 6c56bd7..d2132b6 100644 --- a/src/Mercados.Api/appsettings.json +++ b/src/Mercados.Api/appsettings.json @@ -9,11 +9,24 @@ "ConnectionStrings": { "DefaultConnection": "" }, + "Schedules": { + "MercadoAgroganadero": "0 11 * * 1-5", + "BCR": "30 11 * * 1-5", + "Bolsas": "10 11-17 * * 1-5" + }, "ApiKeys": { "Finnhub": "", "Bcr": { "Key": "", "Secret": "" } + }, + "SmtpSettings": { + "Host": "", + "Port": 587, + "User": "", + "Pass": "", + "SenderName": "Servicio de Mercados", + "Recipient": "" } } \ No newline at end of file diff --git a/src/Mercados.Infrastructure/Services/EmailNotificationService.cs b/src/Mercados.Infrastructure/Services/EmailNotificationService.cs index 1ef141c..747c78d 100644 --- a/src/Mercados.Infrastructure/Services/EmailNotificationService.cs +++ b/src/Mercados.Infrastructure/Services/EmailNotificationService.cs @@ -20,12 +20,12 @@ namespace Mercados.Infrastructure.Services public async Task SendFailureAlertAsync(string subject, string message, DateTime? eventTimeUtc = null) { // Leemos la configuración de forma segura desde IConfiguration (que a su vez lee el .env) - var smtpHost = _configuration["SMTP_HOST"]; - var smtpPort = int.Parse(_configuration["SMTP_PORT"] ?? "587"); - var smtpUser = _configuration["SMTP_USER"]; - var smtpPass = _configuration["SMTP_PASS"]; - var senderName = _configuration["EMAIL_SENDER_NAME"]; - var recipient = _configuration["EMAIL_RECIPIENT"]; + var smtpHost = _configuration["SmtpSettings:Host"]; + var smtpPort = _configuration.GetValue("SmtpSettings:Port"); + var smtpUser = _configuration["SmtpSettings:User"]; + var smtpPass = _configuration["SmtpSettings:Pass"]; + var senderName = _configuration["SmtpSettings:SenderName"]; + var recipient = _configuration["SmtpSettings:Recipient"]; if (string.IsNullOrEmpty(smtpHost) || string.IsNullOrEmpty(smtpUser) || string.IsNullOrEmpty(smtpPass)) { diff --git a/src/Mercados.Worker/Mercados.Worker.csproj b/src/Mercados.Worker/Mercados.Worker.csproj index a9b5af5..d0aec2c 100644 --- a/src/Mercados.Worker/Mercados.Worker.csproj +++ b/src/Mercados.Worker/Mercados.Worker.csproj @@ -9,7 +9,6 @@ - diff --git a/src/Mercados.Worker/Program.cs b/src/Mercados.Worker/Program.cs index 2c7aabf..bf0d5eb 100644 --- a/src/Mercados.Worker/Program.cs +++ b/src/Mercados.Worker/Program.cs @@ -7,49 +7,30 @@ using Mercados.Worker; using Polly; using Polly.Extensions.Http; using Mercados.Infrastructure.Services; -using DotNetEnv; -using DotNetEnv.Configuration; - -var envFilePath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "../../../../../.env")); - -// Cargamos el archivo .env desde la ruta explícita. -// Si no lo encuentra, Load retornará false. -if (!Env.Load(envFilePath).Any()) -{ - Console.WriteLine($"ADVERTENCIA: No se pudo encontrar el archivo .env en la ruta: {envFilePath}"); -} - -Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); IHost host = Host.CreateDefaultBuilder(args) .ConfigureServices((hostContext, services) => { - // La línea 'config.AddDotNetEnv(optional: true);' ha sido eliminada. - IConfiguration configuration = hostContext.Configuration; - // --- 1. Registro de Servicios de Infraestructura --- + // El resto del código no cambia. IConfiguration recogerá automáticamente + // las variables de entorno que cargamos correctamente. services.AddSingleton(); services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); - //services.AddScoped(); services.AddScoped(); - // --- 2. Registro de los Data Fetchers --- - // Descomentados para la versión final y funcional. services.AddScoped(); services.AddScoped(); services.AddScoped(); services.AddScoped(); - // --- 3. Configuración de Clientes HTTP con Polly --- services.AddHttpClient("MercadoAgroFetcher").AddPolicyHandler(GetRetryPolicy()); services.AddHttpClient("BcrDataFetcher").AddPolicyHandler(GetRetryPolicy()); services.AddHttpClient("FinnhubDataFetcher").AddPolicyHandler(GetRetryPolicy()); - // --- 4. Registro del Worker Principal --- services.AddHostedService(); }) .Build(); diff --git a/src/Mercados.Worker/appsettings.json b/src/Mercados.Worker/appsettings.json index baf189e..d2132b6 100644 --- a/src/Mercados.Worker/appsettings.json +++ b/src/Mercados.Worker/appsettings.json @@ -20,5 +20,13 @@ "Key": "", "Secret": "" } + }, + "SmtpSettings": { + "Host": "", + "Port": 587, + "User": "", + "Pass": "", + "SenderName": "Servicio de Mercados", + "Recipient": "" } } \ No newline at end of file