@page "/quotes/authorize/{QuoteId:int}" @using Domain.Dtos @using phronCare.UIBlazor.Models.Sales @using phronCare.UIBlazor.Services.Sales.Quotes @using Blazored.Modal @using Blazored.Modal.Services @inject NavigationManager nav @inject IQuoteService quoteService @inject IToastService toast @inject IModalService Modal

Autorización de Presupuesto

@if (IsLoading) {

Cargando información del presupuesto...

} else if (LoadError) {
Ocurrió un error al intentar cargar el presupuesto.
} else {
N°: @QuoteHeader.Quotenumber
Fecha: @QuoteHeader.IssueDate.ToShortDateString()
Cliente: @QuoteHeader.CustomerName
Médico: @QuoteHeader.ProfessionalName
Hospital: @QuoteHeader.InstitutionName
Paciente: @QuoteHeader.PatientName
Cirugía estimada: @QuoteHeader.EstimatedDate?.ToShortDateString()
Importe total: @QuoteHeader.Total.ToString("C")
Estado: @QuoteHeader.Status
@if (FormModel.Items.Any(i => i.Approved)) { Al menos un ítem será autorizado } else { Todos los ítems serán anulados }
@foreach (var item in FormModel.Items) { }
¿Aprobar? Descripción Cant. Precio U. Subtotal Cant. Aprob. Precio Aprob.
@item.ProductDescription @item.Quantity @item.UnitPrice.ToString("N2") @item.Subtotal.ToString("N2")
}
@code { [Parameter] public int QuoteId { get; set; } private QuoteDto? QuoteHeader; private QuoteAuthorizationFormModel FormModel = new(); private bool IsLoading = true; private bool LoadError = false; protected override async Task OnInitializedAsync() { try { var quote = await quoteService.GetDtoByIdAsync(QuoteId); if (quote?.Items == null || !quote.Items.Any()) { LoadError = true; return; } QuoteHeader = quote; FormModel.Items = quote.Items.Select(x => new QuoteAuthorizationViewItem { Id = x.Id, ProductDescription = x.Description, Quantity = x.Quantity, UnitPrice = x.UnitPrice, Approved = false, ApprovedQuantity = null, ApprovedUnitPrice = null }).ToList(); } catch { LoadError = true; } finally { IsLoading = false; } } private async Task OpenConfirmation() { var options = new ModalOptions() { HideHeader = true }; var parameters = new ModalParameters(); parameters.Add("Message", "¿Desea continuar con esta operación?"); var modal = Modal.Show("Confirmación", parameters,options); var result = await modal.Result; if (!result.Cancelled) { await AuthorizeQuote(); } } private async Task AuthorizeQuote() { var approvedItems = FormModel.Items .Where(i => i.Approved) .ToList(); // Validación: todos los ítems aprobados deben tener cantidad y precio válidos var invalidItems = approvedItems .Where(i => !i.ApprovedQuantity.HasValue || i.ApprovedQuantity <= 0 || !i.ApprovedUnitPrice.HasValue || i.ApprovedUnitPrice <= 0) .ToList(); if (invalidItems.Any()) { toast.ShowError("Hay ítems aprobados sin cantidad o precio válido."); return; } var payload = new QuoteAuthorizationRequest { QuoteId = QuoteId, Items = approvedItems.Select(i => new QuoteAuthorizationDto { Id = i.Id, Approved = true, ApprovedQuantity = i.ApprovedQuantity, ApprovedUnitPrice = i.ApprovedUnitPrice }).ToList() }; try { var success = await quoteService.AuthorizeQuoteAsync(payload); if (success) { if (!approvedItems.Any()) toast.ShowInfo("Presupuesto anulado correctamente."); else toast.ShowSuccess("Presupuesto autorizado con éxito."); nav.NavigateTo("/quotes"); } else { toast.ShowError("No se pudo procesar el presupuesto."); } } catch (Exception ex) { toast.ShowError($"Error inesperado: {ex.Message}"); } } private void Cancel() => nav.NavigateTo("/quotes"); private string GetStatusColor(string status) => status.ToLower() switch { "Anulado" => "bg-danger text-white", "Emitido" => "bg-primary text-white", "Aprobado" => "bg-success", "Despacho" => "bg-info text-white", "SinConsumo" => "bg-warning text-dark", "Transito" => "bg-secondary text-white", "Cerrado" => "bg-dark text-white", _ => "bg-light text-dark" }; public class QuoteAuthorizationFormModel { public List Items { get; set; } = new(); } }