feat(deliverynote): snapshot clínico (ExtraInfo) desde presupuesto
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (pull_request) Successful in 9m31s
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (pull_request) Successful in 9m31s
Se implementa la construcción automática de ExtrainfoJson al seleccionar un presupuesto en la pantalla de emisión de Delivery Note. - Se genera snapshot clínico con Professional, Institution, Patient y SurgeryDate - Se serializa a JSON plano utilizando System.Text.Json - Se asigna a Model.ExtraInfoJson para persistencia - Se limpia el snapshot al deseleccionar o fallar la carga del presupuesto Se mantiene consistencia con el patrón implementado en Expeditions. No se modifican contratos ni capas Core/API/Data. Closes #41
This commit is contained in:
parent
2a9cced311
commit
c1aa6827b0
@ -1,5 +1,6 @@
|
|||||||
@page "/deliverynotes/create"
|
@page "/deliverynotes/create"
|
||||||
@using System.ComponentModel.DataAnnotations
|
@using System.ComponentModel.DataAnnotations
|
||||||
|
@using System.Text.Json
|
||||||
@using Blazored.Typeahead
|
@using Blazored.Typeahead
|
||||||
@using Domain.Constants
|
@using Domain.Constants
|
||||||
@using Domain.Dtos
|
@using Domain.Dtos
|
||||||
@ -27,12 +28,12 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="row mb-3">
|
<div class="row mb-3">
|
||||||
<div class="col-md-4">
|
<div class="col-md-2">
|
||||||
<label for="deliveryNoteNumber" class="form-label">Número de remito</label>
|
<label for="deliveryNoteNumber" class="form-label">Número de remito</label>
|
||||||
<InputText id="deliveryNoteNumber" class="form-control" @bind-Value="Model.DeliveryNoteNumber" />
|
<InputText id="deliveryNoteNumber" class="form-control" @bind-Value="Model.DeliveryNoteNumber" />
|
||||||
<ValidationMessage For="@(() => Model.DeliveryNoteNumber)" />
|
<ValidationMessage For="@(() => Model.DeliveryNoteNumber)" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-2">
|
||||||
<label for="issueDate" class="form-label">Fecha de emisión</label>
|
<label for="issueDate" class="form-label">Fecha de emisión</label>
|
||||||
<InputDate id="issueDate" class="form-control" @bind-Value="Model.IssueDate" />
|
<InputDate id="issueDate" class="form-control" @bind-Value="Model.IssueDate" />
|
||||||
<ValidationMessage For="@(() => Model.IssueDate)" />
|
<ValidationMessage For="@(() => Model.IssueDate)" />
|
||||||
@ -51,10 +52,7 @@
|
|||||||
<SelectedTemplate Context="item">@item.Nombre</SelectedTemplate>
|
<SelectedTemplate Context="item">@item.Nombre</SelectedTemplate>
|
||||||
</BlazoredTypeahead>
|
</BlazoredTypeahead>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
<div class="col-md-4">
|
||||||
|
|
||||||
<div class="row mb-3">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<label for="customerLookup" class="form-label">Cliente</label>
|
<label for="customerLookup" class="form-label">Cliente</label>
|
||||||
<BlazoredTypeahead id="customerLookup" TItem="ELookUpItem" TValue="ELookUpItem"
|
<BlazoredTypeahead id="customerLookup" TItem="ELookUpItem" TValue="ELookUpItem"
|
||||||
SearchMethod="SalesLookupService.SearchCustomersAsync"
|
SearchMethod="SalesLookupService.SearchCustomersAsync"
|
||||||
@ -69,16 +67,47 @@
|
|||||||
</BlazoredTypeahead>
|
</BlazoredTypeahead>
|
||||||
<ValidationMessage For="@(() => Model.CustomerId)" />
|
<ValidationMessage For="@(() => Model.CustomerId)" />
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row mb-3">
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="observations" class="form-label">Observaciones</label>
|
<label for="observations" class="form-label">Observaciones</label>
|
||||||
<InputTextArea id="observations" class="form-control" rows="3" @bind-Value="Model.Observations" />
|
<InputTextArea id="observations" class="form-control" rows="3" @bind-Value="Model.Observations" />
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
@if (SelectedQuote is not null)
|
||||||
|
{
|
||||||
|
<label for="observations" class="form-label">Vinculado</label>
|
||||||
|
<div class="alert alert-dark border mb-3">
|
||||||
|
<strong rows="3">Presupuesto vinculado:</strong> @SelectedQuote.Nombre
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@if (SelectedQuote is not null)
|
@if (SelectedQuote is not null)
|
||||||
{
|
{
|
||||||
<div class="alert alert-light border mb-0">
|
<div class="card border-1 bg-light-subtle">
|
||||||
<strong>Presupuesto vinculado:</strong> @SelectedQuote.Nombre
|
<div class="card-body py-3">
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-semibold mb-1">Profesional</label>
|
||||||
|
<div class="form-control bg-white">@(string.IsNullOrWhiteSpace(ExtraInfo.Professional) ? "No informado" : ExtraInfo.Professional)</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-semibold mb-1">Institución</label>
|
||||||
|
<div class="form-control bg-white">@(string.IsNullOrWhiteSpace(ExtraInfo.Institution) ? "No informada" : ExtraInfo.Institution)</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-semibold mb-1">Paciente</label>
|
||||||
|
<div class="form-control bg-white">@(string.IsNullOrWhiteSpace(ExtraInfo.Patient) ? "No informado" : ExtraInfo.Patient)</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label fw-semibold mb-1">Fecha estimada de cirugía</label>
|
||||||
|
<div class="form-control bg-white">@(ExtraInfo.SurgeryDate.HasValue ? ExtraInfo.SurgeryDate.Value.ToString("dd/MM/yyyy") : "No informada")</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@ -171,6 +200,7 @@
|
|||||||
|
|
||||||
private ELookUpItem? SelectedCustomer;
|
private ELookUpItem? SelectedCustomer;
|
||||||
private ELookUpItem? SelectedQuote;
|
private ELookUpItem? SelectedQuote;
|
||||||
|
private DeliveryNoteExtraInfoModel ExtraInfo = new();
|
||||||
private List<DeliveryNoteItemRow> Items = new();
|
private List<DeliveryNoteItemRow> Items = new();
|
||||||
|
|
||||||
private bool IsSaving;
|
private bool IsSaving;
|
||||||
@ -214,18 +244,27 @@
|
|||||||
Model.QuoteId = quote?.Id;
|
Model.QuoteId = quote?.Id;
|
||||||
|
|
||||||
if (quote is null)
|
if (quote is null)
|
||||||
|
{
|
||||||
|
ExtraInfo = new();
|
||||||
|
Model.ExtraInfoJson = null;
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var quoteDto = await QuoteService.GetDtoByIdAsync(quote.Id);
|
var quoteDto = await QuoteService.GetDtoByIdAsync(quote.Id);
|
||||||
if (quoteDto is null)
|
if (quoteDto is null)
|
||||||
{
|
{
|
||||||
|
ExtraInfo = new();
|
||||||
|
Model.ExtraInfoJson = null;
|
||||||
toastService.ShowError("No se pudo cargar el presupuesto seleccionado.");
|
toastService.ShowError("No se pudo cargar el presupuesto seleccionado.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExtraInfo = BuildExtraInfoModel(quoteDto);
|
||||||
|
|
||||||
var mappedItems = BuildItemsFromApprovedQuote(quoteDto);
|
var mappedItems = BuildItemsFromApprovedQuote(quoteDto);
|
||||||
if (mappedItems.Count == 0)
|
if (mappedItems.Count == 0)
|
||||||
{
|
{
|
||||||
|
Model.ExtraInfoJson = JsonSerializer.Serialize(ExtraInfo);
|
||||||
toastService.ShowWarning("El presupuesto seleccionado no tiene ítems aprobados para precargar.");
|
toastService.ShowWarning("El presupuesto seleccionado no tiene ítems aprobados para precargar.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -243,10 +282,22 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
Items = mappedItems;
|
Items = mappedItems;
|
||||||
|
Model.ExtraInfoJson = JsonSerializer.Serialize(ExtraInfo);
|
||||||
ReindexItems();
|
ReindexItems();
|
||||||
StateHasChanged();
|
StateHasChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static DeliveryNoteExtraInfoModel BuildExtraInfoModel(QuoteDto quote)
|
||||||
|
{
|
||||||
|
return new DeliveryNoteExtraInfoModel
|
||||||
|
{
|
||||||
|
Professional = quote.ProfessionalName,
|
||||||
|
Institution = quote.InstitutionName,
|
||||||
|
Patient = quote.PatientName,
|
||||||
|
SurgeryDate = quote.EstimatedDate
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
private List<DeliveryNoteItemRow> BuildItemsFromApprovedQuote(QuoteDto quote)
|
private List<DeliveryNoteItemRow> BuildItemsFromApprovedQuote(QuoteDto quote)
|
||||||
{
|
{
|
||||||
return quote.Items
|
return quote.Items
|
||||||
@ -351,6 +402,14 @@
|
|||||||
public string? ExtraInfoJson { get; set; }
|
public string? ExtraInfoJson { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed class DeliveryNoteExtraInfoModel
|
||||||
|
{
|
||||||
|
public string? Professional { get; set; }
|
||||||
|
public string? Institution { get; set; }
|
||||||
|
public string? Patient { get; set; }
|
||||||
|
public DateTime? SurgeryDate { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
private sealed class DeliveryNoteItemRow
|
private sealed class DeliveryNoteItemRow
|
||||||
{
|
{
|
||||||
public int LineNumber { get; set; }
|
public int LineNumber { get; set; }
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user