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 | ||||
|     { | ||||
|         #region Clases DTO para la respuesta de la API de BCR | ||||
|         private class BcrTokenResponse { | ||||
|         private class BcrTokenResponse | ||||
|         { | ||||
|             [JsonPropertyName("data")] | ||||
|             public TokenData? Data { get; set; } | ||||
|         } | ||||
|         private class TokenData { | ||||
|         private class TokenData | ||||
|         { | ||||
|             [JsonPropertyName("token")] | ||||
|             public string? Token { get; set; } | ||||
|         } | ||||
|         private class BcrPreciosResponse { | ||||
|         private class BcrPreciosResponse | ||||
|         { | ||||
|             [JsonPropertyName("data")] | ||||
|             public List<BcrPrecioItem>? Data { get; set; } | ||||
|         } | ||||
|         private class BcrPrecioItem { | ||||
|         private class BcrPrecioItem | ||||
|         { | ||||
|             [JsonPropertyName("precio_Cotizacion")] | ||||
|             public decimal PrecioCotizacion { get; set; } | ||||
|             [JsonPropertyName("variacion_Precio_Cotizacion")] | ||||
| @@ -47,10 +51,10 @@ namespace Mercados.Infrastructure.DataFetchers | ||||
|         private readonly ILogger<BcrDataFetcher> _logger; | ||||
|  | ||||
|         public BcrDataFetcher( | ||||
|             IHttpClientFactory httpClientFactory,  | ||||
|             ICotizacionGranoRepository cotizacionRepository,  | ||||
|             IFuenteDatoRepository fuenteDatoRepository,  | ||||
|             IConfiguration configuration,  | ||||
|             IHttpClientFactory httpClientFactory, | ||||
|             ICotizacionGranoRepository cotizacionRepository, | ||||
|             IFuenteDatoRepository fuenteDatoRepository, | ||||
|             IConfiguration configuration, | ||||
|             ILogger<BcrDataFetcher> logger) | ||||
|         { | ||||
|             _httpClientFactory = httpClientFactory; | ||||
| @@ -65,19 +69,26 @@ namespace Mercados.Infrastructure.DataFetchers | ||||
|             _logger.LogInformation("Iniciando fetch para {SourceName}.", SourceName); | ||||
|             try | ||||
|             { | ||||
|                 var client = _httpClientFactory.CreateClient(); | ||||
|                 var client = _httpClientFactory.CreateClient(); // Creamos el cliente una vez | ||||
|  | ||||
|                 var token = await GetAuthTokenAsync(client); | ||||
|                 if (string.IsNullOrEmpty(token)) | ||||
|                 { | ||||
|                     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 fechaDesde = DateTime.Now.AddDays(-3).ToString("yyyy-MM-dd"); | ||||
|                 var fechaHasta = DateTime.Now.ToString("yyyy-MM-dd"); | ||||
|  | ||||
|                 foreach (var grain in _grainIds) | ||||
|                 { | ||||
|                     var response = await client.GetFromJsonAsync<BcrPreciosResponse>( | ||||
|                         $"{BaseUrl}/PreciosCamara?idGrano={grain.Value}&fechaConcertacionDesde={DateTime.Now.AddDays(-3):yyyy-MM-dd}&fechaConcertacionHasta={DateTime.Now:yyyy-MM-dd}"); | ||||
|                     var requestUrl = $"{BaseUrl}/PreciosCamara?idGrano={grain.Value}&fechaConcertacionDesde={fechaDesde}&fechaConcertacionHasta={fechaHasta}"; | ||||
|  | ||||
|                     // 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(); | ||||
|                     if (latestRecord != null) | ||||
| @@ -92,12 +103,12 @@ namespace Mercados.Infrastructure.DataFetchers | ||||
|                         }); | ||||
|                     } | ||||
|                 } | ||||
|                  | ||||
|  | ||||
|                 if (!cotizaciones.Any()) return (false, "No se obtuvieron datos de granos de BCR."); | ||||
|  | ||||
|                 await _cotizacionRepository.GuardarMuchosAsync(cotizaciones); | ||||
|                 await UpdateSourceInfoAsync(); | ||||
|                  | ||||
|  | ||||
|                 _logger.LogInformation("Fetch para {SourceName} completado. Se guardaron {Count} registros.", SourceName, cotizaciones.Count); | ||||
|                 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"); | ||||
|             request.Headers.Add("api_key", _configuration["ApiKeys:Bcr:Key"]); | ||||
|             request.Headers.Add("secret", _configuration["ApiKeys:Bcr:Secret"]); | ||||
|              | ||||
|  | ||||
|             var response = await client.SendAsync(request); | ||||
|             response.EnsureSuccessStatusCode(); | ||||
|  | ||||
|             var tokenResponse = await response.Content.ReadFromJsonAsync<BcrTokenResponse>(); | ||||
|             return tokenResponse?.Data?.Token; | ||||
|         } | ||||
|          | ||||
|  | ||||
|         private async Task UpdateSourceInfoAsync() | ||||
|         { | ||||
|             var fuente = await _fuenteDatoRepository.ObtenerPorNombreAsync(SourceName); | ||||
|   | ||||
| @@ -9,6 +9,7 @@ | ||||
|     <PackageReference Include="Dapper" Version="2.1.66" /> | ||||
|     <PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" /> | ||||
|     <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="YahooFinanceApi" Version="2.3.3" /> | ||||
|   </ItemGroup> | ||||
|   | ||||
| @@ -1,9 +1,11 @@ | ||||
| using System.Text; | ||||
| using Mercados.Infrastructure; | ||||
| using Mercados.Infrastructure.DataFetchers; | ||||
| using Mercados.Infrastructure.Persistence; | ||||
| using Mercados.Infrastructure.Persistence.Repositories; | ||||
| using Mercados.Worker; | ||||
|  | ||||
| Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); | ||||
| // --- Configuración del Host --- | ||||
| // Esto prepara el host del servicio, permitiendo la inyección de dependencias, | ||||
| // la configuración desde appsettings.json y el logging. | ||||
|   | ||||
		Reference in New Issue
	
	Block a user