Mismo que anterior Commit
This commit is contained in:
		@@ -1,13 +1,13 @@
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk.Web">
 | 
			
		||||
<Project Sdk="Microsoft.NET.Sdk.Web">
 | 
			
		||||
 | 
			
		||||
  <PropertyGroup>
 | 
			
		||||
    <TargetFramework>net9.0</TargetFramework>
 | 
			
		||||
    <Nullable>enable</Nullable>
 | 
			
		||||
    <ImplicitUsings>enable</ImplicitUsings>
 | 
			
		||||
    <UserSecretsId>28c6a673-1f1e-4140-aa75-a0d894d1fbc4</UserSecretsId>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <PackageReference Include="DotNetEnv" Version="3.1.1" />
 | 
			
		||||
    <PackageReference Include="FluentMigrator.Runner" Version="7.1.0" />
 | 
			
		||||
    <PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="9.0.5" />
 | 
			
		||||
    <PackageReference Include="Swashbuckle.AspNetCore" Version="9.0.1" />
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										27
									
								
								src/Mercados.Api/Utils/UtcDateTimeConverter.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/Mercados.Api/Utils/UtcDateTimeConverter.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,27 @@
 | 
			
		||||
using System.Text.Json;
 | 
			
		||||
using System.Text.Json.Serialization;
 | 
			
		||||
 | 
			
		||||
namespace Mercados.Api.Utils
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Un convertidor de JSON personalizado para asegurar que los objetos DateTime
 | 
			
		||||
    /// se serialicen al formato ISO 8601 en UTC (con el designador 'Z').
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class UtcDateTimeConverter : JsonConverter<DateTime>
 | 
			
		||||
    {
 | 
			
		||||
        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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -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": ""
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user