@page "/salesdocuments/{Id:int}/review" @using Domain.Constants @using Domain.Dtos.Sales @using phronCare.UIBlazor.Services.Sales.SalesDocuments @inject NavigationManager Navigation @inject ISalesDocumentService SalesDocumentService @inject IToastService toastService

Revision administrativa

Sales Document Draft Review & Validation
@if (IsLoading) {
Cargando...
} else if (Document is null) {
No se pudo cargar el Sales Document.
} else {
@if (IsDraft) { Este documento esta en Draft y puede revisarse visualmente. Guardar y validar requieren los endpoints de backend fuera del alcance UI-only. } else { Este documento no esta en Draft. La revision queda en modo solo lectura. }
Cabecera del documento
@GetStatusLabel(Document.Status)
@DocumentNumber
@GetDocumentTypeLabel(Document.DocumentType)
@FormatDate(Document.IssueDate)
@Document.Currency
@Document.CustomerName
@Document.BillToCustomerName
@(Document.QuoteId?.ToString() ?? "-")
@FormatDate(Document.PeriodFrom)
@FormatDate(Document.PeriodTo)
@Document.ExchangeRate.ToString("N4")
Remitos origen
@if (OriginDeliveryNotes.Any()) {
@foreach (var item in OriginDeliveryNotes) {
@item.DeliveryNoteNumber Remito ID @item.Id @FormatDate(item.IssueDate)
}
} else {
No se detectaron remitos origen en el snapshot del documento.
}
Items
@if (Document.Details.Any()) { @foreach (var item in Document.Details.OrderBy(x => x.LineNumber)) { } } else { }
# Origen Descripcion Cantidad Unitario Neto Impuesto Total
@item.LineNumber @GetOriginTypeLabel(item.OriginType) @item.Description @item.Quantity.ToString("N2") @item.UnitPrice.ToString("N2") @item.NetAmount.ToString("N2") @item.TaxAmount.ToString("N2") @item.TotalAmount.ToString("N2")
Sin items.
Coverage
@if (Document.Coverage.Any()) { @foreach (var coverage in Document.Coverage) { } } else { }
Tipo Presupuesto Quote Detail Porcentaje Importe Desde Hasta Notas
@GetCoverageTypeLabel(coverage.CoverageType) @coverage.QuoteId @(coverage.QuoteDetailId?.ToString() ?? "-") @(coverage.CoveragePercentage?.ToString("N2") ?? "-") @(coverage.CoverageAmount?.ToString("N2") ?? "-") @FormatDate(coverage.PeriodFrom) @FormatDate(coverage.PeriodTo) @(string.IsNullOrWhiteSpace(coverage.Notes) ? "-" : coverage.Notes)
Sin coverage informado.
Validacion del Draft
    @foreach (var item in ValidationItems) {
  • @item.Message
  • }
Importes
Neto @Document.NetAmount.ToString("N2")
Impuestos @Document.TaxAmount.ToString("N2")
Total @Document.Currency @Document.TotalAmount.ToString("N2")
Acciones
Guardar revision persiste los campos editables del Draft. Validar cambia el estado a Validated.
}
@code { [Parameter] public int Id { get; set; } private SalesDocumentDto? Document; private bool IsLoading; private bool IsSaving; private string? ReviewObservations; private List OriginDeliveryNotes = new(); private SalesDocumentDraftValidationDto DraftValidation = new(); private bool IsDraft => Document?.Status == (int)SalesDocumentStatus.Draft; private bool CanValidate => IsDraft && ValidationItems.All(x => x.IsValid); private string DocumentNumber => string.IsNullOrWhiteSpace(Document?.InternalDocumentNumber) ? $"#{Document?.Id}" : Document.InternalDocumentNumber; private List ValidationItems => [ new(DraftValidation.HasDetails, "Tiene detalles"), new(DraftValidation.HasValidAmounts, "Tiene importes validos"), new(DraftValidation.HasCustomer, "Posee cliente asignado"), new(DraftValidation.IsDraft, "Permanece en estado Draft") ]; protected override async Task OnInitializedAsync() { await LoadAsync(); } private async Task LoadAsync() { try { IsLoading = true; var preview = await SalesDocumentService.GetDraftPreviewAsync(Id); ApplyPreview(preview); } catch (Exception ex) { toastService.ShowError(ex.Message); } finally { IsLoading = false; } } private async Task SaveReviewAsync() { if (Document is null) return; try { IsSaving = true; var preview = await SalesDocumentService.UpdateDraftReviewAsync(Id, new SalesDocumentDraftReviewDto { IssueDate = Document.IssueDate, AssociatedDocumentType = Document.AssociatedDocumentType, AssociatedDocumentNumber = Document.AssociatedDocumentNumber, AssociatedDocumentDate = Document.AssociatedDocumentDate, Observations = ReviewObservations, PeriodFrom = Document.PeriodFrom, PeriodTo = Document.PeriodTo }); ApplyPreview(preview); toastService.ShowSuccess("Revision guardada correctamente."); } catch (Exception ex) { toastService.ShowError(ex.Message); } finally { IsSaving = false; } } private async Task ValidateDraftAsync() { try { IsSaving = true; var preview = await SalesDocumentService.ValidateDraftAsync(Id); ApplyPreview(preview); toastService.ShowSuccess("Sales Document validado correctamente."); } catch (Exception ex) { toastService.ShowError(ex.Message); } finally { IsSaving = false; } } private void BackToList() => Navigation.NavigateTo("/salesdocuments"); private void ViewDetail() => Navigation.NavigateTo($"/salesdocuments/{Id}"); private void ApplyPreview(SalesDocumentDraftPreviewDto? preview) { Document = preview?.Document; ReviewObservations = Document?.Observations; OriginDeliveryNotes = preview?.OriginDeliveryNotes ?? new List(); DraftValidation = preview?.Validation ?? new SalesDocumentDraftValidationDto(); } private static string FormatDate(DateTime? value) => value.HasValue ? value.Value.ToString("dd/MM/yyyy") : "-"; private static string GetDocumentTypeLabel(int value) => Enum.IsDefined(typeof(SalesDocumentType), value) ? ((SalesDocumentType)value) switch { SalesDocumentType.Invoice => "Factura", SalesDocumentType.DebitNote => "Nota de debito", SalesDocumentType.CreditNote => "Nota de credito", SalesDocumentType.CreditInvoice => "Factura credito", SalesDocumentType.CreditDebitNote => "N/D credito", SalesDocumentType.CreditCreditNote => "N/C credito", _ => value.ToString() } : value.ToString(); private static string GetStatusLabel(int value) => Enum.IsDefined(typeof(SalesDocumentStatus), value) ? ((SalesDocumentStatus)value) switch { SalesDocumentStatus.Draft => "Borrador", SalesDocumentStatus.Validated => "Validado", SalesDocumentStatus.Issued => "Emitido", SalesDocumentStatus.Cancelled => "Anulado", _ => value.ToString() } : value.ToString(); private static string GetCoverageTypeLabel(int value) => Enum.IsDefined(typeof(SalesDocumentCoverageType), value) ? ((SalesDocumentCoverageType)value) switch { SalesDocumentCoverageType.Direct => "Directa", SalesDocumentCoverageType.Capita => "Capita", SalesDocumentCoverageType.Adjustment => "Ajuste", SalesDocumentCoverageType.Manual => "Manual", _ => value.ToString() } : value.ToString(); private static string GetOriginTypeLabel(string value) => value switch { "MANUAL" => "Manual", "QUOTE" => "Presupuesto", "ADJUSTMENT" => "Ajuste", "CAPITA" => "Capita", "DELIVERY_NOTE" => "Remito", _ => string.IsNullOrWhiteSpace(value) ? "-" : value }; private static string GetStatusBadge(int value) => value switch { (int)SalesDocumentStatus.Draft => "bg-secondary text-white", (int)SalesDocumentStatus.Validated => "bg-info text-dark", (int)SalesDocumentStatus.Issued => "bg-primary text-white", (int)SalesDocumentStatus.Cancelled => "bg-danger text-white", _ => "bg-light text-dark" }; private sealed record ValidationItem(bool IsValid, string Message); }