Update Customers Update Create and List
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m4s
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m4s
This commit is contained in:
parent
ab622e72ff
commit
0177366fc9
@ -10,7 +10,7 @@ namespace Core.Interfaces
|
|||||||
{
|
{
|
||||||
public interface ICustomerDom
|
public interface ICustomerDom
|
||||||
{
|
{
|
||||||
Task<ECustomer> AddAsync(ECustomer entity);
|
Task<ECustomer> CreateAsync(ECustomer entity);
|
||||||
Task<bool> DeleteAsync(int id);
|
Task<bool> DeleteAsync(int id);
|
||||||
Task<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50);
|
Task<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50);
|
||||||
Task<ECustomer?> GetByIdAsync(int id);
|
Task<ECustomer?> GetByIdAsync(int id);
|
||||||
|
|||||||
@ -1,7 +1,11 @@
|
|||||||
using System.Reflection;
|
using System.Drawing.Printing;
|
||||||
|
using System.Reflection;
|
||||||
|
using Azure;
|
||||||
|
using System.Reflection.Metadata;
|
||||||
using Core.Interfaces;
|
using Core.Interfaces;
|
||||||
using Domain.Entities;
|
using Domain.Entities;
|
||||||
using Domain.Generics;
|
using Domain.Generics;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Models.Helpers;
|
using Models.Helpers;
|
||||||
using Models.Interfaces;
|
using Models.Interfaces;
|
||||||
using Models.Models;
|
using Models.Models;
|
||||||
@ -12,22 +16,11 @@ namespace Core.Services
|
|||||||
{
|
{
|
||||||
#region Declaraciones y Constructor
|
#region Declaraciones y Constructor
|
||||||
private readonly IPhSCustomerRepository _repository;
|
private readonly IPhSCustomerRepository _repository;
|
||||||
|
|
||||||
public CustomerService(IPhSCustomerRepository customerRepository)
|
public CustomerService(IPhSCustomerRepository customerRepository)
|
||||||
{
|
{
|
||||||
_repository = customerRepository ?? throw new ArgumentNullException(nameof(customerRepository));
|
_repository = customerRepository ?? throw new ArgumentNullException(nameof(customerRepository));
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
public Task<ECustomer> AddAsync(ECustomer entity)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<bool> DeleteAsync(int id)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50)
|
public async Task<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
@ -40,13 +33,34 @@ namespace Core.Services
|
|||||||
throw new Exception($"{methodName} Message: {ex.Message}", ex);
|
throw new Exception($"{methodName} Message: {ex.Message}", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public async Task<ECustomer?> GetByIdAsync(int id)
|
||||||
public Task<ECustomer?> 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<ECustomer> CreateAsync(ECustomer entity)
|
||||||
|
{
|
||||||
|
if (entity is null)
|
||||||
|
throw new ArgumentNullException(nameof(entity), "El cliente no puede ser nulo.");
|
||||||
|
|
||||||
public async Task<PagedResult<ECustomer>> 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<PagedResult<ECustomer>> SearchAsync(
|
||||||
|
string? name, string? email, string? document,
|
||||||
|
int page = 1, int pageSize = 50)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@ -59,10 +73,20 @@ namespace Core.Services
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task<bool> 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<bool> UpdateAsync(ECustomer entity)
|
return await _repository.UpdateAsync(entity);
|
||||||
|
}
|
||||||
|
public Task<bool> DeleteAsync(int id)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -9,13 +10,13 @@ namespace Domain.Entities
|
|||||||
public class ECustomer
|
public class ECustomer
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
[Required(ErrorMessage = "Debe ingresar un nombre.")]
|
||||||
public string? Name { get; set; }
|
public string? Name { get; set; }
|
||||||
|
[Required(ErrorMessage = "Debe ingresar una razon social.")]
|
||||||
public string? BusinessName { get; set; }
|
public string? BusinessName { get; set; }
|
||||||
|
[Required(ErrorMessage = "Debe seleccionar un tipo de cuenta.")]
|
||||||
public int? AccounttypesId { get; set; }
|
public int? AccounttypesId { get; set; }
|
||||||
|
[Required(ErrorMessage = "Debe seleccionar un condicion.")]
|
||||||
public int? TaxConditionId { get; set; }
|
public int? TaxConditionId { get; set; }
|
||||||
|
|
||||||
public bool HasCreditAccount { get; set; }
|
public bool HasCreditAccount { get; set; }
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -10,7 +11,9 @@ namespace Domain.Entities
|
|||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
public int CustomersId { get; set; }
|
public int CustomersId { get; set; }
|
||||||
|
[Required(ErrorMessage = "Debe un nombre de sucursal/ubicacion.")]
|
||||||
public string? BusinessName { get; set; }
|
public string? BusinessName { get; set; }
|
||||||
|
[Required(ErrorMessage = "Debe ingresar una direccion valida.")]
|
||||||
public string? Streetaddress1 { get; set; }
|
public string? Streetaddress1 { get; set; }
|
||||||
public string? Streetaddress2 { get; set; }
|
public string? Streetaddress2 { get; set; }
|
||||||
public string? City { get; set; }
|
public string? City { get; set; }
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel.DataAnnotations;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@ -9,11 +10,10 @@ namespace Domain.Entities
|
|||||||
public class ECustomerDocument
|
public class ECustomerDocument
|
||||||
{
|
{
|
||||||
public int Id { get; set; }
|
public int Id { get; set; }
|
||||||
|
|
||||||
public int CustomersId { get; set; }
|
public int CustomersId { get; set; }
|
||||||
|
[Required(ErrorMessage = "Debe seleccionar un tipo de documento.")]
|
||||||
public int DocumenttypesId { get; set; }
|
public int DocumenttypesId { get; set; }
|
||||||
|
[Required(ErrorMessage = "Debe seleccionar un numero documento.")]
|
||||||
public string DocumentNumber { get; set; } = null!;
|
public string DocumentNumber { get; set; } = null!;
|
||||||
|
|
||||||
public DateOnly? IssueDate { get; set; }
|
public DateOnly? IssueDate { get; set; }
|
||||||
|
|||||||
@ -65,7 +65,21 @@ namespace Models.Helpers
|
|||||||
|
|
||||||
return destination;
|
return destination;
|
||||||
}
|
}
|
||||||
|
public static void MapEntityToExisting<TSource, TTarget>(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)
|
private static bool IsGenericCollection(Type type)
|
||||||
{
|
{
|
||||||
if (!type.IsGenericType) return false;
|
if (!type.IsGenericType) return false;
|
||||||
|
|||||||
@ -11,7 +11,7 @@ namespace Models.Interfaces
|
|||||||
{
|
{
|
||||||
public interface IPhSCustomerRepository
|
public interface IPhSCustomerRepository
|
||||||
{
|
{
|
||||||
Task<ECustomer> AddAsync(ECustomer entity);
|
Task<ECustomer> CreateAsync(ECustomer entity);
|
||||||
Task<bool> DeleteAsync(int id);
|
Task<bool> DeleteAsync(int id);
|
||||||
Task<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50);
|
Task<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50);
|
||||||
Task<ECustomer?> GetByIdAsync(int id);
|
Task<ECustomer?> GetByIdAsync(int id);
|
||||||
|
|||||||
@ -13,8 +13,6 @@ namespace Models.Repositories
|
|||||||
{
|
{
|
||||||
#region Declaraciones y Constructor
|
#region Declaraciones y Constructor
|
||||||
private readonly PhronCareOperationsHubContext _context = context;
|
private readonly PhronCareOperationsHubContext _context = context;
|
||||||
private readonly ILogger<PhSCustomerRepository> _logger = logger;
|
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
public async Task<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50)
|
public async Task<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50)
|
||||||
{
|
{
|
||||||
@ -34,7 +32,6 @@ namespace Models.Repositories
|
|||||||
PageSize = pagedEntities.PageSize
|
PageSize = pagedEntities.PageSize
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<ECustomer?> GetByIdAsync(int id)
|
public async Task<ECustomer?> GetByIdAsync(int id)
|
||||||
{
|
{
|
||||||
var customer = await _context.PhSCustomers
|
var customer = await _context.PhSCustomers
|
||||||
@ -89,22 +86,87 @@ namespace Models.Repositories
|
|||||||
PageSize = pagedEntities.PageSize
|
PageSize = pagedEntities.PageSize
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
public async Task<ECustomer> CreateAsync(ECustomer entity)
|
||||||
public async Task<ECustomer> AddAsync(ECustomer entity)
|
|
||||||
{
|
{
|
||||||
var customer = EntityMapper.MapEntity<ECustomer, PhSCustomer>(entity);
|
if (entity == null)
|
||||||
await _context.PhSCustomers.AddAsync(customer);
|
{
|
||||||
await _context.SaveChangesAsync();
|
throw new ArgumentNullException(nameof(entity), "El cliente no puede ser nulo.");
|
||||||
return EntityMapper.MapEntity<PhSCustomer, ECustomer>(customer);
|
}
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var customer = EntityMapper.MapEntity<ECustomer, PhSCustomer>(entity);
|
||||||
|
// Mapeo de direcciones
|
||||||
|
foreach (var address in entity.PhSCustomerAddresses)
|
||||||
|
{
|
||||||
|
var mappedAddress = EntityMapper.MapEntity<ECustomerAddress, PhSCustomerAddress>(address);
|
||||||
|
customer.PhSCustomerAddresses.Add(mappedAddress);
|
||||||
|
}
|
||||||
|
// Mapeo de documentos
|
||||||
|
foreach (var doc in entity.PhSCustomerDocuments)
|
||||||
|
{
|
||||||
|
var mappedDoc = EntityMapper.MapEntity<ECustomerDocument, PhSCustomerDocument>(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<PhSCustomer, ECustomer>(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<bool> UpdateAsync(ECustomer entity)
|
public async Task<bool> UpdateAsync(ECustomer entity)
|
||||||
{
|
{
|
||||||
var customer = await _context.PhSCustomers.FindAsync(entity.Id);
|
if (entity == null)
|
||||||
if (customer == null) return false;
|
throw new ArgumentNullException(nameof(entity));
|
||||||
|
|
||||||
_context.Entry(customer).CurrentValues.SetValues(entity);
|
try
|
||||||
await _context.SaveChangesAsync();
|
{
|
||||||
return true;
|
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<ECustomerAddress, PhSCustomerAddress>(address);
|
||||||
|
existingCustomer.PhSCustomerAddresses.Add(mappedAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
_context.PhSCustomerDocuments.RemoveRange(existingCustomer.PhSCustomerDocuments);
|
||||||
|
existingCustomer.PhSCustomerDocuments.Clear();
|
||||||
|
|
||||||
|
foreach (var doc in entity.PhSCustomerDocuments)
|
||||||
|
{
|
||||||
|
var mappedDoc = EntityMapper.MapEntity<ECustomerDocument, PhSCustomerDocument>(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<bool> DeleteAsync(int id)
|
public async Task<bool> DeleteAsync(int id)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
using Core.Interfaces;
|
using Core.Interfaces;
|
||||||
|
using Domain.Entities;
|
||||||
using Microsoft.AspNetCore.Http;
|
using Microsoft.AspNetCore.Http;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
@ -14,6 +15,7 @@ namespace phronCare.API.Controllers.Sales
|
|||||||
{
|
{
|
||||||
_customerService = customerService ?? throw new ArgumentNullException(nameof(customerService));
|
_customerService = customerService ?? throw new ArgumentNullException(nameof(customerService));
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("all")]
|
[HttpGet("all")]
|
||||||
public async Task<IActionResult> GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 50)
|
public async Task<IActionResult> 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}");
|
return StatusCode(500, $"{methodName} Message: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("search")]
|
[HttpGet("search")]
|
||||||
public async Task<IActionResult> Search(
|
public async Task<IActionResult> Search(
|
||||||
[FromQuery] string? name,
|
[FromQuery] string? name,
|
||||||
@ -47,20 +50,67 @@ namespace phronCare.API.Controllers.Sales
|
|||||||
return StatusCode(500, $"{methodName} Message: {ex.Message}");
|
return StatusCode(500, $"{methodName} Message: {ex.Message}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//[HttpGet("search")]
|
[HttpGet("{id:int}")]
|
||||||
//public async Task<IActionResult> Search([FromQuery] string? name, [FromQuery] string? email, [FromQuery] string? document)
|
public async Task<ActionResult<ECustomer>> GetById(int id)
|
||||||
//{
|
{
|
||||||
// try
|
try
|
||||||
// {
|
{
|
||||||
// var result = await _customerService.SearchAsync(name, email, document);
|
var customer = await _customerService.GetByIdAsync(id);
|
||||||
// return Ok(result);
|
if (customer == null)
|
||||||
// }
|
return NotFound();
|
||||||
// catch (Exception ex)
|
|
||||||
// {
|
|
||||||
// var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod";
|
|
||||||
// return StatusCode(500, $"{methodName} Message: {ex.Message}");
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
return Ok(customer);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return StatusCode(500, $"Error: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
[HttpPost("create")]
|
||||||
|
public async Task<IActionResult> 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<IActionResult> 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}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -141,6 +141,32 @@
|
|||||||
],
|
],
|
||||||
"ReturnTypes": []
|
"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",
|
"ContainingType": "phronCare.API.Controllers.AuthenticationController",
|
||||||
"Method": "ConfirmEmail",
|
"Method": "ConfirmEmail",
|
||||||
@ -278,6 +304,121 @@
|
|||||||
],
|
],
|
||||||
"ReturnTypes": []
|
"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",
|
"ContainingType": "phronCare.API.Controllers.DbTestController",
|
||||||
"Method": "TestEdmxConnection",
|
"Method": "TestEdmxConnection",
|
||||||
@ -288,6 +429,58 @@
|
|||||||
"Parameters": [],
|
"Parameters": [],
|
||||||
"ReturnTypes": []
|
"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",
|
"ContainingType": "phronCare.API.Controllers.TestController",
|
||||||
"Method": "GetAdministradores",
|
"Method": "GetAdministradores",
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
@page "/sales/customerform"
|
@page "/sales/customerform"
|
||||||
@page "/sales/customerform/{CustomerId:int}"
|
@page "/sales/customerform/{CustomerId:int}"
|
||||||
|
@using System.ComponentModel.DataAnnotations
|
||||||
|
@using phronCare.UIBlazor.Pages.Shared.Modals
|
||||||
@using phronCare.UIBlazor.Services.Sales
|
@using phronCare.UIBlazor.Services.Sales
|
||||||
|
@inject IModalService Modal
|
||||||
@inject HttpClient _httpClient
|
@inject HttpClient _httpClient
|
||||||
@inject NavigationManager Navigation
|
@inject NavigationManager Navigation
|
||||||
@inject IToastService toastService
|
@inject IToastService toastService
|
||||||
@ -9,216 +11,222 @@
|
|||||||
@inject AccountTypeService accountTypeService
|
@inject AccountTypeService accountTypeService
|
||||||
@inject TaxConditionService taxConditionService
|
@inject TaxConditionService taxConditionService
|
||||||
|
|
||||||
|
<div class="card " style="zoom:70%">
|
||||||
<EditForm Model="@customer" OnValidSubmit="@HandleValidSubmit">
|
<div class="card-header">
|
||||||
<DataAnnotationsValidator />
|
<h3 class="card-title">Formulario: cliente</h3>
|
||||||
<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>
|
||||||
|
<div class="card-body">
|
||||||
<div class="row">
|
<EditForm Model="@customer" OnValidSubmit="@HandleValidSubmit">
|
||||||
<div class="col-md-6">
|
<DataAnnotationsValidator />
|
||||||
<label for="AccounttypesId">Tipo de Cuenta:</label>
|
<ValidationSummary />
|
||||||
<InputSelect id="AccounttypesId" @bind-Value="customer.AccounttypesId" class="form-control">
|
<div class="row">
|
||||||
<option value="">-- Seleccionar --</option>
|
<div class="col-md-6">
|
||||||
@foreach (var type in accountTypes)
|
<label for="Name">Nombre / Razón Social:</label>
|
||||||
{
|
<InputText id="Name" @bind-Value="customer.Name" class="form-control" />
|
||||||
<option value="@type.Id">@type.Name</option>
|
</div>
|
||||||
}
|
<div class="col-md-6">
|
||||||
</InputSelect>
|
<label for="BusinessName">Sucursal / Nombre Comercial:</label>
|
||||||
</div>
|
<InputText id="BusinessName" @bind-Value="customer.BusinessName" class="form-control" />
|
||||||
<div class="col-md-6">
|
</div>
|
||||||
<label for="TaxConditionId">Condición Fiscal:</label>
|
</div>
|
||||||
<InputSelect id="TaxConditionId" @bind-Value="customer.TaxConditionId" class="form-control">
|
<div class="row">
|
||||||
<option value="">-- Seleccionar --</option>
|
<div class="col-md-6">
|
||||||
@foreach (var tax in taxConditions)
|
<label for="AccounttypesId">Tipo de Cuenta:</label>
|
||||||
{
|
<InputSelect id="AccounttypesId" @bind-Value="customer.AccounttypesId" class="form-control">
|
||||||
<option value="@tax.Id">@tax.Description</option>
|
<option value="">-- Seleccionar --</option>
|
||||||
}
|
@foreach (var type in accountTypes)
|
||||||
</InputSelect>
|
{
|
||||||
</div>
|
<option value="@type.Id">@type.Name</option>
|
||||||
</div>
|
}
|
||||||
|
</InputSelect>
|
||||||
<div class="row">
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-6">
|
||||||
<label for="HasCreditAccount">¿Cuenta Corriente?</label><br />
|
<label for="TaxConditionId">Condición Fiscal:</label>
|
||||||
<InputCheckbox id="HasCreditAccount" @bind-Value="customer.HasCreditAccount" />
|
<InputSelect id="TaxConditionId" @bind-Value="customer.TaxConditionId" class="form-control">
|
||||||
</div>
|
<option value="">-- Seleccionar --</option>
|
||||||
<div class="col-md-4">
|
@foreach (var tax in taxConditions)
|
||||||
<label for="CreditLimit">Límite de Crédito:</label>
|
{
|
||||||
<InputNumber id="CreditLimit" @bind-Value="customer.CreditLimit" class="form-control" />
|
<option value="@tax.Id">@tax.Description</option>
|
||||||
</div>
|
}
|
||||||
<div class="col-md-4">
|
</InputSelect>
|
||||||
<label for="Active">Activo:</label><br />
|
</div>
|
||||||
<InputCheckbox id="Active" @bind-Value="customer.Active" />
|
</div>
|
||||||
</div>
|
<div class="row">
|
||||||
</div>
|
<div class="col-md-4">
|
||||||
<hr />
|
<label for="HasCreditAccount">¿Cuenta Corriente?</label><br />
|
||||||
<h5>Documentos</h5>
|
<InputCheckbox id="HasCreditAccount" @bind-Value="customer.HasCreditAccount" />
|
||||||
|
</div>
|
||||||
<div class="row align-items-end">
|
<div class="col-md-4">
|
||||||
<div class="col-sm-4">
|
<label for="CreditLimit">Límite de Crédito:</label>
|
||||||
<label for="TipoDocumento">Tipo:</label>
|
<InputNumber id="CreditLimit" @bind-Value="customer.CreditLimit" class="form-control" />
|
||||||
<InputSelect id="TipoDocumento" class="form-control" @bind-Value="documentFormModel.DocumenttypesId">
|
</div>
|
||||||
<option value="">Seleccione</option>
|
<div class="col-md-4">
|
||||||
@foreach (var tipo in documentTypes)
|
<label for="Active">Activo:</label><br />
|
||||||
{
|
<InputCheckbox id="Active" @bind-Value="customer.Active" />
|
||||||
<option value="@tipo.Id">@tipo.Name</option>
|
</div>
|
||||||
}
|
</div>
|
||||||
</InputSelect>
|
<hr />
|
||||||
</div>
|
<h5>Documentos</h5>
|
||||||
<div class="col-sm-4">
|
<div class="row align-items-end">
|
||||||
<label for="NumeroDocumento">Número:</label>
|
<div class="col-sm-4">
|
||||||
<InputText id="NumeroDocumento" class="form-control" @bind-Value="documentFormModel.DocumentNumber" />
|
<label for="TipoDocumento">Tipo:</label>
|
||||||
</div>
|
<InputSelect id="TipoDocumento" class="form-control" @bind-Value="documentFormModel.DocumenttypesId">
|
||||||
<div class="col-sm-2">
|
<option value="">Seleccione</option>
|
||||||
<button type="button" class="btn btn-success" @onclick="AddCustomerDocument">Agregar</button>
|
@foreach (var tipo in documentTypes)
|
||||||
</div>
|
{
|
||||||
</div>
|
<option value="@tipo.Id">@tipo.Name</option>
|
||||||
|
}
|
||||||
<br />
|
</InputSelect>
|
||||||
|
</div>
|
||||||
@if (customer.PhSCustomerDocuments?.Any() == true)
|
<div class="col-sm-4">
|
||||||
{
|
<label for="NumeroDocumento">Número:</label>
|
||||||
<table class="table table-sm table-bordered">
|
<InputText id="NumeroDocumento" class="form-control" @bind-Value="documentFormModel.DocumentNumber" />
|
||||||
<thead>
|
</div>
|
||||||
<tr>
|
<div class="col-sm-2">
|
||||||
<th>Tipo</th>
|
<button type="button" class="btn btn-success" @onclick="AddCustomerDocument">Agregar</button>
|
||||||
<th>Número</th>
|
</div>
|
||||||
<th style="width:50px;"></th>
|
</div>
|
||||||
</tr>
|
<br />
|
||||||
</thead>
|
@if (customer.PhSCustomerDocuments?.Any() == true)
|
||||||
<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">
|
<table class="table table-sm table-bordered">
|
||||||
<option value="">Seleccionar provincia</option>
|
<thead>
|
||||||
@foreach (var provincia in provincias)
|
<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 type="button" class="btn btn-sm btn-danger" @onclick="() => RemoveCustomerDocument(doc)">🗑</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
<hr />
|
||||||
|
<h5>Direcciones</h5>
|
||||||
|
<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))
|
||||||
{
|
{
|
||||||
<option value="@provincia">@provincia</option>
|
<select class="form-control" @bind="editingAddress.Stateprovince">
|
||||||
|
<option value="">Seleccionar provincia</option>
|
||||||
|
@foreach (var provincia in provincias)
|
||||||
|
{
|
||||||
|
<option value="@provincia">@provincia</option>
|
||||||
|
}
|
||||||
|
</select>
|
||||||
}
|
}
|
||||||
</select>
|
else
|
||||||
}
|
{
|
||||||
else
|
<input class="form-control" placeholder="Estado/Provincia" @bind="editingAddress.Stateprovince" />
|
||||||
{
|
}
|
||||||
<input class="form-control" placeholder="Estado/Provincia" @bind="editingAddress.Stateprovince" />
|
</div>
|
||||||
}
|
</div>
|
||||||
</div>
|
<div class="row mb-3">
|
||||||
</div>
|
<div class="col-md-4">
|
||||||
|
<input class="form-control" placeholder="Código Postal" @bind="editingAddress.Postalcode" />
|
||||||
<div class="row mb-3">
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<input class="form-control" placeholder="Código Postal" @bind="editingAddress.Postalcode" />
|
<input class="form-control" placeholder="Teléfono" @bind="editingAddress.Phonenumber" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-md-4">
|
||||||
<input class="form-control" placeholder="Teléfono" @bind="editingAddress.Phonenumber" />
|
<input class="form-control" placeholder="Email" @bind="editingAddress.Email" />
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
</div>
|
||||||
<input class="form-control" placeholder="Email" @bind="editingAddress.Email" />
|
<div class="row mb-3">
|
||||||
</div>
|
<div class="col-md-12">
|
||||||
</div>
|
<textarea class="form-control" placeholder="Notas" @bind="editingAddress.Notes"></textarea>
|
||||||
|
</div>
|
||||||
<div class="row mb-3">
|
</div>
|
||||||
<div class="col-md-12">
|
<div class="mb-3">
|
||||||
<textarea class="form-control" placeholder="Notas" @bind="editingAddress.Notes"></textarea>
|
<button type="button" class="btn btn-sm btn-success" @onclick="AddOrUpdateAddress">
|
||||||
</div>
|
@((editingIndex == -1) ? "Agregar dirección" : "Actualizar dirección")
|
||||||
</div>
|
</button>
|
||||||
|
@if (editingIndex != -1)
|
||||||
<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>
|
<button type="button" class="btn btn-sm btn-secondary ms-2" @onclick="CancelAddressEdit">Cancelar</button>
|
||||||
<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>
|
</div>
|
||||||
</table>
|
|
||||||
}
|
@if (customer.PhSCustomerAddresses.Any())
|
||||||
</EditForm>
|
{
|
||||||
|
<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 type="button" class="btn btn-sm btn-primary me-1" @onclick="() => EditAddress(address.index)">Editar</button>
|
||||||
|
<button type="button" class="btn btn-sm btn-danger" @onclick="() => RemoveAddress(address.index)">Eliminar</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
}
|
||||||
|
</EditForm>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<div class="mt-4">
|
||||||
|
<button class="btn btn-primary" type="button" @onclick="HandleValidSubmit" disabled="@isSaving">
|
||||||
|
@(isSaving ? "Guardando..." : "Guardar Cliente")
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
@code {
|
@code {
|
||||||
[Parameter]
|
[Parameter]
|
||||||
@ -229,6 +237,7 @@
|
|||||||
private List<ETaxCondition> taxConditions = new();
|
private List<ETaxCondition> taxConditions = new();
|
||||||
private List<EDocumentType> documentTypes = new();
|
private List<EDocumentType> documentTypes = new();
|
||||||
private ECustomerDocument documentFormModel = new();
|
private ECustomerDocument documentFormModel = new();
|
||||||
|
private bool isSaving = false;
|
||||||
|
|
||||||
private string returnUrl = "/sales/customers";
|
private string returnUrl = "/sales/customers";
|
||||||
|
|
||||||
@ -262,6 +271,18 @@
|
|||||||
|
|
||||||
private void AddOrUpdateAddress()
|
private void AddOrUpdateAddress()
|
||||||
{
|
{
|
||||||
|
var context = new ValidationContext(editingAddress, null, null);
|
||||||
|
var results = new List<ValidationResult>();
|
||||||
|
|
||||||
|
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)
|
if (editingIndex == -1)
|
||||||
{
|
{
|
||||||
// Agregar nueva dirección
|
// Agregar nueva dirección
|
||||||
@ -332,7 +353,6 @@
|
|||||||
editingIndex = -1;
|
editingIndex = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected override async Task OnInitializedAsync()
|
protected override async Task OnInitializedAsync()
|
||||||
{
|
{
|
||||||
await LoadAccountTypes();
|
await LoadAccountTypes();
|
||||||
@ -342,7 +362,7 @@
|
|||||||
if (CustomerId.HasValue)
|
if (CustomerId.HasValue)
|
||||||
{
|
{
|
||||||
// Cargar datos del cliente existente desde la API
|
// Cargar datos del cliente existente desde la API
|
||||||
customer = await _httpClient.GetFromJsonAsync<ECustomer>($"/api/Customer/GetById/{CustomerId.Value}") ?? new();
|
customer = await _httpClient.GetFromJsonAsync<ECustomer>($"/api/Customer/{CustomerId.Value}") ?? new();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -372,7 +392,6 @@
|
|||||||
{
|
{
|
||||||
customer.PhSCustomerDocuments.Remove(document);
|
customer.PhSCustomerDocuments.Remove(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void RemoveCustomerAddress(ECustomerAddress address)
|
private void RemoveCustomerAddress(ECustomerAddress address)
|
||||||
{
|
{
|
||||||
customer.PhSCustomerAddresses.Remove(address);
|
customer.PhSCustomerAddresses.Remove(address);
|
||||||
@ -380,6 +399,14 @@
|
|||||||
|
|
||||||
private async Task HandleValidSubmit()
|
private async Task HandleValidSubmit()
|
||||||
{
|
{
|
||||||
|
var parameters = new ModalParameters();
|
||||||
|
parameters.Add("Message", "¿Desea guardar los cambios del cliente?");
|
||||||
|
|
||||||
|
var modal = Modal.Show<ConfirmModal>("Confirmacion", parameters);
|
||||||
|
var result = await modal.Result;
|
||||||
|
|
||||||
|
if (result.Cancelled)
|
||||||
|
return;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
HttpResponseMessage response;
|
HttpResponseMessage response;
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<h3 class="card-title">Listado de clientes</h3> @* wtf? *@
|
<h3 class="card-title">Listado de clientes</h3> @* wtf? *@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body" style="zoom:70%;">
|
||||||
<div class="mb-4 space-y-2">
|
<div class="mb-4 space-y-2">
|
||||||
<input @bind="SearchParams.Name" placeholder="Nombre" class="border rounded p-1 w-full" />
|
<input @bind="SearchParams.Name" placeholder="Nombre" class="border rounded p-1 w-full" />
|
||||||
<input @bind="SearchParams.Email" placeholder="Email" class="border rounded p-1 w-full" />
|
<input @bind="SearchParams.Email" placeholder="Email" class="border rounded p-1 w-full" />
|
||||||
@ -118,10 +118,27 @@
|
|||||||
// var filename = $"Tickets_{Group}_{currentDate}.xlsx";
|
// var filename = $"Tickets_{Group}_{currentDate}.xlsx";
|
||||||
// await js.InvokeAsync<object>("saveAsFile", filename, Convert.ToBase64String(fileBytes));
|
// await js.InvokeAsync<object>("saveAsFile", filename, Convert.ToBase64String(fileBytes));
|
||||||
}
|
}
|
||||||
List<PhTable.ButtonOptions> botones = new List<PhTable.ButtonOptions>
|
|
||||||
|
List<PhTable.ButtonOptions> botones = new();
|
||||||
|
protected override void OnInitialized()
|
||||||
{
|
{
|
||||||
new PhTable.ButtonOptions{ Caption="Editar", ElementClass="btn btn-primary btn-sm"}
|
botones = new List<PhTable.ButtonOptions>
|
||||||
};
|
{
|
||||||
|
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 :
|
private int TotalPaginas => PagedResult is null ? 1 :
|
||||||
(int)Math.Ceiling((double)(PagedResult.TotalItems) / SearchParams.PageSize);
|
(int)Math.Ceiling((double)(PagedResult.TotalItems) / SearchParams.PageSize);
|
||||||
private bool PuedeAvanzar => PagedResult != null && SearchParams.Page < TotalPaginas;
|
private bool PuedeAvanzar => PagedResult != null && SearchParams.Page < TotalPaginas;
|
||||||
|
|||||||
30
phronCare.UIBlazor/Pages/Shared/Modals/ConfirmModal.razor
Normal file
30
phronCare.UIBlazor/Pages/Shared/Modals/ConfirmModal.razor
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
@using Blazored.Modal
|
||||||
|
@using Blazored.Modal.Services
|
||||||
|
@inherits LayoutComponentBase
|
||||||
|
|
||||||
|
<div class="modal-body">
|
||||||
|
<h5>@Title</h5>
|
||||||
|
<p>@Message</p>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="btn btn-secondary" @onclick="Cancel">Cancelar</button>
|
||||||
|
<button class="btn btn-primary" @onclick="Confirm">Confirmar</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
x
Reference in New Issue
Block a user