diff --git a/Core/Interfaces/ICustomerDom.cs b/Core/Interfaces/ICustomerDom.cs index 009de10..75bdf9e 100644 --- a/Core/Interfaces/ICustomerDom.cs +++ b/Core/Interfaces/ICustomerDom.cs @@ -10,7 +10,7 @@ namespace Core.Interfaces { public interface ICustomerDom { - Task AddAsync(ECustomer entity); + Task CreateAsync(ECustomer entity); Task DeleteAsync(int id); Task> GetAllAsync(int page = 1, int pageSize = 50); Task GetByIdAsync(int id); diff --git a/Core/Services/CustomerService.cs b/Core/Services/CustomerService.cs index bea465e..3f63ebe 100644 --- a/Core/Services/CustomerService.cs +++ b/Core/Services/CustomerService.cs @@ -1,7 +1,11 @@ -using System.Reflection; +using System.Drawing.Printing; +using System.Reflection; +using Azure; +using System.Reflection.Metadata; using Core.Interfaces; using Domain.Entities; using Domain.Generics; +using Microsoft.EntityFrameworkCore; using Models.Helpers; using Models.Interfaces; using Models.Models; @@ -12,22 +16,11 @@ namespace Core.Services { #region Declaraciones y Constructor private readonly IPhSCustomerRepository _repository; - public CustomerService(IPhSCustomerRepository customerRepository) { _repository = customerRepository ?? throw new ArgumentNullException(nameof(customerRepository)); } #endregion - public Task AddAsync(ECustomer entity) - { - throw new NotImplementedException(); - } - - public Task DeleteAsync(int id) - { - throw new NotImplementedException(); - } - public async Task> GetAllAsync(int page = 1, int pageSize = 50) { try @@ -40,13 +33,34 @@ namespace Core.Services throw new Exception($"{methodName} Message: {ex.Message}", ex); } } - - public Task GetByIdAsync(int id) + public async Task GetByIdAsync(int id) { - throw new NotImplementedException(); + try + { + return await _repository.GetByIdAsync(id); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } } + public async Task CreateAsync(ECustomer entity) + { + if (entity is null) + throw new ArgumentNullException(nameof(entity), "El cliente no puede ser nulo."); - public async Task> SearchAsync(string? name, string? email, string? document, int page, int pageSize) + if (!entity.AccounttypesId.HasValue) + throw new ArgumentException("Debe seleccionar un tipo de cuenta.", nameof(entity.AccounttypesId)); + + if (entity.PhSCustomerDocuments == null || !entity.PhSCustomerDocuments.Any()) + throw new ArgumentException("El cliente debe tener al menos un documento (por ejemplo, CUIT).", nameof(entity.PhSCustomerDocuments)); + + return await _repository.CreateAsync(entity); + } + public async Task> SearchAsync( + string? name, string? email, string? document, + int page = 1, int pageSize = 50) { try { @@ -59,10 +73,20 @@ namespace Core.Services } } + public async Task UpdateAsync(ECustomer entity) + { + if (entity is null) + throw new ArgumentNullException(nameof(entity), "El cliente no puede ser nulo."); + if (!entity.AccounttypesId.HasValue) + throw new ArgumentException("Debe seleccionar un tipo de cuenta.", nameof(entity.AccounttypesId)); + if (entity.PhSCustomerDocuments == null || !entity.PhSCustomerDocuments.Any()) + throw new ArgumentException("El cliente debe tener al menos un documento (por ejemplo, CUIT).", nameof(entity.PhSCustomerDocuments)); - public Task UpdateAsync(ECustomer entity) + return await _repository.UpdateAsync(entity); + } + public Task DeleteAsync(int id) { throw new NotImplementedException(); } diff --git a/Domain/Entities/ECustomer.cs b/Domain/Entities/ECustomer.cs index 5dcc679..1b7798a 100644 --- a/Domain/Entities/ECustomer.cs +++ b/Domain/Entities/ECustomer.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -9,13 +10,13 @@ namespace Domain.Entities public class ECustomer { public int Id { get; set; } - + [Required(ErrorMessage = "Debe ingresar un nombre.")] public string? Name { get; set; } - + [Required(ErrorMessage = "Debe ingresar una razon social.")] public string? BusinessName { get; set; } - + [Required(ErrorMessage = "Debe seleccionar un tipo de cuenta.")] public int? AccounttypesId { get; set; } - + [Required(ErrorMessage = "Debe seleccionar un condicion.")] public int? TaxConditionId { get; set; } public bool HasCreditAccount { get; set; } diff --git a/Domain/Entities/ECustomerAddress.cs b/Domain/Entities/ECustomerAddress.cs index d195c6c..ab51a57 100644 --- a/Domain/Entities/ECustomerAddress.cs +++ b/Domain/Entities/ECustomerAddress.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -10,7 +11,9 @@ namespace Domain.Entities { public int Id { get; set; } public int CustomersId { get; set; } + [Required(ErrorMessage = "Debe un nombre de sucursal/ubicacion.")] public string? BusinessName { get; set; } + [Required(ErrorMessage = "Debe ingresar una direccion valida.")] public string? Streetaddress1 { get; set; } public string? Streetaddress2 { get; set; } public string? City { get; set; } diff --git a/Domain/Entities/ECustomerDocument.cs b/Domain/Entities/ECustomerDocument.cs index c6294c7..2549f68 100644 --- a/Domain/Entities/ECustomerDocument.cs +++ b/Domain/Entities/ECustomerDocument.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; @@ -9,11 +10,10 @@ namespace Domain.Entities public class ECustomerDocument { public int Id { get; set; } - public int CustomersId { get; set; } - + [Required(ErrorMessage = "Debe seleccionar un tipo de documento.")] public int DocumenttypesId { get; set; } - + [Required(ErrorMessage = "Debe seleccionar un numero documento.")] public string DocumentNumber { get; set; } = null!; public DateOnly? IssueDate { get; set; } diff --git a/Models/Helpers/EntityMapper.cs b/Models/Helpers/EntityMapper.cs index f526ada..7c587a8 100644 --- a/Models/Helpers/EntityMapper.cs +++ b/Models/Helpers/EntityMapper.cs @@ -65,7 +65,21 @@ namespace Models.Helpers return destination; } + public static void MapEntityToExisting(TSource source, TTarget target) + { + var sourceProps = typeof(TSource).GetProperties(); + var targetProps = typeof(TTarget).GetProperties(); + foreach (var sourceProp in sourceProps) + { + var targetProp = targetProps.FirstOrDefault(p => p.Name == sourceProp.Name && p.PropertyType == sourceProp.PropertyType); + if (targetProp != null && targetProp.CanWrite) + { + var value = sourceProp.GetValue(source); + targetProp.SetValue(target, value); + } + } + } private static bool IsGenericCollection(Type type) { if (!type.IsGenericType) return false; diff --git a/Models/Interfaces/IPhSCustomerRepository.cs b/Models/Interfaces/IPhSCustomerRepository.cs index f5d390c..6c7bd60 100644 --- a/Models/Interfaces/IPhSCustomerRepository.cs +++ b/Models/Interfaces/IPhSCustomerRepository.cs @@ -11,7 +11,7 @@ namespace Models.Interfaces { public interface IPhSCustomerRepository { - Task AddAsync(ECustomer entity); + Task CreateAsync(ECustomer entity); Task DeleteAsync(int id); Task> GetAllAsync(int page = 1, int pageSize = 50); Task GetByIdAsync(int id); diff --git a/Models/Repositories/PhSCustomerRepository.cs b/Models/Repositories/PhSCustomerRepository.cs index 45602b7..8248cec 100644 --- a/Models/Repositories/PhSCustomerRepository.cs +++ b/Models/Repositories/PhSCustomerRepository.cs @@ -13,8 +13,6 @@ namespace Models.Repositories { #region Declaraciones y Constructor private readonly PhronCareOperationsHubContext _context = context; - private readonly ILogger _logger = logger; - #endregion public async Task> GetAllAsync(int page = 1, int pageSize = 50) { @@ -34,7 +32,6 @@ namespace Models.Repositories PageSize = pagedEntities.PageSize }; } - public async Task GetByIdAsync(int id) { var customer = await _context.PhSCustomers @@ -89,22 +86,87 @@ namespace Models.Repositories PageSize = pagedEntities.PageSize }; } - - public async Task AddAsync(ECustomer entity) + public async Task CreateAsync(ECustomer entity) { - var customer = EntityMapper.MapEntity(entity); - await _context.PhSCustomers.AddAsync(customer); - await _context.SaveChangesAsync(); - return EntityMapper.MapEntity(customer); + if (entity == null) + { + throw new ArgumentNullException(nameof(entity), "El cliente no puede ser nulo."); + } + try + { + var customer = EntityMapper.MapEntity(entity); + // Mapeo de direcciones + foreach (var address in entity.PhSCustomerAddresses) + { + var mappedAddress = EntityMapper.MapEntity(address); + customer.PhSCustomerAddresses.Add(mappedAddress); + } + // Mapeo de documentos + foreach (var doc in entity.PhSCustomerDocuments) + { + var mappedDoc = EntityMapper.MapEntity(doc); + customer.PhSCustomerDocuments.Add(mappedDoc); + } + // Agregar el cliente al contexto de la base de datos + await _context.PhSCustomers.AddAsync(customer); + await _context.SaveChangesAsync(); + // Mapear y devolver el cliente con la estructura de dominio + return EntityMapper.MapEntity(customer); + } + catch (DbUpdateException dbEx) + { + // Error relacionado con la base de datos (como violación de integridad referencial) + throw new Exception("Error al guardar el cliente en la base de datos. Es posible que haya un problema con la integridad de los datos.", dbEx); + } + catch (Exception ex) + { + // Captura cualquier otro tipo de excepción + throw new Exception("Error inesperado al crear el cliente: " + ex.Message, ex); + } } public async Task UpdateAsync(ECustomer entity) { - var customer = await _context.PhSCustomers.FindAsync(entity.Id); - if (customer == null) return false; + if (entity == null) + throw new ArgumentNullException(nameof(entity)); - _context.Entry(customer).CurrentValues.SetValues(entity); - await _context.SaveChangesAsync(); - return true; + try + { + var existingCustomer = await _context.PhSCustomers + .Include(c => c.PhSCustomerAddresses) + .Include(c => c.PhSCustomerDocuments) + .FirstOrDefaultAsync(c => c.Id == entity.Id); + + if (existingCustomer == null) + return false; + + EntityMapper.MapEntityToExisting(entity, existingCustomer); + + _context.PhSCustomerAddresses.RemoveRange(existingCustomer.PhSCustomerAddresses); + existingCustomer.PhSCustomerAddresses.Clear(); + + foreach (var address in entity.PhSCustomerAddresses) + { + var mappedAddress = EntityMapper.MapEntity(address); + existingCustomer.PhSCustomerAddresses.Add(mappedAddress); + } + + _context.PhSCustomerDocuments.RemoveRange(existingCustomer.PhSCustomerDocuments); + existingCustomer.PhSCustomerDocuments.Clear(); + + foreach (var doc in entity.PhSCustomerDocuments) + { + var mappedDoc = EntityMapper.MapEntity(doc); + existingCustomer.PhSCustomerDocuments.Add(mappedDoc); + } + + await _context.SaveChangesAsync(); + return true; + } + catch (Exception ex) + { + // Podés loguear el error si querés + return false; + } } public async Task DeleteAsync(int id) { diff --git a/phronCare.API/Controllers/Sales/CustomerController.cs b/phronCare.API/Controllers/Sales/CustomerController.cs index 1691776..6b006b1 100644 --- a/phronCare.API/Controllers/Sales/CustomerController.cs +++ b/phronCare.API/Controllers/Sales/CustomerController.cs @@ -1,4 +1,5 @@ using Core.Interfaces; +using Domain.Entities; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.Reflection; @@ -14,6 +15,7 @@ namespace phronCare.API.Controllers.Sales { _customerService = customerService ?? throw new ArgumentNullException(nameof(customerService)); } + [HttpGet("all")] public async Task GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 50) { @@ -28,6 +30,7 @@ namespace phronCare.API.Controllers.Sales return StatusCode(500, $"{methodName} Message: {ex.Message}"); } } + [HttpGet("search")] public async Task Search( [FromQuery] string? name, @@ -47,20 +50,67 @@ namespace phronCare.API.Controllers.Sales return StatusCode(500, $"{methodName} Message: {ex.Message}"); } } - //[HttpGet("search")] - //public async Task Search([FromQuery] string? name, [FromQuery] string? email, [FromQuery] string? document) - //{ - // try - // { - // var result = await _customerService.SearchAsync(name, email, document); - // return Ok(result); - // } - // catch (Exception ex) - // { - // var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; - // return StatusCode(500, $"{methodName} Message: {ex.Message}"); - // } - //} + [HttpGet("{id:int}")] + public async Task> GetById(int id) + { + try + { + var customer = await _customerService.GetByIdAsync(id); + if (customer == null) + return NotFound(); + return Ok(customer); + } + catch (Exception ex) + { + return StatusCode(500, $"Error: {ex.Message}"); + } + } + [HttpPost("create")] + public async Task Create([FromBody] ECustomer customer) + { + try + { + if (customer == null) + return BadRequest("El cliente no puede ser nulo."); + + var result = await _customerService.CreateAsync(customer); + return Ok(result); + } + catch (ArgumentNullException ex) + { + return BadRequest($"Validación fallida: {ex.Message}"); + } + catch (InvalidOperationException ex) + { + return BadRequest($"Error de negocio: {ex.Message}"); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } + [HttpPut("update")] + public async Task Update([FromBody] ECustomer customer) + { + try + { + if (customer == null || customer.Id <= 0) + return BadRequest("El cliente es inválido o no tiene un ID válido."); + + var success = await _customerService.UpdateAsync(customer); + + if (!success) + return NotFound($"No se encontró un cliente con ID {customer.Id}."); + + return Ok("Cliente actualizado correctamente."); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } } } diff --git a/phronCare.API/obj/Debug/net8.0/ApiEndpoints.json b/phronCare.API/obj/Debug/net8.0/ApiEndpoints.json index cfd3881..cee6104 100644 --- a/phronCare.API/obj/Debug/net8.0/ApiEndpoints.json +++ b/phronCare.API/obj/Debug/net8.0/ApiEndpoints.json @@ -141,6 +141,32 @@ ], "ReturnTypes": [] }, + { + "ContainingType": "phronCare.API.Controllers.Sales.AccountTypeController", + "Method": "GetAll", + "RelativePath": "api/AccountType/GetAll", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.AccountTypeController", + "Method": "GetByName", + "RelativePath": "api/AccountType/GetByName/{name}", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "name", + "Type": "System.String", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, { "ContainingType": "phronCare.API.Controllers.AuthenticationController", "Method": "ConfirmEmail", @@ -278,6 +304,121 @@ ], "ReturnTypes": [] }, + { + "ContainingType": "phronCare.API.Controllers.Sales.CustomerController", + "Method": "GetById", + "RelativePath": "api/Customer/{id}", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "id", + "Type": "System.Int32", + "IsRequired": true + } + ], + "ReturnTypes": [ + { + "Type": "Domain.Entities.ECustomer", + "MediaTypes": [ + "text/plain", + "application/json", + "text/json" + ], + "StatusCode": 200 + } + ] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.CustomerController", + "Method": "GetAll", + "RelativePath": "api/Customer/all", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "page", + "Type": "System.Int32", + "IsRequired": false + }, + { + "Name": "pageSize", + "Type": "System.Int32", + "IsRequired": false + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.CustomerController", + "Method": "Create", + "RelativePath": "api/Customer/create", + "HttpMethod": "POST", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "customer", + "Type": "Domain.Entities.ECustomer", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.CustomerController", + "Method": "Search", + "RelativePath": "api/Customer/search", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "name", + "Type": "System.String", + "IsRequired": false + }, + { + "Name": "email", + "Type": "System.String", + "IsRequired": false + }, + { + "Name": "document", + "Type": "System.String", + "IsRequired": false + }, + { + "Name": "page", + "Type": "System.Int32", + "IsRequired": false + }, + { + "Name": "pageSize", + "Type": "System.Int32", + "IsRequired": false + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.CustomerController", + "Method": "Update", + "RelativePath": "api/Customer/update", + "HttpMethod": "PUT", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "customer", + "Type": "Domain.Entities.ECustomer", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, { "ContainingType": "phronCare.API.Controllers.DbTestController", "Method": "TestEdmxConnection", @@ -288,6 +429,58 @@ "Parameters": [], "ReturnTypes": [] }, + { + "ContainingType": "phronCare.API.Controllers.Sales.DocumentTypeController", + "Method": "GetAll", + "RelativePath": "api/DocumentType/GetAll", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.DocumentTypeController", + "Method": "GetByName", + "RelativePath": "api/DocumentType/GetByName/{name}", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "name", + "Type": "System.String", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.TaxConditionController", + "Method": "GetAll", + "RelativePath": "api/TaxCondition/GetAll", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.TaxConditionController", + "Method": "GetByName", + "RelativePath": "api/TaxCondition/GetByName/{name}", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "name", + "Type": "System.String", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, { "ContainingType": "phronCare.API.Controllers.TestController", "Method": "GetAdministradores", diff --git a/phronCare.UIBlazor/Pages/Sales/CustomerForm.razor b/phronCare.UIBlazor/Pages/Sales/CustomerForm.razor index 647d331..1caedd4 100644 --- a/phronCare.UIBlazor/Pages/Sales/CustomerForm.razor +++ b/phronCare.UIBlazor/Pages/Sales/CustomerForm.razor @@ -1,7 +1,9 @@ @page "/sales/customerform" @page "/sales/customerform/{CustomerId:int}" +@using System.ComponentModel.DataAnnotations +@using phronCare.UIBlazor.Pages.Shared.Modals @using phronCare.UIBlazor.Services.Sales - +@inject IModalService Modal @inject HttpClient _httpClient @inject NavigationManager Navigation @inject IToastService toastService @@ -9,216 +11,222 @@ @inject AccountTypeService accountTypeService @inject TaxConditionService taxConditionService - - - - -
-
- - -
-
- - -
+
+
+

Formulario: cliente

- -
-
- - - - @foreach (var type in accountTypes) - { - - } - -
-
- - - - @foreach (var tax in taxConditions) - { - - } - -
-
- -
-
-
- -
-
- - -
-
-
- -
-
-
-
Documentos
- -
-
- - - - @foreach (var tipo in documentTypes) - { - - } - -
-
- - -
-
- -
-
- -
- - @if (customer.PhSCustomerDocuments?.Any() == true) - { - - - - - - - - - - @foreach (var doc in customer.PhSCustomerDocuments) - { - - - - - - } - -
TipoNúmero
@documentTypes.FirstOrDefault(t => t.Id == doc.DocumenttypesId)?.Name@doc.DocumentNumber - -
- } - -

Direcciones

- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- @if (editingAddress.Country == "Argentina" && provincesByCountry.TryGetValue("Argentina", out var provincias)) +
+ + + +
+
+ + +
+
+ + +
+
+
+
+ + + + @foreach (var type in accountTypes) + { + + } + +
+
+ + + + @foreach (var tax in taxConditions) + { + + } + +
+
+
+
+
+ +
+
+ + +
+
+
+ +
+
+
+
Documentos
+
+
+ + + + @foreach (var tipo in documentTypes) + { + + } + +
+
+ + +
+
+ +
+
+
+ @if (customer.PhSCustomerDocuments?.Any() == true) { - +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ @if (editingAddress.Country == "Argentina" && provincesByCountry.TryGetValue("Argentina", out var provincias)) { - + } - - } - else - { - - } -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
-
- -
- - @if (editingIndex != -1) - { - - } -
- - @if (customer.PhSCustomerAddresses.Any()) - { - - - - - - - - - - - - - @foreach (var address in customer.PhSCustomerAddresses.Select((value, index) => new { value, index })) + else + { + + } + + +
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+
+ + @if (editingIndex != -1) { -
- - - - - - - + } - -
SucursalDirecciónCiudadProvinciaPaís
@address.value.BusinessName@address.value.Streetaddress1@address.value.City@address.value.Stateprovince@address.value.Country - - -
- } - +
+ + @if (customer.PhSCustomerAddresses.Any()) + { + + + + + + + + + + + + + @foreach (var address in customer.PhSCustomerAddresses.Select((value, index) => new { value, index })) + { + + + + + + + + + } + +
SucursalDirecciónCiudadProvinciaPaís
@address.value.BusinessName@address.value.Streetaddress1@address.value.City@address.value.Stateprovince@address.value.Country + + +
+ } + +
+ +
@code { [Parameter] @@ -229,6 +237,7 @@ private List taxConditions = new(); private List documentTypes = new(); private ECustomerDocument documentFormModel = new(); + private bool isSaving = false; private string returnUrl = "/sales/customers"; @@ -262,6 +271,18 @@ private void AddOrUpdateAddress() { + var context = new ValidationContext(editingAddress, null, null); + var results = new List(); + + if (!Validator.TryValidateObject(editingAddress, context, results, true)) + { + // Mostrar errores en un toast o en pantalla + foreach (var error in results) + { + toastService.ShowError(error.ErrorMessage); + } + return; + } if (editingIndex == -1) { // Agregar nueva dirección @@ -332,7 +353,6 @@ editingIndex = -1; } - protected override async Task OnInitializedAsync() { await LoadAccountTypes(); @@ -342,7 +362,7 @@ if (CustomerId.HasValue) { // Cargar datos del cliente existente desde la API - customer = await _httpClient.GetFromJsonAsync($"/api/Customer/GetById/{CustomerId.Value}") ?? new(); + customer = await _httpClient.GetFromJsonAsync($"/api/Customer/{CustomerId.Value}") ?? new(); } } @@ -372,14 +392,21 @@ { customer.PhSCustomerDocuments.Remove(document); } - private void RemoveCustomerAddress(ECustomerAddress address) { customer.PhSCustomerAddresses.Remove(address); } - + private async Task HandleValidSubmit() { + var parameters = new ModalParameters(); + parameters.Add("Message", "¿Desea guardar los cambios del cliente?"); + + var modal = Modal.Show("Confirmacion", parameters); + var result = await modal.Result; + + if (result.Cancelled) + return; try { HttpResponseMessage response; @@ -413,4 +440,4 @@ { Navigation.NavigateTo(returnUrl); } -} +} \ No newline at end of file diff --git a/phronCare.UIBlazor/Pages/Sales/Customers.razor b/phronCare.UIBlazor/Pages/Sales/Customers.razor index 3897a8d..42f58de 100644 --- a/phronCare.UIBlazor/Pages/Sales/Customers.razor +++ b/phronCare.UIBlazor/Pages/Sales/Customers.razor @@ -10,7 +10,7 @@

Listado de clientes

@* wtf? *@
-
+
@@ -118,10 +118,27 @@ // var filename = $"Tickets_{Group}_{currentDate}.xlsx"; // await js.InvokeAsync("saveAsFile", filename, Convert.ToBase64String(fileBytes)); } - List botones = new List + + List botones = new(); + protected override void OnInitialized() { - new PhTable.ButtonOptions{ Caption="Editar", ElementClass="btn btn-primary btn-sm"} - }; + botones = new List + { + new PhTable.ButtonOptions + { + Caption = "Editar", + ElementClass = "btn btn-primary btn-sm", + UrlAction = "/sales/customers/edit/", + OnClickAction = async (id) => + { + if (int.TryParse(id, out var customerId)) + { + Navigation.NavigateTo($"/sales/customerform/{customerId}"); + } + } + } + }; + } private int TotalPaginas => PagedResult is null ? 1 : (int)Math.Ceiling((double)(PagedResult.TotalItems) / SearchParams.PageSize); private bool PuedeAvanzar => PagedResult != null && SearchParams.Page < TotalPaginas; diff --git a/phronCare.UIBlazor/Pages/Shared/Modals/ConfirmModal.razor b/phronCare.UIBlazor/Pages/Shared/Modals/ConfirmModal.razor new file mode 100644 index 0000000..3144dee --- /dev/null +++ b/phronCare.UIBlazor/Pages/Shared/Modals/ConfirmModal.razor @@ -0,0 +1,30 @@ +@using Blazored.Modal +@using Blazored.Modal.Services +@inherits LayoutComponentBase + + + + +@code { + [CascadingParameter] BlazoredModalInstance ModalInstance { get; set; } + + [Parameter] public string Title { get; set; } = string.Empty; + [Parameter] public string Message { get; set; } = string.Empty; + + private async Task Confirm() + { + await ModalInstance.CloseAsync(ModalResult.Ok(true)); + } + + private async Task Cancel() + { + await ModalInstance.CancelAsync(); + } +} +