@page "/salesdocuments/create" @using Domain.Constants @using Domain.Dtos.Sales @using Domain.Generics @using phronCare.UIBlazor.Services.Sales.SalesDocuments @inject NavigationManager Navigation @inject ISalesDocumentService SalesDocumentService @inject IToastService toastService

Nuevo Sales Document desde remitos

Sales Document representa el documento comercial facturable. No emite comprobante fiscal ni integra ARCA/AFIP.
Remitos emitidos pendientes
Seleccionados: @SelectedIds.Count
@if (Candidates.Items.Any()) {
@foreach (var item in Candidates.Items) { }
Remito Fecha Cliente fiscal Presupuesto Ítems Importe aprobado
@item.DeliveryNoteNumber @item.IssueDate.ToString("dd/MM/yyyy") @item.CustomerName @(item.QuoteNumber ?? item.QuoteId?.ToString() ?? "-") @item.ItemCount @item.ApprovedAmount.ToString("N2")
} else {
Buscá remitos emitidos pendientes de facturación.
}
Resumen comercial
@if (SelectedCandidates.Any()) {
Cliente fiscal:
@SelectedCustomerLabel
Remitos:
@SelectedCandidates.Count
Total:
@SelectedTotal.ToString("N2")
Validación:
@if (HasSingleFiscalCustomer) { Cliente único } else { Clientes fiscales distintos }
} else {
Seleccioná uno o más remitos para ver el resumen.
}
@code { private string? CustomerText; private string? DeliveryNoteNumber; private int? QuoteId; private DateTime? IssueDateFrom; private DateTime? IssueDateTo; private string? Observations; private bool IsLoading; private bool IsSaving; private PagedResult Candidates = new(); private readonly HashSet SelectedIds = new(); private readonly Dictionary SelectedMap = new(); private List SelectedCandidates => SelectedMap.Values.OrderBy(x => x.IssueDate).ThenBy(x => x.Id).ToList(); private bool HasSingleFiscalCustomer => SelectedCandidates.Select(x => x.CustomerId).Distinct().Count() <= 1; private bool CanCreate => SelectedIds.Count > 0 && HasSingleFiscalCustomer && SelectedTotal > 0; private decimal SelectedTotal => SelectedCandidates.Sum(x => x.ApprovedAmount); private string SelectedCustomerLabel => SelectedCandidates.FirstOrDefault()?.CustomerName ?? "-"; private async Task SearchCandidatesAsync() { try { IsLoading = true; Candidates = await SalesDocumentService.SearchDeliveryNoteCandidatesAsync( null, CustomerText, DeliveryNoteNumber, QuoteId, IssueDateFrom, IssueDateTo, 1, 50); } catch (Exception ex) { toastService.ShowError(ex.Message); } finally { IsLoading = false; } } private void ToggleSelection(SalesDocumentDeliveryNoteCandidateDto item, ChangeEventArgs args) { var selected = args.Value is bool value && value; if (selected) { SelectedIds.Add(item.Id); SelectedMap[item.Id] = item; } else { SelectedIds.Remove(item.Id); SelectedMap.Remove(item.Id); } } private void ClearFilters() { CustomerText = null; DeliveryNoteNumber = null; QuoteId = null; IssueDateFrom = null; IssueDateTo = null; Candidates = new PagedResult(); SelectedIds.Clear(); SelectedMap.Clear(); } private async Task CreateAsync() { if (!CanCreate) { toastService.ShowError("Debe seleccionar remitos pendientes de un único cliente fiscal."); return; } try { IsSaving = true; var created = await SalesDocumentService.CreateFromDeliveryNotesAsync(new SalesDocumentCreateFromDeliveryNotesRequest { DeliveryNoteIds = SelectedIds.ToList(), DocumentType = (int)SalesDocumentType.Invoice, IssueDate = DateTime.Today, Currency = "ARS", ExchangeRate = 1, Observations = Observations }); toastService.ShowSuccess("Sales Document creado correctamente desde remitos."); Navigation.NavigateTo($"/salesdocuments/{created.Id}"); } catch (Exception ex) { toastService.ShowError(ex.Message); } finally { IsSaving = false; } } private void BackToList() => Navigation.NavigateTo("/salesdocuments"); }