@page "/quote/create" @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

Emisión de Presupuesto

@customer.Nombre @customer.Nombre
@item.Nombre @item.Nombre
@item.Nombre @item.Nombre
@item.Nombre @item.Nombre
@item.Nombre @item.Nombre
@foreach (var unidad in _businessUnits) { }

Productos Cotizados
@if (_quoteModel.PhSQuoteDetails.Any()) { foreach (var item in _quoteModel.PhSQuoteDetails) { } } else { }
Producto Descripción Cantidad Precio Unitario Total
@item.ProductId $ @($"{item.Quantity * item.Unitprice:0.00}")
No hay productos agregados.
@if (_quoteModel.PhSQuoteAdjustments.Any()) {
@foreach (var adj in _quoteModel.PhSQuoteAdjustments) { @adj.ReasonCode }
} else {

Sin ajustes.

}
@if (_quoteModel.PhSQuoteTaxes.Any()) {
@foreach (var tax in _quoteModel.PhSQuoteTaxes) { }
Nombre % Importe
@tax.Taxname @tax.Taxrate.ToString("0.##")% $@tax.Taxamount.ToString("N2")
} else {

No hay impuestos aplicados

}
  • Subtotal $ @_netAmount.ToString("N2")
  • Taxes $ @_taxAmount.ToString("N2")
  • Total $ @_grandTotal.ToString("N2")
@code { private EQuoteHeader _quoteModel = new(); private ELookUpItem? _selectedCustomer; private ELookUpItem? _selectedProfessional; private ELookUpItem? _selectedInstitution; private ELookUpItem? _selectedPatient; private ELookUpItem? _selectedPerson; private List _businessUnits = new(); private decimal _netAmount = 0; private decimal _taxAmount = 0; private decimal _grandTotal = 0; private EExchangeRateHistory? YesterdayRate; private Task OnValueChanged(EQuoteDetail item, T value, Action setter) { setter(item, value); RecalculateTotals(); return Task.CompletedTask; } 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() { var options = new ModalOptions() { Size = ModalSize.Large, HideHeader = true }; var modal = Modal.Show("", options); var result = await modal.Result; if (!result.Cancelled && result.Data is EProductLookupItem selected) { var newDetail = new EQuoteDetail { ProductId = selected.Id, ProductDescription = selected.Description, Quantity = 1, Unitprice = selected.UnitPrice, Approved = false, Createdat = DateTime.Now }; _quoteModel.PhSQuoteDetails.Add(newDetail); } } private async Task AddNewProfessional() { var options = new ModalOptions() { Size = ModalSize.Large, HideHeader = true }; var modal = Modal.Show(options); var result = await modal.Result; if (!result.Cancelled && result.Data is ELookUpItem nuevo) { _selectedProfessional = nuevo; // No hay ProfessionalId en el modelo base, pero si lo usás, actualizalo aquí. // _quoteModel.ProfessionalId = nuevo.Id; } } private Task OnCustomerSelected(ELookUpItem item) => SetLookupSelection(item, sel => _selectedCustomer = sel, id => _quoteModel.CustomerId = id); private Task OnPersonSelected(ELookUpItem item) => SetLookupSelection(item, sel => _selectedPerson = sel, id => _quoteModel.PeopleId = id); // private Task OnProfessionalSelected(ELookUpItem item) // => SetLookupSelection(item, sel => _selectedProfessional = sel); // private Task OnInstitutionSelected(ELookUpItem item) // => SetLookupSelection(item, sel => _selectedInstitution = sel); // private Task OnPatientSelected(ELookUpItem item) // => SetLookupSelection(item, sel => _selectedPatient = sel); private Task SetLookupSelection(ELookUpItem? item, Action setSelected, Action? setModelId = null) { setSelected(item); if (item != null && setModelId != null) setModelId(item.Id); return Task.CompletedTask; } private void OnDetailChanged(EQuoteDetail item) { } private void RemoveDetail(EQuoteDetail item) => _quoteModel.PhSQuoteDetails.Remove(item); private void RecalculateTotals() { _netAmount = _quoteModel.PhSQuoteDetails.Sum(d => d.Quantity * d.Unitprice); _taxAmount = _quoteModel.PhSQuoteTaxes.Sum(t => t.Taxamount); _grandTotal = _netAmount + _taxAmount; _quoteModel.Netamount = _netAmount; _quoteModel.Total = _grandTotal; } private async Task OpenAdjustmentModal() { var modal = Modal.Show("Agregar Ajuste", new ModalOptions { HideHeader = true }); var result = await modal.Result; if (!result.Cancelled && result.Data is QuoteAdjustmentQuickAddModal.QuoteAdjustmentDto dto) { _quoteModel.PhSQuoteAdjustments.Add(new EQuoteAdjustment { ReasonCode = dto.ReasonCode, Amount = dto.Amount }); } } private void RemoveAdjustment(EQuoteAdjustment adj) { _quoteModel.PhSQuoteAdjustments.Remove(adj); } private async Task AddNewTax() { var parameters = new ModalParameters(); parameters.Add(nameof(QuoteTaxQuickAddModal.NetAmount), _netAmount); var options = new ModalOptions { HideHeader = true, Size = ModalSize.Small }; var modal = Modal.Show("", parameters, options); var result = await modal.Result; if (!result.Cancelled && result.Data is EQuoteTax newTax) { _quoteModel.PhSQuoteTaxes.Add(newTax); RecalculateTotals(); } } private void RemoveTax(EQuoteTax tax) { _quoteModel.PhSQuoteTaxes.Remove(tax); RecalculateTotals(); } private async Task HandleValidSubmit() { // Si necesitas validar algo extra antes de llamar al servicio, hazlo aquí int selectedSeriesId = 1/* obtenlo de donde corresponda, p.ej. de un dropdown */; var result = await QuoteService.CreateFullQuoteAsync(_quoteModel, selectedSeriesId); if (!result.Success) { toastService.ShowError(result.ErrorMessage); return; } toastService.ShowSuccess($"Presupuesto creado: {result.QuoteNumber}"); //Navigation.NavigateTo($"/sales/quotes/details/{result.QuoteNumber}"); } /// /// Agrega o actualiza un rol dentro de _quoteModel.PhSQuoteRoles /// private void AddOrUpdateRole(string entityType, int entityId, string roleName) { var existing = _quoteModel.PhSQuoteRoles .FirstOrDefault(r => r.Entitytype == entityType); if (existing != null) { existing.EntityId = entityId; existing.Role = roleName; } else { _quoteModel.PhSQuoteRoles.Add(new EQuoteRole { // QuoteheaderId lo llenará EF en el servidor Entitytype = entityType, EntityId = entityId, Role = roleName }); } } private Task OnProfessionalSelected(ELookUpItem item) { _selectedProfessional = item; AddOrUpdateRole("PhS_Professionals", item.Id, "Medico"); return Task.CompletedTask; } private Task OnInstitutionSelected(ELookUpItem item) { _selectedInstitution = item; AddOrUpdateRole("PhS_Institutions", item.Id, "Hospital"); return Task.CompletedTask; } private Task OnPatientSelected(ELookUpItem item) { _selectedPatient = item; AddOrUpdateRole("PhS_Patients", item.Id, "Paciente"); return Task.CompletedTask; } }