fix: Resolve encoding issue for AgroFetcher and authorization for BcrFetcher
This commit is contained in:
		| @@ -11,19 +11,23 @@ namespace Mercados.Infrastructure.DataFetchers | |||||||
|     public class BcrDataFetcher : IDataFetcher |     public class BcrDataFetcher : IDataFetcher | ||||||
|     { |     { | ||||||
|         #region Clases DTO para la respuesta de la API de BCR |         #region Clases DTO para la respuesta de la API de BCR | ||||||
|         private class BcrTokenResponse { |         private class BcrTokenResponse | ||||||
|  |         { | ||||||
|             [JsonPropertyName("data")] |             [JsonPropertyName("data")] | ||||||
|             public TokenData? Data { get; set; } |             public TokenData? Data { get; set; } | ||||||
|         } |         } | ||||||
|         private class TokenData { |         private class TokenData | ||||||
|  |         { | ||||||
|             [JsonPropertyName("token")] |             [JsonPropertyName("token")] | ||||||
|             public string? Token { get; set; } |             public string? Token { get; set; } | ||||||
|         } |         } | ||||||
|         private class BcrPreciosResponse { |         private class BcrPreciosResponse | ||||||
|  |         { | ||||||
|             [JsonPropertyName("data")] |             [JsonPropertyName("data")] | ||||||
|             public List<BcrPrecioItem>? Data { get; set; } |             public List<BcrPrecioItem>? Data { get; set; } | ||||||
|         } |         } | ||||||
|         private class BcrPrecioItem { |         private class BcrPrecioItem | ||||||
|  |         { | ||||||
|             [JsonPropertyName("precio_Cotizacion")] |             [JsonPropertyName("precio_Cotizacion")] | ||||||
|             public decimal PrecioCotizacion { get; set; } |             public decimal PrecioCotizacion { get; set; } | ||||||
|             [JsonPropertyName("variacion_Precio_Cotizacion")] |             [JsonPropertyName("variacion_Precio_Cotizacion")] | ||||||
| @@ -47,10 +51,10 @@ namespace Mercados.Infrastructure.DataFetchers | |||||||
|         private readonly ILogger<BcrDataFetcher> _logger; |         private readonly ILogger<BcrDataFetcher> _logger; | ||||||
|  |  | ||||||
|         public BcrDataFetcher( |         public BcrDataFetcher( | ||||||
|             IHttpClientFactory httpClientFactory,  |             IHttpClientFactory httpClientFactory, | ||||||
|             ICotizacionGranoRepository cotizacionRepository,  |             ICotizacionGranoRepository cotizacionRepository, | ||||||
|             IFuenteDatoRepository fuenteDatoRepository,  |             IFuenteDatoRepository fuenteDatoRepository, | ||||||
|             IConfiguration configuration,  |             IConfiguration configuration, | ||||||
|             ILogger<BcrDataFetcher> logger) |             ILogger<BcrDataFetcher> logger) | ||||||
|         { |         { | ||||||
|             _httpClientFactory = httpClientFactory; |             _httpClientFactory = httpClientFactory; | ||||||
| @@ -65,19 +69,26 @@ namespace Mercados.Infrastructure.DataFetchers | |||||||
|             _logger.LogInformation("Iniciando fetch para {SourceName}.", SourceName); |             _logger.LogInformation("Iniciando fetch para {SourceName}.", SourceName); | ||||||
|             try |             try | ||||||
|             { |             { | ||||||
|                 var client = _httpClientFactory.CreateClient(); |                 var client = _httpClientFactory.CreateClient(); // Creamos el cliente una vez | ||||||
|  |  | ||||||
|                 var token = await GetAuthTokenAsync(client); |                 var token = await GetAuthTokenAsync(client); | ||||||
|                 if (string.IsNullOrEmpty(token)) |                 if (string.IsNullOrEmpty(token)) | ||||||
|                 { |                 { | ||||||
|                     return (false, "No se pudo obtener el token de autenticación de BCR."); |                     return (false, "No se pudo obtener el token de autenticación de BCR."); | ||||||
|                 } |                 } | ||||||
|                 client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); |                 // Añadimos el token a las cabeceras por defecto de este cliente para todas las peticiones futuras. | ||||||
|  |                 client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token.Replace("Bearer ", "")); // Aseguramos que no haya doble "Bearer" | ||||||
|  |  | ||||||
|                 var cotizaciones = new List<CotizacionGrano>(); |                 var cotizaciones = new List<CotizacionGrano>(); | ||||||
|  |                 var fechaDesde = DateTime.Now.AddDays(-3).ToString("yyyy-MM-dd"); | ||||||
|  |                 var fechaHasta = DateTime.Now.ToString("yyyy-MM-dd"); | ||||||
|  |  | ||||||
|                 foreach (var grain in _grainIds) |                 foreach (var grain in _grainIds) | ||||||
|                 { |                 { | ||||||
|                     var response = await client.GetFromJsonAsync<BcrPreciosResponse>( |                     var requestUrl = $"{BaseUrl}/PreciosCamara?idGrano={grain.Value}&fechaConcertacionDesde={fechaDesde}&fechaConcertacionHasta={fechaHasta}"; | ||||||
|                         $"{BaseUrl}/PreciosCamara?idGrano={grain.Value}&fechaConcertacionDesde={DateTime.Now.AddDays(-3):yyyy-MM-dd}&fechaConcertacionHasta={DateTime.Now:yyyy-MM-dd}"); |  | ||||||
|  |                     // Usamos el mismo cliente que ya tiene el token configurado. | ||||||
|  |                     var response = await client.GetFromJsonAsync<BcrPreciosResponse>(requestUrl); | ||||||
|  |  | ||||||
|                     var latestRecord = response?.Data?.OrderByDescending(r => r.FechaOperacionPizarra).FirstOrDefault(); |                     var latestRecord = response?.Data?.OrderByDescending(r => r.FechaOperacionPizarra).FirstOrDefault(); | ||||||
|                     if (latestRecord != null) |                     if (latestRecord != null) | ||||||
| @@ -92,12 +103,12 @@ namespace Mercados.Infrastructure.DataFetchers | |||||||
|                         }); |                         }); | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|                  |  | ||||||
|                 if (!cotizaciones.Any()) return (false, "No se obtuvieron datos de granos de BCR."); |                 if (!cotizaciones.Any()) return (false, "No se obtuvieron datos de granos de BCR."); | ||||||
|  |  | ||||||
|                 await _cotizacionRepository.GuardarMuchosAsync(cotizaciones); |                 await _cotizacionRepository.GuardarMuchosAsync(cotizaciones); | ||||||
|                 await UpdateSourceInfoAsync(); |                 await UpdateSourceInfoAsync(); | ||||||
|                  |  | ||||||
|                 _logger.LogInformation("Fetch para {SourceName} completado. Se guardaron {Count} registros.", SourceName, cotizaciones.Count); |                 _logger.LogInformation("Fetch para {SourceName} completado. Se guardaron {Count} registros.", SourceName, cotizaciones.Count); | ||||||
|                 return (true, $"Proceso completado. Se guardaron {cotizaciones.Count} registros."); |                 return (true, $"Proceso completado. Se guardaron {cotizaciones.Count} registros."); | ||||||
|             } |             } | ||||||
| @@ -113,14 +124,14 @@ namespace Mercados.Infrastructure.DataFetchers | |||||||
|             var request = new HttpRequestMessage(HttpMethod.Post, $"{BaseUrl}/Login"); |             var request = new HttpRequestMessage(HttpMethod.Post, $"{BaseUrl}/Login"); | ||||||
|             request.Headers.Add("api_key", _configuration["ApiKeys:Bcr:Key"]); |             request.Headers.Add("api_key", _configuration["ApiKeys:Bcr:Key"]); | ||||||
|             request.Headers.Add("secret", _configuration["ApiKeys:Bcr:Secret"]); |             request.Headers.Add("secret", _configuration["ApiKeys:Bcr:Secret"]); | ||||||
|              |  | ||||||
|             var response = await client.SendAsync(request); |             var response = await client.SendAsync(request); | ||||||
|             response.EnsureSuccessStatusCode(); |             response.EnsureSuccessStatusCode(); | ||||||
|  |  | ||||||
|             var tokenResponse = await response.Content.ReadFromJsonAsync<BcrTokenResponse>(); |             var tokenResponse = await response.Content.ReadFromJsonAsync<BcrTokenResponse>(); | ||||||
|             return tokenResponse?.Data?.Token; |             return tokenResponse?.Data?.Token; | ||||||
|         } |         } | ||||||
|          |  | ||||||
|         private async Task UpdateSourceInfoAsync() |         private async Task UpdateSourceInfoAsync() | ||||||
|         { |         { | ||||||
|             var fuente = await _fuenteDatoRepository.ObtenerPorNombreAsync(SourceName); |             var fuente = await _fuenteDatoRepository.ObtenerPorNombreAsync(SourceName); | ||||||
|   | |||||||
| @@ -9,6 +9,7 @@ | |||||||
|     <PackageReference Include="Dapper" Version="2.1.66" /> |     <PackageReference Include="Dapper" Version="2.1.66" /> | ||||||
|     <PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" /> |     <PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" /> | ||||||
|     <PackageReference Include="Microsoft.Extensions.Http" Version="9.0.6" /> |     <PackageReference Include="Microsoft.Extensions.Http" Version="9.0.6" /> | ||||||
|  |     <PackageReference Include="System.Text.Encoding.CodePages" Version="9.0.6" /> | ||||||
|     <PackageReference Include="ThreeFourteen.Finnhub.Client" Version="1.2.0" /> |     <PackageReference Include="ThreeFourteen.Finnhub.Client" Version="1.2.0" /> | ||||||
|     <PackageReference Include="YahooFinanceApi" Version="2.3.3" /> |     <PackageReference Include="YahooFinanceApi" Version="2.3.3" /> | ||||||
|   </ItemGroup> |   </ItemGroup> | ||||||
|   | |||||||
| @@ -1,9 +1,11 @@ | |||||||
|  | using System.Text; | ||||||
| using Mercados.Infrastructure; | using Mercados.Infrastructure; | ||||||
| using Mercados.Infrastructure.DataFetchers; | using Mercados.Infrastructure.DataFetchers; | ||||||
| using Mercados.Infrastructure.Persistence; | using Mercados.Infrastructure.Persistence; | ||||||
| using Mercados.Infrastructure.Persistence.Repositories; | using Mercados.Infrastructure.Persistence.Repositories; | ||||||
| using Mercados.Worker; | using Mercados.Worker; | ||||||
|  |  | ||||||
|  | Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); | ||||||
| // --- Configuración del Host --- | // --- Configuración del Host --- | ||||||
| // Esto prepara el host del servicio, permitiendo la inyección de dependencias, | // Esto prepara el host del servicio, permitiendo la inyección de dependencias, | ||||||
| // la configuración desde appsettings.json y el logging. | // la configuración desde appsettings.json y el logging. | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user