Add ExchangeRate Function BCRA
Some checks failed
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Failing after 56s
Some checks failed
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Failing after 56s
This commit is contained in:
parent
3d6af27e34
commit
e1bd50d4d6
13
Core/Interfaces/IExchangeRateDom.cs
Normal file
13
Core/Interfaces/IExchangeRateDom.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Core.Interfaces
|
||||
{
|
||||
public interface IExchangeRateDom
|
||||
{
|
||||
Task<EExchangeRateHistory> GetYesterdayRateAsync();
|
||||
/// <summary>
|
||||
/// Solo lee del histórico; no dispara llamada externa.
|
||||
/// </summary>
|
||||
Task<EExchangeRateHistory?> GetByDateAsync(DateOnly date);
|
||||
}
|
||||
}
|
||||
97
Core/Services/ExchangeRateService.cs
Normal file
97
Core/Services/ExchangeRateService.cs
Normal file
@ -0,0 +1,97 @@
|
||||
using Core.Interfaces;
|
||||
using Domain.Entities;
|
||||
using Models.Interfaces;
|
||||
using System.Net.Http.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
public class ExchangeRateDom : IExchangeRateDom
|
||||
{
|
||||
private readonly IPhOHExchangeRateHistory _repository;
|
||||
private readonly HttpClient _http;
|
||||
|
||||
public ExchangeRateDom(IPhOHExchangeRateHistory repository, HttpClient http)
|
||||
{
|
||||
_repository = repository;
|
||||
_http = http;
|
||||
}
|
||||
|
||||
public async Task<EExchangeRateHistory> GetYesterdayRateAsync()
|
||||
{
|
||||
// 1) Calcular “ayer” en ART
|
||||
var argentinaNow = DateTime.UtcNow.AddHours(-3);
|
||||
var yesterday = DateOnly.FromDateTime(argentinaNow.Date.AddDays(-1));
|
||||
|
||||
// 2) Intentar rescatar del histórico
|
||||
var existing = await _repository.GetByDateAsync(yesterday);
|
||||
if (existing is not null)
|
||||
return existing;
|
||||
|
||||
// 3) Si no está, llamar al API BCRA pedimos desde hace 7 días hasta ayer para saltar feriados/fines de semana
|
||||
var from = yesterday.AddDays(-7).ToString("yyyy-MM-dd");
|
||||
var to = yesterday.ToString("yyyy-MM-dd");
|
||||
var url = $"estadisticascambiarias/v1.0/Cotizaciones/USD?fechadesde={from}&fechahasta={to}";
|
||||
|
||||
var series = await _http.GetFromJsonAsync<SeriesResponse>(url)
|
||||
?? throw new InvalidOperationException("No se obtuvo JSON válido del BCRA");
|
||||
|
||||
if (series.Results == null || !series.Results.Any())
|
||||
throw new InvalidOperationException("No hay datos de cotización en el período solicitado");
|
||||
|
||||
// 4) El primer elemento es el más reciente (ayer o último día hábil)
|
||||
var day = series.Results.First();
|
||||
var detail = day.Details.First(d => d.CodigoMoneda == "USD");
|
||||
var rate = detail.TipoCotizacion;
|
||||
|
||||
// 5) Construir dominio y persistir
|
||||
var entity = new EExchangeRateHistory
|
||||
{
|
||||
Ratedate = yesterday,
|
||||
Purchaserate = rate,
|
||||
Salerate = rate,
|
||||
Source = "BCRA",
|
||||
Createdat = DateTime.UtcNow
|
||||
};
|
||||
|
||||
return await _repository.AddAsync(entity);
|
||||
}
|
||||
public Task<EExchangeRateHistory?> GetByDateAsync(DateOnly date)
|
||||
{
|
||||
// Simplemente delega al repositorio
|
||||
return _repository.GetByDateAsync(date);
|
||||
}
|
||||
}
|
||||
|
||||
// Core/Services/Dto.cs
|
||||
|
||||
public class SeriesResponse
|
||||
{
|
||||
public int Status { get; set; }
|
||||
public Metadata Metadata { get; set; } = null!;
|
||||
public List<RateDay> Results { get; set; } = new();
|
||||
}
|
||||
|
||||
public class Metadata
|
||||
{
|
||||
public Resultset Resultset { get; set; } = null!;
|
||||
}
|
||||
|
||||
public class Resultset
|
||||
{
|
||||
public int Count { get; set; }
|
||||
public int Offset { get; set; }
|
||||
public int Limit { get; set; }
|
||||
}
|
||||
|
||||
public class RateDay
|
||||
{
|
||||
public DateTime Fecha { get; set; }
|
||||
[JsonPropertyName("detalle")]
|
||||
public List<RateDetail> Details { get; set; } = new();
|
||||
}
|
||||
|
||||
public class RateDetail
|
||||
{
|
||||
public string CodigoMoneda { get; set; } = null!;
|
||||
public decimal TipoCotizacion { get; set; }
|
||||
// otros campos opcionales: descripcion, tipoPase, etc.
|
||||
}
|
||||
36
Domain/Entities/EExchangeRateHistory.cs
Normal file
36
Domain/Entities/EExchangeRateHistory.cs
Normal file
@ -0,0 +1,36 @@
|
||||
namespace Domain.Entities
|
||||
{
|
||||
public class EExchangeRateHistory
|
||||
{
|
||||
/// <summary>
|
||||
/// Clave primaria autonumérica
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fecha de la cotización (por ejemplo, 2025-05-06)
|
||||
/// </summary>
|
||||
public DateOnly Ratedate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tasa de compra del dólar oficial
|
||||
/// </summary>
|
||||
public decimal Purchaserate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tasa de venta del dólar oficial
|
||||
/// </summary>
|
||||
public decimal Salerate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Origen del dato (por ejemplo, BCRA, Blue, MEP, etc.)
|
||||
/// </summary>
|
||||
public string Source { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Fecha y hora en que se guardó el registro
|
||||
/// </summary>
|
||||
public DateTime Createdat { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
10
Domain/Generics/CurrencyResponse.cs
Normal file
10
Domain/Generics/CurrencyResponse.cs
Normal file
@ -0,0 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Domain.Generics
|
||||
{
|
||||
public class CurrencyResponse
|
||||
{
|
||||
public string d { get; set; } // fecha
|
||||
public decimal v { get; set; } // valor
|
||||
}
|
||||
}
|
||||
11
Models/Interfaces/IPhOHExchangeRateHistory.cs
Normal file
11
Models/Interfaces/IPhOHExchangeRateHistory.cs
Normal file
@ -0,0 +1,11 @@
|
||||
using Domain.Entities;
|
||||
|
||||
namespace Models.Interfaces
|
||||
{
|
||||
public interface IPhOHExchangeRateHistory
|
||||
{
|
||||
Task<EExchangeRateHistory> AddAsync(EExchangeRateHistory entity);
|
||||
Task<EExchangeRateHistory?> GetByDateAsync(DateOnly date);
|
||||
|
||||
}
|
||||
}
|
||||
40
Models/Models/PhOhExchangeRateHistory.cs
Normal file
40
Models/Models/PhOhExchangeRateHistory.cs
Normal file
@ -0,0 +1,40 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Models.Models;
|
||||
|
||||
/// <summary>
|
||||
/// Histórico de cotizaciones diarias del dólar oficial del BCRA
|
||||
/// </summary>
|
||||
public partial class PhOhExchangeRateHistory
|
||||
{
|
||||
/// <summary>
|
||||
/// Clave primaria autonumérica
|
||||
/// </summary>
|
||||
public int Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Fecha de la cotización (por ejemplo, 2025-05-06)
|
||||
/// </summary>
|
||||
public DateOnly Ratedate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tasa de compra del dólar oficial
|
||||
/// </summary>
|
||||
public decimal Purchaserate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Tasa de venta del dólar oficial
|
||||
/// </summary>
|
||||
public decimal Salerate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Origen del dato (por ejemplo, BCRA, Blue, MEP, etc.)
|
||||
/// </summary>
|
||||
public string Source { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Fecha y hora en que se guardó el registro
|
||||
/// </summary>
|
||||
public DateTime Createdat { get; set; }
|
||||
}
|
||||
@ -19,6 +19,8 @@ public partial class PhronCareOperationsHubContext : DbContext
|
||||
|
||||
public virtual DbSet<PhOhArcataxType> PhOhArcataxTypes { get; set; }
|
||||
|
||||
public virtual DbSet<PhOhExchangeRateHistory> PhOhExchangeRateHistories { get; set; }
|
||||
|
||||
public virtual DbSet<PhOhTaxCondition> PhOhTaxConditions { get; set; }
|
||||
|
||||
public virtual DbSet<PhOhTicket> PhOhTickets { get; set; }
|
||||
@ -147,6 +149,40 @@ public partial class PhronCareOperationsHubContext : DbContext
|
||||
.HasColumnName("taxrate");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<PhOhExchangeRateHistory>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__PhOH_Exc__3213E83F4D9813B8");
|
||||
|
||||
entity.ToTable("PhOH_ExchangeRateHistory", tb => tb.HasComment("Histórico de cotizaciones diarias del dólar oficial del BCRA"));
|
||||
|
||||
entity.HasIndex(e => e.Ratedate, "UQ__PhOH_Exc__81B17E87D8FDABB7").IsUnique();
|
||||
|
||||
entity.Property(e => e.Id)
|
||||
.HasComment("Clave primaria autonumérica")
|
||||
.HasColumnName("id");
|
||||
entity.Property(e => e.Createdat)
|
||||
.HasDefaultValueSql("(sysutcdatetime())")
|
||||
.HasComment("Fecha y hora en que se guardó el registro")
|
||||
.HasColumnName("createdat");
|
||||
entity.Property(e => e.Purchaserate)
|
||||
.HasComment("Tasa de compra del dólar oficial")
|
||||
.HasColumnType("decimal(18, 6)")
|
||||
.HasColumnName("purchaserate");
|
||||
entity.Property(e => e.Ratedate)
|
||||
.HasComment("Fecha de la cotización (por ejemplo, 2025-05-06)")
|
||||
.HasColumnName("ratedate");
|
||||
entity.Property(e => e.Salerate)
|
||||
.HasComment("Tasa de venta del dólar oficial")
|
||||
.HasColumnType("decimal(18, 6)")
|
||||
.HasColumnName("salerate");
|
||||
entity.Property(e => e.Source)
|
||||
.HasMaxLength(100)
|
||||
.IsUnicode(false)
|
||||
.HasDefaultValue("BCRA")
|
||||
.HasComment("Origen del dato (por ejemplo, BCRA, Blue, MEP, etc.)")
|
||||
.HasColumnName("source");
|
||||
});
|
||||
|
||||
modelBuilder.Entity<PhOhTaxCondition>(entity =>
|
||||
{
|
||||
entity.HasKey(e => e.Id).HasName("PK__PhOH_Tax__3213E83F26F7EAEF");
|
||||
|
||||
42
Models/Repositories/PhOHExchangeRateHistory.cs
Normal file
42
Models/Repositories/PhOHExchangeRateHistory.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using Domain.Entities;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Models.Helpers;
|
||||
using Models.Interfaces;
|
||||
using Models.Models;
|
||||
|
||||
namespace Models.Repositories
|
||||
{
|
||||
public class PhOHExchangeRateHistory(PhronCareOperationsHubContext context) : IPhOHExchangeRateHistory
|
||||
{
|
||||
#region Declaraciones y Constructor
|
||||
private readonly PhronCareOperationsHubContext _context = context;
|
||||
#endregion
|
||||
|
||||
#region Metodos de clase
|
||||
public async Task<EExchangeRateHistory?> GetByDateAsync(DateOnly date)
|
||||
{
|
||||
var ph = await _context.PhOhExchangeRateHistories
|
||||
.AsNoTracking()
|
||||
.FirstOrDefaultAsync(x => x.Ratedate == date);
|
||||
|
||||
return ph is null
|
||||
? null
|
||||
: EntityMapper.MapEntity<PhOhExchangeRateHistory, EExchangeRateHistory>(ph);
|
||||
}
|
||||
public async Task<EExchangeRateHistory> AddAsync(EExchangeRateHistory entity)
|
||||
{
|
||||
// 1) Mapea tu modelo de dominio a la entidad EF
|
||||
var phEntity = EntityMapper.MapEntity<EExchangeRateHistory, PhOhExchangeRateHistory>(entity);
|
||||
|
||||
// 2) Agrégalo al contexto y guarda
|
||||
await _context.PhOhExchangeRateHistories.AddAsync(phEntity);
|
||||
await _context.SaveChangesAsync();
|
||||
|
||||
// 3) Mapea de vuelta y retorna el modelo de dominio con el Id generado
|
||||
return EntityMapper.MapEntity<PhOhExchangeRateHistory, EExchangeRateHistory>(phEntity);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
|
||||
using Core.Interfaces;
|
||||
using Domain.Entities;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
|
||||
|
||||
namespace phronCare.API.Controllers.Integrations
|
||||
{
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class ExchangeRateController : ControllerBase
|
||||
{
|
||||
private readonly IExchangeRateDom _exchangeRateDom;
|
||||
|
||||
public ExchangeRateController(IExchangeRateDom exchangeRateDom)
|
||||
{
|
||||
_exchangeRateDom = exchangeRateDom;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Devuelve la cotización oficial del dólar del día anterior,
|
||||
/// leyendo de histórico o consultando BCRA si hace falta.
|
||||
/// </summary>
|
||||
[HttpGet("yesterday")]
|
||||
public async Task<ActionResult<EExchangeRateHistory>> GetYesterdayAsync()
|
||||
{
|
||||
try
|
||||
{
|
||||
var rate = await _exchangeRateDom.GetYesterdayRateAsync();
|
||||
return Ok(rate);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Aquí puedes loggear el error o transformarlo en un código HTTP distinto
|
||||
return StatusCode(500, new { message = ex.Message });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtiene la cotización del dólar oficial para una fecha dada
|
||||
/// </summary>
|
||||
[HttpGet("{date:datetime}")]
|
||||
public async Task<ActionResult<EExchangeRateHistory>> GetByDateAsync(DateTime date)
|
||||
{
|
||||
var dateOnly = DateOnly.FromDateTime(date);
|
||||
var existing = await _exchangeRateDom.GetByDateAsync(dateOnly);
|
||||
if (existing is null)
|
||||
return NotFound(new { message = $"No hay cotización para {dateOnly:yyyy-MM-dd}" });
|
||||
return Ok(existing);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@ -18,6 +18,7 @@ using phronCare.API.Models.Security;
|
||||
using phronCare.API.Models;
|
||||
using Core.Interfaces;
|
||||
using Core.Services;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
@ -252,4 +253,14 @@ static void RepositorysAndServices(WebApplicationBuilder builder)
|
||||
builder.Services.AddScoped<ILookUpDom, LookupService>();
|
||||
builder.Services.AddScoped<IPhSLookUpRepository, PhSLookUpRepository>();
|
||||
|
||||
// 2) Repositorio de histórico de cotizaciones
|
||||
builder.Services.AddScoped<IPhOHExchangeRateHistory, PhOHExchangeRateHistory>();
|
||||
|
||||
// 3) Dominio/servicio con HttpClient para BCRA
|
||||
builder.Services.AddHttpClient<IExchangeRateDom, ExchangeRateDom>(client =>
|
||||
{
|
||||
|
||||
client.BaseAddress = new Uri("https://api.bcra.gob.ar/");
|
||||
});
|
||||
|
||||
}
|
||||
@ -29,5 +29,8 @@
|
||||
"ValidIssuer": "http://phroncare-bio-d7e9h0-api.saludlab.com.ar:9000",
|
||||
"ValidAudience": "http://phroncare-bio-d7e9h0-api.saludlab.com.ar:9000",
|
||||
"Secret": "8f96cb2c6eac839349f783369690eb368411359afbaa8de6c6c2b30927d2f9fe6222fc6911348eb88c235cf393cb808ce80b5498de31e37090ba06482eca93ecbf31b8e1d97209d9ae4ba01d4e285af64bc9758b70decfb385bf96e74f2b6c61d00cc80b8fbfd999d5902e2ca58f2f7a3ee574280d776ba61a5b1cbd0180689577b02fc8ec26297a501c4409f8529b338814f629a2b8fcba21dc0e15f408969dbc4b7f14b43a19b46a41bc288ddf207c16d50b11e1039ffd131c312ddf10df6fd65d8bc3f898a14294cd32366269bee53f84e94f45de80e8b5ddaa1a3b4aa288a7cb35eacaf9c2005d65237210c14843af022177be2f6e93764c3b4030b59f24"
|
||||
},
|
||||
"EstadisticasBcra": {
|
||||
"Token": "eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3NzgxOTk2ODcsInR5cGUiOiJleHRlcm5hbCIsInVzZXIiOiJzaXN0ZW1hc0BiaW9kZWMubmV0In0.fIU3xrBWa6_erILDpG1VUTX105vSaDe-pAw3mQCR13zX487-4dQ-zUEXTnFIZbl6iUVs0CGH_w1fkeUsmEwEwQ"
|
||||
}
|
||||
}
|
||||
@ -581,6 +581,52 @@
|
||||
],
|
||||
"ReturnTypes": []
|
||||
},
|
||||
{
|
||||
"ContainingType": "phronCare.API.Controllers.Integrations.ExchangeRateController",
|
||||
"Method": "GetByDateAsync",
|
||||
"RelativePath": "api/ExchangeRate/{date}",
|
||||
"HttpMethod": "GET",
|
||||
"IsController": true,
|
||||
"Order": 0,
|
||||
"Parameters": [
|
||||
{
|
||||
"Name": "date",
|
||||
"Type": "System.DateTime",
|
||||
"IsRequired": true
|
||||
}
|
||||
],
|
||||
"ReturnTypes": [
|
||||
{
|
||||
"Type": "Domain.Entities.EExchangeRateHistory",
|
||||
"MediaTypes": [
|
||||
"text/plain",
|
||||
"application/json",
|
||||
"text/json"
|
||||
],
|
||||
"StatusCode": 200
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ContainingType": "phronCare.API.Controllers.Integrations.ExchangeRateController",
|
||||
"Method": "GetYesterdayAsync",
|
||||
"RelativePath": "api/ExchangeRate/yesterday",
|
||||
"HttpMethod": "GET",
|
||||
"IsController": true,
|
||||
"Order": 0,
|
||||
"Parameters": [],
|
||||
"ReturnTypes": [
|
||||
{
|
||||
"Type": "Domain.Entities.EExchangeRateHistory",
|
||||
"MediaTypes": [
|
||||
"text/plain",
|
||||
"application/json",
|
||||
"text/json"
|
||||
],
|
||||
"StatusCode": 200
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"ContainingType": "phronCare.API.Controllers.Sales.InstitutionController",
|
||||
"Method": "GetById",
|
||||
|
||||
@ -2,15 +2,29 @@
|
||||
@using System.Globalization;
|
||||
@using System.Net.Http.Json
|
||||
@using Blazored.Typeahead
|
||||
@using Core.Interfaces
|
||||
@using Services.Lookups
|
||||
@using phronCare.UIBlazor.Pages.Sales.Modals
|
||||
@using phronCare.UIBlazor.Services.Sales.Quotes
|
||||
|
||||
@inject ISalesLookupService SalesLookupService
|
||||
@inject IQuoteService QuoteService
|
||||
@inject IToastService toastService
|
||||
@inject NavigationManager Navigation
|
||||
@inject IModalService Modal
|
||||
@inject IExchangeRateDom ExchangeRateService
|
||||
|
||||
@* @if (YesterdayRate == null)
|
||||
{
|
||||
<p>Cargando tipo de cambio…</p>
|
||||
}
|
||||
else
|
||||
{
|
||||
<div class="mb-3">
|
||||
<strong>Tipo de Cambio (ayer @YesterdayRate.Ratedate: d):</strong>
|
||||
@YesterdayRate.Salerate (@YesterdayRate.Source)
|
||||
</div>
|
||||
} *@
|
||||
<EditForm Model="_quoteModel" >
|
||||
<div class="container mt-4" style="zoom:0.8;">
|
||||
<div class="card">
|
||||
@ -122,7 +136,7 @@
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Tipo de cambio</label>
|
||||
<InputNumber class="form-control" @bind-Value="_quoteModel.Exchangerate" />
|
||||
<InputNumber class="form-control" @bind-Value="_quoteModel.Exchangerate"/>
|
||||
</div>
|
||||
<div class="col-md-4 d-flex align-items-end">
|
||||
<div class="form-check form-switch">
|
||||
@ -320,7 +334,7 @@
|
||||
private decimal _netAmount = 0;
|
||||
private decimal _taxAmount = 0;
|
||||
private decimal _grandTotal = 0;
|
||||
|
||||
private EExchangeRateHistory? YesterdayRate;
|
||||
private Task OnValueChanged<T>(EQuoteDetail item, T value, Action<EQuoteDetail, T> setter)
|
||||
{
|
||||
setter(item, value);
|
||||
@ -330,6 +344,22 @@
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// 1. Levantamos la cotización de ayer
|
||||
try
|
||||
{
|
||||
YesterdayRate = await ExchangeRateService.GetYesterdayRateAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// manejar error (toast, log, etc.)
|
||||
Console.Error.WriteLine(ex.Message);
|
||||
}
|
||||
|
||||
// 2. Asignamos al modelo si aún no tiene valor
|
||||
if (YesterdayRate != null && _quoteModel.Exchangerate == 0)
|
||||
{
|
||||
_quoteModel.Exchangerate = YesterdayRate.Salerate;
|
||||
}
|
||||
_businessUnits = (await SalesLookupService.SearchBussinessUnitsAsync(string.Empty)).ToList();
|
||||
}
|
||||
private async Task AddNewProduct()
|
||||
|
||||
@ -11,6 +11,8 @@ using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
|
||||
using Blazored.Modal;
|
||||
using Blazored.Toast;
|
||||
using phronCare.UIBlazor.Services.Sales.Quotes;
|
||||
using Core.Interfaces;
|
||||
using phronCare.UIBlazor.Services.Integrations;
|
||||
|
||||
var builder = WebAssemblyHostBuilder.CreateDefault(args);
|
||||
builder.RootComponents.Add<App>("#app");
|
||||
@ -54,6 +56,7 @@ static void InjectDependencies(WebAssemblyHostBuilder builder)
|
||||
{
|
||||
builder.Services.AddScoped<ISalesLookupService, SalesLookupService>();
|
||||
builder.Services.AddScoped<IQuoteService,QuoteService>();
|
||||
builder.Services.AddScoped<IExchangeRateDom, ExchangeRateService>();
|
||||
|
||||
builder.Services.AddScoped<TicketsService>();
|
||||
builder.Services.AddScoped<CustomerService>();
|
||||
|
||||
@ -0,0 +1,40 @@
|
||||
using Core.Interfaces;
|
||||
using Domain.Entities;
|
||||
using System.Net.Http.Json;
|
||||
|
||||
namespace phronCare.UIBlazor.Services.Integrations
|
||||
{
|
||||
public class ExchangeRateService : IExchangeRateDom
|
||||
|
||||
{
|
||||
private readonly HttpClient _http;
|
||||
|
||||
public ExchangeRateService(HttpClient http)
|
||||
{
|
||||
_http = http;
|
||||
}
|
||||
|
||||
public async Task<EExchangeRateHistory> GetYesterdayRateAsync()
|
||||
{
|
||||
// Ajustá la URL si tu API está en un path o puerto distinto
|
||||
var dto = await _http.GetFromJsonAsync<EExchangeRateHistory>("api/ExchangeRate/yesterday");
|
||||
if (dto == null)
|
||||
throw new InvalidOperationException("No se obtuvo la cotización de ayer.");
|
||||
return dto;
|
||||
}
|
||||
|
||||
public async Task<EExchangeRateHistory?> GetByDateAsync(DateOnly date)
|
||||
{
|
||||
// Formateamos la fecha para la URL: 2025-05-07
|
||||
var dateString = date.ToString("yyyy-MM-dd");
|
||||
|
||||
// Llamamos a GET /api/ExchangeRate/{date}
|
||||
var dto = await _http
|
||||
.GetFromJsonAsync<EExchangeRateHistory>($"api/ExchangeRate/{dateString}");
|
||||
|
||||
if (dto == null)
|
||||
throw new InvalidOperationException($"No se obtuvo la cotización para la fecha {dateString}.");
|
||||
return dto;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,81 @@
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\phronCare.UIBlazor\\phronCare.UIBlazor.csproj": {}
|
||||
},
|
||||
"projects": {
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Core\\Core.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Core\\Core.csproj",
|
||||
"projectName": "Core",
|
||||
"projectPath": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Core\\Core.csproj",
|
||||
"packagesPath": "C:\\Users\\maski\\.nuget\\packages\\",
|
||||
"outputPath": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Core\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\maski\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net8.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net8.0": {
|
||||
"targetAlias": "net8.0",
|
||||
"projectReferences": {
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Domain\\Domain.csproj": {
|
||||
"projectPath": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Domain\\Domain.csproj"
|
||||
},
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Models\\Models.csproj": {
|
||||
"projectPath": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Models\\Models.csproj"
|
||||
},
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Transversal\\Transversal.csproj": {
|
||||
"projectPath": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Transversal\\Transversal.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "direct"
|
||||
},
|
||||
"SdkAnalysisLevel": "9.0.200"
|
||||
},
|
||||
"frameworks": {
|
||||
"net8.0": {
|
||||
"targetAlias": "net8.0",
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.201/PortableRuntimeIdentifierGraph.json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Domain\\Domain.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
@ -69,6 +144,87 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Models\\Models.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
"projectUniqueName": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Models\\Models.csproj",
|
||||
"projectName": "Models",
|
||||
"projectPath": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Models\\Models.csproj",
|
||||
"packagesPath": "C:\\Users\\maski\\.nuget\\packages\\",
|
||||
"outputPath": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Models\\obj\\",
|
||||
"projectStyle": "PackageReference",
|
||||
"fallbackFolders": [
|
||||
"C:\\Program Files (x86)\\Microsoft Visual Studio\\Shared\\NuGetPackages"
|
||||
],
|
||||
"configFilePaths": [
|
||||
"C:\\Users\\maski\\AppData\\Roaming\\NuGet\\NuGet.Config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.FallbackLocation.config",
|
||||
"C:\\Program Files (x86)\\NuGet\\Config\\Microsoft.VisualStudio.Offline.config"
|
||||
],
|
||||
"originalTargetFrameworks": [
|
||||
"net8.0"
|
||||
],
|
||||
"sources": {
|
||||
"C:\\Program Files (x86)\\Microsoft SDKs\\NuGetPackages\\": {},
|
||||
"https://api.nuget.org/v3/index.json": {}
|
||||
},
|
||||
"frameworks": {
|
||||
"net8.0": {
|
||||
"targetAlias": "net8.0",
|
||||
"projectReferences": {
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Domain\\Domain.csproj": {
|
||||
"projectPath": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Domain\\Domain.csproj"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"warningProperties": {
|
||||
"warnAsError": [
|
||||
"NU1605"
|
||||
]
|
||||
},
|
||||
"restoreAuditProperties": {
|
||||
"enableAudit": "true",
|
||||
"auditLevel": "low",
|
||||
"auditMode": "direct"
|
||||
},
|
||||
"SdkAnalysisLevel": "9.0.200"
|
||||
},
|
||||
"frameworks": {
|
||||
"net8.0": {
|
||||
"targetAlias": "net8.0",
|
||||
"dependencies": {
|
||||
"Microsoft.EntityFrameworkCore.Design": {
|
||||
"include": "Runtime, Build, Native, ContentFiles, Analyzers, BuildTransitive",
|
||||
"suppressParent": "All",
|
||||
"target": "Package",
|
||||
"version": "[8.0.10, )"
|
||||
},
|
||||
"Microsoft.EntityFrameworkCore.SqlServer": {
|
||||
"target": "Package",
|
||||
"version": "[8.0.10, )"
|
||||
}
|
||||
},
|
||||
"imports": [
|
||||
"net461",
|
||||
"net462",
|
||||
"net47",
|
||||
"net471",
|
||||
"net472",
|
||||
"net48",
|
||||
"net481"
|
||||
],
|
||||
"assetTargetFallback": true,
|
||||
"warn": true,
|
||||
"frameworkReferences": {
|
||||
"Microsoft.NETCore.App": {
|
||||
"privateAssets": "all"
|
||||
}
|
||||
},
|
||||
"runtimeIdentifierGraphPath": "C:\\Program Files\\dotnet\\sdk\\9.0.201/PortableRuntimeIdentifierGraph.json"
|
||||
}
|
||||
}
|
||||
},
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\phronCare.UIBlazor\\phronCare.UIBlazor.csproj": {
|
||||
"version": "1.0.0",
|
||||
"restore": {
|
||||
@ -97,6 +253,9 @@
|
||||
"net8.0": {
|
||||
"targetAlias": "net8.0",
|
||||
"projectReferences": {
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Core\\Core.csproj": {
|
||||
"projectPath": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Core\\Core.csproj"
|
||||
},
|
||||
"C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Domain\\Domain.csproj": {
|
||||
"projectPath": "C:\\Users\\maski\\source\\repos\\SaludLAB\\phronCare\\Domain\\Domain.csproj"
|
||||
},
|
||||
|
||||
@ -14,6 +14,7 @@
|
||||
<SourceRoot Include="C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages\" />
|
||||
</ItemGroup>
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.entityframeworkcore\8.0.10\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props" Condition="Exists('$(NuGetPackageRoot)microsoft.entityframeworkcore\8.0.10\buildTransitive\net8.0\Microsoft.EntityFrameworkCore.props')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.net.sdk.webassembly.pack\9.0.3\build\Microsoft.NET.Sdk.WebAssembly.Pack.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.sdk.webassembly.pack\9.0.3\build\Microsoft.NET.Sdk.WebAssembly.Pack.props')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.net.illink.tasks\8.0.14\build\Microsoft.NET.ILLink.Tasks.props" Condition="Exists('$(NuGetPackageRoot)microsoft.net.illink.tasks\8.0.14\build\Microsoft.NET.ILLink.Tasks.props')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.aspnetcore.components.webassembly\8.0.6\build\net8.0\Microsoft.AspNetCore.Components.WebAssembly.props" Condition="Exists('$(NuGetPackageRoot)microsoft.aspnetcore.components.webassembly\8.0.6\build\net8.0\Microsoft.AspNetCore.Components.WebAssembly.props')" />
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8" standalone="no"?>
|
||||
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ImportGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.net.sdk.webassembly.pack\9.0.3\build\Microsoft.NET.Sdk.WebAssembly.Pack.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.sdk.webassembly.pack\9.0.3\build\Microsoft.NET.Sdk.WebAssembly.Pack.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.extensions.options\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Options.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.options\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Options.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\8.0.1\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.logging.abstractions\8.0.2\buildTransitive\net6.0\Microsoft.Extensions.Logging.Abstractions.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.net.sdk.webassembly.pack\9.0.3\build\Microsoft.NET.Sdk.WebAssembly.Pack.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.net.sdk.webassembly.pack\9.0.3\build\Microsoft.NET.Sdk.WebAssembly.Pack.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.extensions.configuration.binder\8.0.1\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.extensions.configuration.binder\8.0.1\buildTransitive\netstandard2.0\Microsoft.Extensions.Configuration.Binder.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.aspnetcore.components.webassembly.devserver\8.0.6\build\Microsoft.AspNetCore.Components.WebAssembly.DevServer.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.aspnetcore.components.webassembly.devserver\8.0.6\build\Microsoft.AspNetCore.Components.WebAssembly.DevServer.targets')" />
|
||||
<Import Project="$(NuGetPackageRoot)microsoft.aspnetcore.components.analyzers\8.0.6\buildTransitive\netstandard2.0\Microsoft.AspNetCore.Components.Analyzers.targets" Condition="Exists('$(NuGetPackageRoot)microsoft.aspnetcore.components.analyzers\8.0.6\buildTransitive\netstandard2.0\Microsoft.AspNetCore.Components.Analyzers.targets')" />
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -23,6 +23,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Core\Core.csproj" />
|
||||
<ProjectReference Include="..\Domain\Domain.csproj" />
|
||||
<ProjectReference Include="..\Transversal\Transversal.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user