All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 7m16s
228 lines
8.6 KiB
Plaintext
228 lines
8.6 KiB
Plaintext
@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 QuoteService quoteService
|
|
@inject NavigationManager nav
|
|
@inject IToastService toast
|
|
@inject IModalService Modal
|
|
|
|
<div class="card" style="zoom: 80%">
|
|
<div class="card-header d-flex justify-content-center align-items-center">
|
|
<h3 class="card-title m-0">
|
|
<i class="fas fa-file-signature text-secondary me-2"></i> Autorización de Presupuesto
|
|
</h3>
|
|
</div>
|
|
<div class="card-body">
|
|
@if (IsLoading)
|
|
{
|
|
<p>Cargando información del presupuesto...</p>
|
|
}
|
|
else if (LoadError)
|
|
{
|
|
<div class="alert alert-danger">
|
|
Ocurrió un error al intentar cargar el presupuesto.
|
|
</div>
|
|
}
|
|
else
|
|
{
|
|
<div class="mb-4">
|
|
<div class="row">
|
|
<div class="col"><strong>N°:</strong> @QuoteHeader.Quotenumber</div>
|
|
<div class="col"><strong>Fecha:</strong> @QuoteHeader.IssueDate.ToShortDateString()</div>
|
|
<div class="col"><strong>Cliente:</strong> @QuoteHeader.CustomerName</div>
|
|
</div>
|
|
<div class="row mt-1">
|
|
<div class="col"><strong>Médico:</strong> @QuoteHeader.ProfessionalName</div>
|
|
<div class="col"><strong>Hospital:</strong> @QuoteHeader.InstitutionName</div>
|
|
<div class="col"><strong>Paciente:</strong> @QuoteHeader.PatientName</div>
|
|
</div>
|
|
<div class="row mt-1">
|
|
<div class="col"><strong>Cirugía estimada:</strong> @QuoteHeader.EstimatedDate?.ToShortDateString()</div>
|
|
<div class="col"><strong>Importe total:</strong> @QuoteHeader.Total.ToString("C")</div>
|
|
<div class="col">
|
|
<strong>Estado:</strong>
|
|
<span class="badge @GetStatusColor(QuoteHeader.Status)">
|
|
@QuoteHeader.Status
|
|
</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<EditForm Model="FormModel" OnValidSubmit="OpenConfirmation">
|
|
<div class="text-end mb-2">
|
|
@if (FormModel.Items.Any(i => i.Approved))
|
|
{
|
|
<span class="badge bg-success px-3 py-2"><i class="fas fa-check-circle me-1"></i> Al menos un ítem será autorizado</span>
|
|
}
|
|
else
|
|
{
|
|
<span class="badge bg-danger px-3 py-2"><i class="fas fa-ban me-1"></i> Todos los ítems serán anulados</span>
|
|
}
|
|
</div>
|
|
<table class="table table-sm table-bordered">
|
|
<thead class="table-light text-center">
|
|
<tr>
|
|
<th style="width: 40px;">¿Aprobar?</th>
|
|
<th style="width: 60%;">Descripción</th>
|
|
<th>Cant.</th>
|
|
<th>Precio U.</th>
|
|
<th>Subtotal</th>
|
|
<th>Cant. Aprob.</th>
|
|
<th>Precio Aprob.</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
@foreach (var item in FormModel.Items)
|
|
{
|
|
<tr>
|
|
<td class="text-center">
|
|
<input type="checkbox" class="form-check-input"
|
|
@bind="item.Approved" />
|
|
</td>
|
|
<td>@item.ProductDescription</td>
|
|
<td class="text-center">@item.Quantity</td>
|
|
<td class="text-end">@item.UnitPrice.ToString("N2")</td>
|
|
<td class="text-end">@item.Subtotal.ToString("N2")</td>
|
|
<td class="text-center">
|
|
<InputNumber @bind-Value="item.ApprovedQuantity"
|
|
class="form-control form-control-sm text-center"
|
|
disabled="@(item.Approved == false)" />
|
|
</td>
|
|
<td class="text-end">
|
|
<InputNumber @bind-Value="item.ApprovedUnitPrice"
|
|
class="form-control form-control-sm text-end"
|
|
disabled="@(item.Approved == false)" />
|
|
</td>
|
|
</tr>
|
|
}
|
|
</tbody>
|
|
</table>
|
|
<div class="d-flex justify-content-end mt-3">
|
|
<button type="submit" class="btn text-white me-2 @(FormModel.Items.Any(i => i.Approved) ? "btn-success" : "btn-danger")">
|
|
@(FormModel.Items.Any(i => i.Approved) ? "Confirmar Autorización" : "Confirmar Anulación")
|
|
</button>
|
|
<button type="button" class="btn btn-secondary" @onclick="Cancel">Cancelar
|
|
</button>
|
|
</div>
|
|
</EditForm>
|
|
}
|
|
</div>
|
|
</div>
|
|
|
|
@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<Shared.Modals.ConfirmModal>("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)
|
|
.Select(i => new QuoteAuthorizationDto
|
|
{
|
|
Id = i.Id,
|
|
Approved = true,
|
|
ApprovedQuantity = i.ApprovedQuantity,
|
|
ApprovedUnitPrice = i.ApprovedUnitPrice
|
|
})
|
|
.ToList();
|
|
|
|
var payload = new QuoteAuthorizationRequest
|
|
{
|
|
QuoteId = QuoteId,
|
|
Items = approvedItems
|
|
};
|
|
|
|
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.");
|
|
}
|
|
}
|
|
|
|
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<QuoteAuthorizationViewItem> Items { get; set; } = new();
|
|
}
|
|
}
|