Leandro Hernan Rojas ab622e72ff
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m0s
Update CustomerForm Address List
2025-04-11 11:25:29 -03:00

417 lines
14 KiB
Plaintext

@page "/sales/customerform"
@page "/sales/customerform/{CustomerId:int}"
@using phronCare.UIBlazor.Services.Sales
@inject HttpClient _httpClient
@inject NavigationManager Navigation
@inject IToastService toastService
@inject AuthenticationStateProvider authenticationStateProvider
@inject AccountTypeService accountTypeService
@inject TaxConditionService taxConditionService
<EditForm Model="@customer" OnValidSubmit="@HandleValidSubmit">
<DataAnnotationsValidator />
<ValidationSummary />
<div class="row">
<div class="col-md-6">
<label for="Name">Nombre / Razón Social:</label>
<InputText id="Name" @bind-Value="customer.Name" class="form-control" />
</div>
<div class="col-md-6">
<label for="BusinessName">Sucursal / Nombre Comercial:</label>
<InputText id="BusinessName" @bind-Value="customer.BusinessName" class="form-control" />
</div>
</div>
<div class="row">
<div class="col-md-6">
<label for="AccounttypesId">Tipo de Cuenta:</label>
<InputSelect id="AccounttypesId" @bind-Value="customer.AccounttypesId" class="form-control">
<option value="">-- Seleccionar --</option>
@foreach (var type in accountTypes)
{
<option value="@type.Id">@type.Name</option>
}
</InputSelect>
</div>
<div class="col-md-6">
<label for="TaxConditionId">Condición Fiscal:</label>
<InputSelect id="TaxConditionId" @bind-Value="customer.TaxConditionId" class="form-control">
<option value="">-- Seleccionar --</option>
@foreach (var tax in taxConditions)
{
<option value="@tax.Id">@tax.Description</option>
}
</InputSelect>
</div>
</div>
<div class="row">
<div class="col-md-4">
<label for="HasCreditAccount">¿Cuenta Corriente?</label><br />
<InputCheckbox id="HasCreditAccount" @bind-Value="customer.HasCreditAccount" />
</div>
<div class="col-md-4">
<label for="CreditLimit">Límite de Crédito:</label>
<InputNumber id="CreditLimit" @bind-Value="customer.CreditLimit" class="form-control" />
</div>
<div class="col-md-4">
<label for="Active">Activo:</label><br />
<InputCheckbox id="Active" @bind-Value="customer.Active" />
</div>
</div>
<hr />
<h5>Documentos</h5>
<div class="row align-items-end">
<div class="col-sm-4">
<label for="TipoDocumento">Tipo:</label>
<InputSelect id="TipoDocumento" class="form-control" @bind-Value="documentFormModel.DocumenttypesId">
<option value="">Seleccione</option>
@foreach (var tipo in documentTypes)
{
<option value="@tipo.Id">@tipo.Name</option>
}
</InputSelect>
</div>
<div class="col-sm-4">
<label for="NumeroDocumento">Número:</label>
<InputText id="NumeroDocumento" class="form-control" @bind-Value="documentFormModel.DocumentNumber" />
</div>
<div class="col-sm-2">
<button type="button" class="btn btn-success" @onclick="AddCustomerDocument">Agregar</button>
</div>
</div>
<br />
@if (customer.PhSCustomerDocuments?.Any() == true)
{
<table class="table table-sm table-bordered">
<thead>
<tr>
<th>Tipo</th>
<th>Número</th>
<th style="width:50px;"></th>
</tr>
</thead>
<tbody>
@foreach (var doc in customer.PhSCustomerDocuments)
{
<tr>
<td>@documentTypes.FirstOrDefault(t => t.Id == doc.DocumenttypesId)?.Name</td>
<td>@doc.DocumentNumber</td>
<td>
<button class="btn btn-sm btn-danger" @onclick="() => RemoveCustomerDocument(doc)">🗑</button>
</td>
</tr>
}
</tbody>
</table>
}
<h4 class="mt-4">Direcciones</h4>
<div class="row mb-3">
<div class="col-md-6">
<input class="form-control" placeholder="Nombre de sucursal" @bind="editingAddress.BusinessName" />
</div>
<div class="col-md-6">
<input class="form-control" placeholder="Dirección línea 1" @bind="editingAddress.Streetaddress1" />
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<input class="form-control" placeholder="Dirección línea 2" @bind="editingAddress.Streetaddress2" />
</div>
<div class="col-md-6">
<input class="form-control" placeholder="Ciudad" @bind="editingAddress.City" />
</div>
</div>
<div class="row mb-3">
<div class="col-md-6">
<select class="form-control" value="@editingAddress.Country" @onchange="OnCountryChanged">
<option value="">Seleccionar país</option>
@foreach (var country in countries)
{
<option value="@country">@country</option>
}
</select>
</div>
<div class="col-md-6">
@if (editingAddress.Country == "Argentina" && provincesByCountry.TryGetValue("Argentina", out var provincias))
{
<select class="form-control" @bind="editingAddress.Stateprovince">
<option value="">Seleccionar provincia</option>
@foreach (var provincia in provincias)
{
<option value="@provincia">@provincia</option>
}
</select>
}
else
{
<input class="form-control" placeholder="Estado/Provincia" @bind="editingAddress.Stateprovince" />
}
</div>
</div>
<div class="row mb-3">
<div class="col-md-4">
<input class="form-control" placeholder="Código Postal" @bind="editingAddress.Postalcode" />
</div>
<div class="col-md-4">
<input class="form-control" placeholder="Teléfono" @bind="editingAddress.Phonenumber" />
</div>
<div class="col-md-4">
<input class="form-control" placeholder="Email" @bind="editingAddress.Email" />
</div>
</div>
<div class="row mb-3">
<div class="col-md-12">
<textarea class="form-control" placeholder="Notas" @bind="editingAddress.Notes"></textarea>
</div>
</div>
<div class="mb-3">
<button class="btn btn-sm btn-success" @onclick="AddOrUpdateAddress">
@((editingIndex == -1) ? "Agregar dirección" : "Actualizar dirección")
</button>
@if (editingIndex != -1)
{
<button class="btn btn-sm btn-secondary ms-2" @onclick="CancelAddressEdit">Cancelar</button>
}
</div>
@if (customer.PhSCustomerAddresses.Any())
{
<table class="table table-bordered">
<thead>
<tr>
<th>Sucursal</th>
<th>Dirección</th>
<th>Ciudad</th>
<th>Provincia</th>
<th>País</th>
<th></th>
</tr>
</thead>
<tbody>
@foreach (var address in customer.PhSCustomerAddresses.Select((value, index) => new { value, index }))
{
<tr>
<td>@address.value.BusinessName</td>
<td>@address.value.Streetaddress1</td>
<td>@address.value.City</td>
<td>@address.value.Stateprovince</td>
<td>@address.value.Country</td>
<td>
<button class="btn btn-sm btn-primary me-1" @onclick="() => EditAddress(address.index)">Editar</button>
<button class="btn btn-sm btn-danger" @onclick="() => RemoveAddress(address.index)">Eliminar</button>
</td>
</tr>
}
</tbody>
</table>
}
</EditForm>
@code {
[Parameter]
public int? CustomerId { get; set; }
private ECustomer customer { get; set; } = new();
private List<EAccountType> accountTypes = new();
private List<ETaxCondition> taxConditions = new();
private List<EDocumentType> documentTypes = new();
private ECustomerDocument documentFormModel = new();
private string returnUrl = "/sales/customers";
private List<string> countries = new() {
"Argentina", "Brasil", "Chile", "Uruguay", "Paraguay", "Estados Unidos", "Canadá",
"México", "Alemania", "Reino Unido", "Francia", "Italia", "España"
};
private Dictionary<string, List<string>> provincesByCountry = new()
{
{
"Argentina", new List<string>
{
"Buenos Aires", "CABA", "Catamarca", "Chaco", "Chubut", "Córdoba", "Corrientes",
"Entre Ríos", "Formosa", "Jujuy", "La Pampa", "La Rioja", "Mendoza", "Misiones",
"Neuquén", "Río Negro", "Salta", "San Juan", "San Luis", "Santa Cruz",
"Santa Fe", "Santiago del Estero", "Tierra del Fuego", "Tucumán"
}
}
};
private ECustomerAddress editingAddress = new();
private int editingIndex = -1;
private void OnCountryChanged(ChangeEventArgs e)
{
var selectedCountry = e.Value?.ToString();
editingAddress.Country = selectedCountry;
editingAddress.Stateprovince = string.Empty; // Resetear la provincia si cambia el país
}
private void AddOrUpdateAddress()
{
if (editingIndex == -1)
{
// Agregar nueva dirección
customer.PhSCustomerAddresses.Add(editingAddress);
}
else
{
// Actualizar dirección existente
var existing = customer.PhSCustomerAddresses.ElementAt(editingIndex);
existing.BusinessName = editingAddress.BusinessName;
existing.Streetaddress1 = editingAddress.Streetaddress1;
existing.Streetaddress2 = editingAddress.Streetaddress2;
existing.City = editingAddress.City;
existing.Stateprovince = editingAddress.Stateprovince;
existing.Postalcode = editingAddress.Postalcode;
existing.Country = editingAddress.Country;
existing.Latitude = editingAddress.Latitude;
existing.Longitude = editingAddress.Longitude;
existing.Phonenumber = editingAddress.Phonenumber;
existing.Email = editingAddress.Email;
existing.Notes = editingAddress.Notes;
}
ResetAddressForm();
}
private void EditAddress(int index)
{
var addr = customer.PhSCustomerAddresses.ElementAt(index);
editingAddress = new ECustomerAddress
{
Id = addr.Id, // Incluí el Id como mencionamos antes, para no perder referencia
BusinessName = addr.BusinessName,
Streetaddress1 = addr.Streetaddress1,
Streetaddress2 = addr.Streetaddress2,
City = addr.City,
Stateprovince = addr.Stateprovince,
Postalcode = addr.Postalcode,
Country = addr.Country,
Latitude = addr.Latitude,
Longitude = addr.Longitude,
Phonenumber = addr.Phonenumber,
Email = addr.Email,
Notes = addr.Notes
};
editingIndex = index;
}
private void RemoveAddress(int index)
{
var itemToRemove = customer.PhSCustomerAddresses.ElementAt(index);
customer.PhSCustomerAddresses.Remove(itemToRemove);
ResetAddressForm();
}
private void CancelAddressEdit()
{
ResetAddressForm();
}
private void ResetAddressForm()
{
editingAddress = new();
editingIndex = -1;
}
protected override async Task OnInitializedAsync()
{
await LoadAccountTypes();
await LoadTaxConditions();
await LoadDocumentTypes();
if (CustomerId.HasValue)
{
// Cargar datos del cliente existente desde la API
customer = await _httpClient.GetFromJsonAsync<ECustomer>($"/api/Customer/GetById/{CustomerId.Value}") ?? new();
}
}
private async Task LoadAccountTypes()
{
accountTypes = await accountTypeService.GetAllAsync();
}
private async Task LoadTaxConditions()
{
taxConditions = await taxConditionService.GetAllAsync();
}
private async Task LoadDocumentTypes()
{
var result = await _httpClient.GetFromJsonAsync<List<EDocumentType>>("/api/DocumentType/GetAll");
documentTypes = result ?? new();
}
private void AddCustomerDocument()
{
if (!string.IsNullOrWhiteSpace(documentFormModel.DocumentNumber))
{
customer.PhSCustomerDocuments.Add(documentFormModel);
documentFormModel = new();
}
}
private void RemoveCustomerDocument(ECustomerDocument document)
{
customer.PhSCustomerDocuments.Remove(document);
}
private void RemoveCustomerAddress(ECustomerAddress address)
{
customer.PhSCustomerAddresses.Remove(address);
}
private async Task HandleValidSubmit()
{
try
{
HttpResponseMessage response;
if (CustomerId.HasValue)
{
response = await _httpClient.PutAsJsonAsync("/api/Customer/Update", customer);
}
else
{
response = await _httpClient.PostAsJsonAsync("/api/Customer/Create", customer);
}
if (response.IsSuccessStatusCode)
{
toastService.ShowSuccess("Cliente guardado exitosamente");
Navigation.NavigateTo(returnUrl);
}
else
{
var error = await response.Content.ReadAsStringAsync();
toastService.ShowError($"Error: {error}");
}
}
catch (Exception ex)
{
toastService.ShowError($"Error: {ex.Message}");
}
}
private void Cancel()
{
Navigation.NavigateTo(returnUrl);
}
}