From 862348822106db1f74d1b5e328a21a3df6cc8f26 Mon Sep 17 00:00:00 2001 From: Leandro Hernan Rojas Date: Sun, 20 Apr 2025 19:58:17 -0300 Subject: [PATCH] Update ADD Patients y Institutions Models in API --- Core/Interfaces/IInstitutionDom.cs | 21 ++ Core/Interfaces/IPatientDom.cs | 18 ++ Core/Services/InstitutionService.cs | 124 +++++++++ Core/Services/PatientService.cs | 130 +++++++++ Domain/Entities/EInstitution.cs | 20 ++ Domain/Entities/EPatient.cs | 24 ++ Domain/Entities/EProduct.cs | 9 +- Domain/Generics/InstitutionSearchParams.cs | 9 + Domain/Generics/PatientSearchParams .cs | 10 + Domain/obj/Domain.csproj.nuget.g.props | 2 +- .../Interfaces/IPhSInstitutionRepository.cs | 19 ++ Models/Interfaces/IPhSPatientRepository.cs | 20 ++ Models/Models/PhSBusinessUnit.cs | 5 +- Models/Models/PhSCustomer.cs | 2 + Models/Models/PhSDocumentType.cs | 2 + Models/Models/PhSInstitution.cs | 33 +++ Models/Models/PhSPatient.cs | 41 +++ Models/Models/PhSProductCategory.cs | 5 +- Models/Models/PhSQuoteDetail.cs | 5 +- .../Models/PhronCareOperationsHubContext.cs | 98 ++++++- Models/Repositories/PhSCustomerRepository.cs | 2 + .../Repositories/PhSInstitutionReposotory.cs | 111 ++++++++ Models/Repositories/PhSPatientRepository .cs | 133 +++++++++ Models/obj/Models.csproj.nuget.g.props | 2 +- .../Controllers/InstitutionController.cs | 130 +++++++++ .../Controllers/Sales/PatientController.cs | 135 +++++++++ phronCare.API/Program.cs | 6 + .../obj/Debug/net8.0/ApiEndpoints.json | 257 ++++++++++++++++++ .../Pages/Sales/CustomerForm.razor | 174 ++++++------ .../Pages/Sales/ProductForm.razor | 3 +- 30 files changed, 1454 insertions(+), 96 deletions(-) create mode 100644 Core/Interfaces/IInstitutionDom.cs create mode 100644 Core/Interfaces/IPatientDom.cs create mode 100644 Core/Services/InstitutionService.cs create mode 100644 Core/Services/PatientService.cs create mode 100644 Domain/Entities/EInstitution.cs create mode 100644 Domain/Entities/EPatient.cs create mode 100644 Domain/Generics/InstitutionSearchParams.cs create mode 100644 Domain/Generics/PatientSearchParams .cs create mode 100644 Models/Interfaces/IPhSInstitutionRepository.cs create mode 100644 Models/Interfaces/IPhSPatientRepository.cs create mode 100644 Models/Models/PhSInstitution.cs create mode 100644 Models/Models/PhSPatient.cs create mode 100644 Models/Repositories/PhSInstitutionReposotory.cs create mode 100644 Models/Repositories/PhSPatientRepository .cs create mode 100644 phronCare.API/Controllers/InstitutionController.cs create mode 100644 phronCare.API/Controllers/Sales/PatientController.cs diff --git a/Core/Interfaces/IInstitutionDom.cs b/Core/Interfaces/IInstitutionDom.cs new file mode 100644 index 0000000..c954f7c --- /dev/null +++ b/Core/Interfaces/IInstitutionDom.cs @@ -0,0 +1,21 @@ +using Domain.Entities; +using Domain.Generics; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Core.Interfaces +{ + public interface IInstitutionDom + { + Task CreateAsync(EInstitution entity); + Task DeleteAsync(int id); + Task ExportFilteredInstitutionsToExcelAsync(InstitutionSearchParams searchParams); + Task> GetAllAsync(int page = 1, int pageSize = 50); + Task GetByIdAsync(int id); + Task> SearchAsync(string? name, string? city, string? province, int page = 1, int pageSize = 50); + Task UpdateAsync(EInstitution entity); + } +} diff --git a/Core/Interfaces/IPatientDom.cs b/Core/Interfaces/IPatientDom.cs new file mode 100644 index 0000000..cff4186 --- /dev/null +++ b/Core/Interfaces/IPatientDom.cs @@ -0,0 +1,18 @@ +using Domain.Entities; +using Domain.Generics; +using Domain.SearchParams; + +namespace Core.Interfaces +{ + public interface IPatientDom + { + Task CreateAsync(EPatient entity); + Task DeleteAsync(int id); + Task ExportFilteredPatientsToExcelAsync(PatientSearchParams searchParams); + Task> GetAllAsync(int page = 1, int pageSize = 50); + Task GetByIdAsync(int id); + Task> SearchAsync(string? name, string? document, int page = 1, int pageSize = 50); + Task UpdateAsync(EPatient entity); + + } +} diff --git a/Core/Services/InstitutionService.cs b/Core/Services/InstitutionService.cs new file mode 100644 index 0000000..4755365 --- /dev/null +++ b/Core/Services/InstitutionService.cs @@ -0,0 +1,124 @@ +using Core.Interfaces; +using Domain.Entities; +using Domain.Generics; +using Models.Interfaces; +using System.Reflection; +using Transversal.Services; + +namespace Core.Services +{ + public class InstitutionService : IInstitutionDom + { + #region Declaraciones y Constructor + private readonly IPhSInstitutionRepository _repository; + public InstitutionService(IPhSInstitutionRepository repository) + { + _repository = repository ?? throw new ArgumentNullException(nameof(repository)); + } + #endregion + #region Métodos + public async Task> GetAllAsync(int page = 1, int pageSize = 50) + { + try + { + return await _repository.GetAllAsync(page, pageSize); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } + } + public async Task GetByIdAsync(int id) + { + 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(EInstitution entity) + { + if (entity is null) + throw new ArgumentNullException(nameof(entity), "La institución no puede ser nula."); + + if (string.IsNullOrWhiteSpace(entity.Name) ) + throw new ArgumentException("Debe completar el nombre de la institución."); + + if (string.IsNullOrWhiteSpace(entity.Type)) + throw new ArgumentException("Debe seleccionar un tipo de institución."); + + return await _repository.CreateAsync(entity); + } + public async Task UpdateAsync(EInstitution entity) + { + if (entity is null || entity.Id <= 0) + throw new ArgumentException("La institución es inválida o no tiene un ID válido."); + + if (string.IsNullOrWhiteSpace(entity.Name)) + throw new ArgumentException("Debe completar el nombre de la institución."); + + if (string.IsNullOrWhiteSpace(entity.Type)) + throw new ArgumentException("Debe seleccionar un tipo de institución."); + return await _repository.UpdateAsync(entity); + } + public async Task> SearchAsync(string? name, string? city, string? province, int page = 1, int pageSize = 50) + { + try + { + return await _repository.SearchAsync(name, city, province, page, pageSize); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } + } + public Task DeleteAsync(int id) + { + throw new NotImplementedException(); + } + public async Task ExportFilteredInstitutionsToExcelAsync(InstitutionSearchParams searchParams) + { + try + { + var searchResult = await SearchAsync( + searchParams.Name, + searchParams.City, + searchParams.Province, + searchParams.Page, + searchParams.PageSize + ); + + if (searchResult?.Items is null || !searchResult.Items.Any()) + throw new Exception("No se encontraron instituciones para exportar."); + + var stream = new XLSXExportBase(); + + var data = searchResult.Items.Select(i => new + { + i.Id, + i.Name, + i.Type, + i.City, + i.Province, + i.Email, + i.Phone, + i.Isactive + }).ToList(); + + return stream.ExportExcel(data); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } + } + #endregion + } +} diff --git a/Core/Services/PatientService.cs b/Core/Services/PatientService.cs new file mode 100644 index 0000000..fc34ef4 --- /dev/null +++ b/Core/Services/PatientService.cs @@ -0,0 +1,130 @@ +using Core.Interfaces; +using Domain.Entities; +using Domain.Generics; +using Domain.SearchParams; +using Models.Interfaces; +using System.Reflection; +using Transversal.Services; + +public class PatientService : IPatientDom +{ + #region Declaraciones y Constructor + private readonly IPhSPatientRepository _repository; + public PatientService(IPhSPatientRepository patientRepository) + { + _repository = patientRepository ?? throw new ArgumentNullException(nameof(patientRepository)); + } + #endregion + #region Métodos de servicio + public async Task> GetAllAsync(int page = 1, int pageSize = 50) + { + try + { + return await _repository.GetAllAsync(page, pageSize); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } + } + public async Task GetByIdAsync(int id) + { + 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(EPatient entity) + { + if (entity is null) + throw new ArgumentNullException(nameof(entity), "El paciente no puede ser nulo."); + + if (string.IsNullOrWhiteSpace(entity.Firstname) || string.IsNullOrWhiteSpace(entity.Lastname)) + throw new ArgumentException("Debe completar el nombre y apellido del paciente."); + + if (string.IsNullOrWhiteSpace(entity.DocumentNumber)) + throw new ArgumentException("Debe completar el número de documento del paciente."); + + return await _repository.CreateAsync(entity); + } + public async Task UpdateAsync(EPatient entity) + { + if (entity is null) + throw new ArgumentNullException(nameof(entity), "El paciente no puede ser nulo."); + + if (string.IsNullOrWhiteSpace(entity.Firstname) || string.IsNullOrWhiteSpace(entity.Lastname)) + throw new ArgumentException("Debe completar el nombre y apellido del paciente."); + + if (string.IsNullOrWhiteSpace(entity.DocumentNumber)) + throw new ArgumentException("Debe completar el número de documento del paciente."); + + return await _repository.UpdateAsync(entity); + } + + public async Task> SearchAsync(string? name, string? document, int page = 1, int pageSize = 50) + { + try + { + return await _repository.SearchAsync(name, document, page, pageSize); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } + } + + public Task DeleteAsync(int id) + { + // Implementar según políticas del sistema (soft delete, etc.) + throw new NotImplementedException(); + } + public async Task ExportFilteredPatientsToExcelAsync(PatientSearchParams searchParams) + { + try + { + var searchResult = await SearchAsync( + searchParams.Name, + searchParams.Document, + searchParams.Page, + searchParams.PageSize + ); + + if (searchResult?.Items is null || !searchResult.Items.Any()) + { + throw new Exception("No se encontraron pacientes para exportar."); + } + + var stream = new XLSXExportBase(); + + var patientData = searchResult.Items.Select(p => new + { + p.Id, + p.Firstname, + p.Lastname, + p.DocumentNumber, + p.AffiliateNumber, + p.Email, + p.Phone, + p.Birthdate, + p.Gender + }).ToList(); + + var excelFile = stream.ExportExcel(patientData); + return excelFile; + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} - Error al exportar pacientes: {ex.Message}", ex); + } + } + + #endregion +} diff --git a/Domain/Entities/EInstitution.cs b/Domain/Entities/EInstitution.cs new file mode 100644 index 0000000..d63c250 --- /dev/null +++ b/Domain/Entities/EInstitution.cs @@ -0,0 +1,20 @@ +namespace Domain.Entities +{ + public partial class EInstitution + { + public int Id { get; set; } + public string Name { get; set; } = null!; + public string Type { get; set; } = null!; + public string? Streetaddress { get; set; } + public string? City { get; set; } + public string? Province { get; set; } + public string? Phone { get; set; } + public string? Email { get; set; } + public string? Operatingroominfo { get; set; } + public DateTime Createdat { get; set; } + public bool Isactive { get; set; } + public double? Latitude { get; set; } + public double? Longitude { get; set; } + + } +} \ No newline at end of file diff --git a/Domain/Entities/EPatient.cs b/Domain/Entities/EPatient.cs new file mode 100644 index 0000000..e858c30 --- /dev/null +++ b/Domain/Entities/EPatient.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations; + +namespace Domain.Entities +{ + public class EPatient + { + public int Id { get; set; } + [Required(ErrorMessage = "Debe ingresar un nombre.")] + public string Firstname { get; set; } = null!; + public string Lastname { get; set; } = null!; + public int? DocumenttypesId { get; set; } + public string? DocumentNumber { get; set; } + public string? AffiliateNumber { get; set; } + public DateOnly? Birthdate { get; set; } + public string? Gender { get; set; } + public string? Phone { get; set; } + public string? Email { get; set; } + public string? Address { get; set; } + public string? Notes { get; set; } + public int? CustomerId { get; set; } + public DateTime Createdat { get; set; } + public DateTime? Modifiedat { get; set; } + } +} diff --git a/Domain/Entities/EProduct.cs b/Domain/Entities/EProduct.cs index 0a71a1b..a5c484e 100644 --- a/Domain/Entities/EProduct.cs +++ b/Domain/Entities/EProduct.cs @@ -1,13 +1,14 @@ -namespace Domain.Entities +using System.ComponentModel.DataAnnotations; + +namespace Domain.Entities { public class EProduct { public int Id { get; set; } - public int? BusinessunitsId { get; set; } - + [Required(ErrorMessage = "Debe ingresar un nombre.")] public string? Name { get; set; } - + [Required(ErrorMessage = "Debe ingresar una descripcion.")] public string Description { get; set; } = null!; public int? Categoryid { get; set; } diff --git a/Domain/Generics/InstitutionSearchParams.cs b/Domain/Generics/InstitutionSearchParams.cs new file mode 100644 index 0000000..3e0ced0 --- /dev/null +++ b/Domain/Generics/InstitutionSearchParams.cs @@ -0,0 +1,9 @@ +namespace Domain.Generics +{ + public class InstitutionSearchParams :PagedRequest + { + public string? Name { get; set; } + public string? City { get; set; } + public string? Province { get; set; } + } +} \ No newline at end of file diff --git a/Domain/Generics/PatientSearchParams .cs b/Domain/Generics/PatientSearchParams .cs new file mode 100644 index 0000000..119798e --- /dev/null +++ b/Domain/Generics/PatientSearchParams .cs @@ -0,0 +1,10 @@ +using Domain.Generics; + +namespace Domain.SearchParams +{ + public class PatientSearchParams : PagedRequest + { + public string? Name { get; set; } + public string? Document { get; set; } + } +} diff --git a/Domain/obj/Domain.csproj.nuget.g.props b/Domain/obj/Domain.csproj.nuget.g.props index 8b4eb7e..3efed38 100644 --- a/Domain/obj/Domain.csproj.nuget.g.props +++ b/Domain/obj/Domain.csproj.nuget.g.props @@ -7,7 +7,7 @@ $(UserProfile)\.nuget\packages\ C:\Users\maski\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages PackageReference - 6.13.2 + 6.13.1 diff --git a/Models/Interfaces/IPhSInstitutionRepository.cs b/Models/Interfaces/IPhSInstitutionRepository.cs new file mode 100644 index 0000000..612a011 --- /dev/null +++ b/Models/Interfaces/IPhSInstitutionRepository.cs @@ -0,0 +1,19 @@ +using Domain.Entities; +using Domain.Generics; + +namespace Models.Interfaces +{ + public interface IPhSInstitutionRepository + { + Task CreateAsync(EInstitution model); + Task> GetAllAsync(int page = 1, int pageSize = 50); + Task GetByIdAsync(int id); + Task> SearchAsync( + string? name, + string? city, + string? province, + int page = 1, + int pageSize = 50); + Task UpdateAsync(EInstitution model); + } +} diff --git a/Models/Interfaces/IPhSPatientRepository.cs b/Models/Interfaces/IPhSPatientRepository.cs new file mode 100644 index 0000000..d2022b0 --- /dev/null +++ b/Models/Interfaces/IPhSPatientRepository.cs @@ -0,0 +1,20 @@ +using Domain.Entities; +using Domain.Generics; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Models.Interfaces +{ + public interface IPhSPatientRepository + { + Task CreateAsync(EPatient entity); + Task DeleteAsync(int id); + Task> GetAllAsync(int page = 1, int pageSize = 50); + Task GetByIdAsync(int id); + Task> SearchAsync(string? name, string? document, int page = 1, int pageSize = 50); + Task UpdateAsync(EPatient entity); + } +} diff --git a/Models/Models/PhSBusinessUnit.cs b/Models/Models/PhSBusinessUnit.cs index 9f517b6..64f5e0f 100644 --- a/Models/Models/PhSBusinessUnit.cs +++ b/Models/Models/PhSBusinessUnit.cs @@ -1,4 +1,7 @@ -namespace Models.Models; +using System; +using System.Collections.Generic; + +namespace Models.Models; public partial class PhSBusinessUnit { diff --git a/Models/Models/PhSCustomer.cs b/Models/Models/PhSCustomer.cs index 7cd12cc..4dbea6a 100644 --- a/Models/Models/PhSCustomer.cs +++ b/Models/Models/PhSCustomer.cs @@ -29,6 +29,8 @@ public partial class PhSCustomer public virtual ICollection PhSCustomerDocuments { get; set; } = new List(); + public virtual ICollection PhSPatients { get; set; } = new List(); + public virtual ICollection PhSQuoteHeaders { get; set; } = new List(); public virtual PhOhTaxCondition? TaxCondition { get; set; } diff --git a/Models/Models/PhSDocumentType.cs b/Models/Models/PhSDocumentType.cs index 511ea3f..a666d64 100644 --- a/Models/Models/PhSDocumentType.cs +++ b/Models/Models/PhSDocumentType.cs @@ -14,4 +14,6 @@ public partial class PhSDocumentType public string? Description { get; set; } public virtual ICollection PhSCustomerDocuments { get; set; } = new List(); + + public virtual ICollection PhSPatients { get; set; } = new List(); } diff --git a/Models/Models/PhSInstitution.cs b/Models/Models/PhSInstitution.cs new file mode 100644 index 0000000..091bd9c --- /dev/null +++ b/Models/Models/PhSInstitution.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; + +namespace Models.Models; + +public partial class PhSInstitution +{ + public int Id { get; set; } + + public string Name { get; set; } = null!; + + public string Type { get; set; } = null!; + + public string? Streetaddress { get; set; } + + public string? City { get; set; } + + public string? Province { get; set; } + + public string? Phone { get; set; } + + public string? Email { get; set; } + + public string? Operatingroominfo { get; set; } + + public DateTime Createdat { get; set; } + + public bool Isactive { get; set; } + + public double? Latitude { get; set; } + + public double? Longitude { get; set; } +} diff --git a/Models/Models/PhSPatient.cs b/Models/Models/PhSPatient.cs new file mode 100644 index 0000000..63470ec --- /dev/null +++ b/Models/Models/PhSPatient.cs @@ -0,0 +1,41 @@ +using System; +using System.Collections.Generic; + +namespace Models.Models; + +public partial class PhSPatient +{ + public int Id { get; set; } + + public string Firstname { get; set; } = null!; + + public string Lastname { get; set; } = null!; + + public int? DocumenttypesId { get; set; } + + public string? DocumentNumber { get; set; } + + public string? AffiliateNumber { get; set; } + + public DateOnly? Birthdate { get; set; } + + public string? Gender { get; set; } + + public string? Phone { get; set; } + + public string? Email { get; set; } + + public string? Address { get; set; } + + public string? Notes { get; set; } + + public int? CustomerId { get; set; } + + public DateTime Createdat { get; set; } + + public DateTime? Modifiedat { get; set; } + + public virtual PhSCustomer? Customer { get; set; } + + public virtual PhSDocumentType? Documenttypes { get; set; } +} diff --git a/Models/Models/PhSProductCategory.cs b/Models/Models/PhSProductCategory.cs index 1da13f5..c767a05 100644 --- a/Models/Models/PhSProductCategory.cs +++ b/Models/Models/PhSProductCategory.cs @@ -1,4 +1,7 @@ -namespace Models.Models; +using System; +using System.Collections.Generic; + +namespace Models.Models; public partial class PhSProductCategory { diff --git a/Models/Models/PhSQuoteDetail.cs b/Models/Models/PhSQuoteDetail.cs index 494992c..5a5acb1 100644 --- a/Models/Models/PhSQuoteDetail.cs +++ b/Models/Models/PhSQuoteDetail.cs @@ -1,4 +1,7 @@ -namespace Models.Models; +using System; +using System.Collections.Generic; + +namespace Models.Models; public partial class PhSQuoteDetail { diff --git a/Models/Models/PhronCareOperationsHubContext.cs b/Models/Models/PhronCareOperationsHubContext.cs index b1ebb35..2612b26 100644 --- a/Models/Models/PhronCareOperationsHubContext.cs +++ b/Models/Models/PhronCareOperationsHubContext.cs @@ -31,6 +31,10 @@ public partial class PhronCareOperationsHubContext : DbContext public virtual DbSet PhSDocumentTypes { get; set; } + public virtual DbSet PhSInstitutions { get; set; } + + public virtual DbSet PhSPatients { get; set; } + public virtual DbSet PhSProducts { get; set; } public virtual DbSet PhSProductCategories { get; set; } @@ -48,7 +52,7 @@ public partial class PhronCareOperationsHubContext : DbContext } } #endregion - // => optionsBuilder.UseSqlServer("data source=srv01.saludlab.com.ar,39458;initial catalog=phronCare_OperationsHub;User ID=sa;Password=HS|s[~xxQzTo/n>9jO;encrypt=False;trustServerCertificate=True;MultipleActiveResultSets=True"); + //=> optionsBuilder.UseSqlServer("data source=srv01.saludlab.com.ar,39458;initial catalog=phronCare_OperationsHub;User ID=sa;Password=HS|s[~xxQzTo/n>9jO;encrypt=False;trustServerCertificate=True;MultipleActiveResultSets=True"); protected override void OnModelCreating(ModelBuilder modelBuilder) { @@ -259,6 +263,98 @@ public partial class PhronCareOperationsHubContext : DbContext .HasColumnName("name"); }); + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("PK__PhS_Inst__3213E83F7645655B"); + + entity.ToTable("PhS_Institutions"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.City) + .HasMaxLength(100) + .HasColumnName("city"); + entity.Property(e => e.Createdat) + .HasDefaultValueSql("(getdate())") + .HasColumnType("datetime") + .HasColumnName("createdat"); + entity.Property(e => e.Email) + .HasMaxLength(150) + .HasColumnName("email"); + entity.Property(e => e.Isactive) + .HasDefaultValue(true) + .HasColumnName("isactive"); + entity.Property(e => e.Name) + .HasMaxLength(200) + .HasColumnName("name"); + entity.Property(e => e.Operatingroominfo) + .HasMaxLength(200) + .HasColumnName("operatingroominfo"); + entity.Property(e => e.Phone) + .HasMaxLength(50) + .HasColumnName("phone"); + entity.Property(e => e.Province) + .HasMaxLength(100) + .HasColumnName("province"); + entity.Property(e => e.Streetaddress) + .HasMaxLength(250) + .HasColumnName("streetaddress"); + entity.Property(e => e.Type) + .HasMaxLength(15) + .HasColumnName("type"); + }); + + modelBuilder.Entity(entity => + { + entity.HasKey(e => e.Id).HasName("PK__PhS_Pati__3213E83F93A6EB7E"); + + entity.ToTable("PhS_Patients"); + + entity.Property(e => e.Id).HasColumnName("id"); + entity.Property(e => e.Address) + .HasMaxLength(250) + .HasColumnName("address"); + entity.Property(e => e.AffiliateNumber) + .HasMaxLength(100) + .HasColumnName("affiliate_number"); + entity.Property(e => e.Birthdate).HasColumnName("birthdate"); + entity.Property(e => e.Createdat) + .HasDefaultValueSql("(getdate())") + .HasColumnType("datetime") + .HasColumnName("createdat"); + entity.Property(e => e.CustomerId).HasColumnName("customer_id"); + entity.Property(e => e.DocumentNumber) + .HasMaxLength(50) + .HasColumnName("document_number"); + entity.Property(e => e.DocumenttypesId).HasColumnName("documenttypes_id"); + entity.Property(e => e.Email) + .HasMaxLength(150) + .HasColumnName("email"); + entity.Property(e => e.Firstname) + .HasMaxLength(100) + .HasColumnName("firstname"); + entity.Property(e => e.Gender) + .HasMaxLength(10) + .HasColumnName("gender"); + entity.Property(e => e.Lastname) + .HasMaxLength(100) + .HasColumnName("lastname"); + entity.Property(e => e.Modifiedat) + .HasColumnType("datetime") + .HasColumnName("modifiedat"); + entity.Property(e => e.Notes).HasColumnName("notes"); + entity.Property(e => e.Phone) + .HasMaxLength(50) + .HasColumnName("phone"); + + entity.HasOne(d => d.Customer).WithMany(p => p.PhSPatients) + .HasForeignKey(d => d.CustomerId) + .HasConstraintName("FK_Patients_Customers"); + + entity.HasOne(d => d.Documenttypes).WithMany(p => p.PhSPatients) + .HasForeignKey(d => d.DocumenttypesId) + .HasConstraintName("FK_Patients_DocumentTypes"); + }); + modelBuilder.Entity(entity => { entity.ToTable("PhS_Products"); diff --git a/Models/Repositories/PhSCustomerRepository.cs b/Models/Repositories/PhSCustomerRepository.cs index ef008ce..dc6198c 100644 --- a/Models/Repositories/PhSCustomerRepository.cs +++ b/Models/Repositories/PhSCustomerRepository.cs @@ -13,6 +13,7 @@ namespace Models.Repositories #region Declaraciones y Constructor private readonly PhronCareOperationsHubContext _context = context; #endregion + #region Métodos de clase public async Task> GetAllAsync(int page = 1, int pageSize = 50) { var query = _context.PhSCustomers @@ -176,5 +177,6 @@ namespace Models.Repositories await _context.SaveChangesAsync(); return true; } + #endregion } } diff --git a/Models/Repositories/PhSInstitutionReposotory.cs b/Models/Repositories/PhSInstitutionReposotory.cs new file mode 100644 index 0000000..35b0fd8 --- /dev/null +++ b/Models/Repositories/PhSInstitutionReposotory.cs @@ -0,0 +1,111 @@ +using Microsoft.EntityFrameworkCore; +using Models.Interfaces; +using Domain.Entities; +using Models.Helpers; +using Models.Models; +using Domain.Generics; + +namespace Models.Repositories +{ + public class PhSInstitutionRepository(PhronCareOperationsHubContext context):IPhSInstitutionRepository + { + #region Declaraciones y Constructor + private readonly PhronCareOperationsHubContext _context = context; + #endregion + #region Metodos de clase + public async Task> GetAllAsync(int page = 1, int pageSize = 50) + { + var query = _context.PhSInstitutions.AsNoTracking().OrderBy(x => x.Name); + var totalItems = await query.CountAsync(); + + var pagedEntities = await query.ToPagedResultAsync(page, pageSize); + + return new PagedResult + { + Items = pagedEntities.Items.Select(EntityMapper.MapEntity), + TotalItems = pagedEntities.TotalItems, + Page = pagedEntities.Page, + PageSize = pagedEntities.PageSize + }; + } + public async Task GetByIdAsync(int id) + { + var entity = await _context.PhSInstitutions.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id); + return entity == null ? null : EntityMapper.MapEntity(entity); + } + public async Task> SearchAsync(string? name, string? city, string? province, int page = 1, int pageSize = 50) + { + var query = _context.PhSInstitutions.AsQueryable(); + + if (!string.IsNullOrWhiteSpace(name)) + { + var lowered = name.ToLower(); + query = query.Where(i => i.Name.ToLower().Contains(lowered)); + } + + if (!string.IsNullOrWhiteSpace(city)) + { + var lowered = city.ToLower(); + query = query.Where(i => i.City != null && i.City.ToLower().Contains(lowered)); + } + + if (!string.IsNullOrWhiteSpace(province)) + { + var lowered = province.ToLower(); + query = query.Where(i => i.Province != null && i.Province.ToLower().Contains(lowered)); + } + + var pagedEntities = await query.ToPagedResultAsync(page, pageSize); + + return new PagedResult + { + Items = pagedEntities.Items.Select(EntityMapper.MapEntity), + TotalItems = pagedEntities.TotalItems, + Page = pagedEntities.Page, + PageSize = pagedEntities.PageSize + }; + } + public async Task CreateAsync(EInstitution model) + { + if (model == null) + throw new ArgumentNullException(nameof(model), "La insitucion no puede ser nula."); + try + { + var entity = EntityMapper.MapEntity(model); + _context.PhSInstitutions.Add(entity); + await _context.SaveChangesAsync(); + return EntityMapper.MapEntity(entity); + } + catch (DbUpdateException dbEx) + { + throw new Exception("Error al guardar la institucion en la base de datos.", dbEx); + } + catch (Exception ex) + { + throw new Exception("Error inesperado al crear la institucion: " + ex.Message, ex); + } + } + public async Task UpdateAsync(EInstitution model) + { + if (model == null) + throw new ArgumentNullException(nameof(model)); + + try + { + var existingInstitution = await _context.PhSInstitutions.FirstOrDefaultAsync(x => x.Id == model.Id); + if (existingInstitution == null) + return false; + + EntityMapper.MapEntityToExisting(model, existingInstitution); // Actualiza campos + await _context.SaveChangesAsync(); + return true; + } + catch (Exception) + { + return false; + } + + } + #endregion + } +} diff --git a/Models/Repositories/PhSPatientRepository .cs b/Models/Repositories/PhSPatientRepository .cs new file mode 100644 index 0000000..7df8973 --- /dev/null +++ b/Models/Repositories/PhSPatientRepository .cs @@ -0,0 +1,133 @@ +using Domain.Entities; +using Domain.Generics; +using Microsoft.EntityFrameworkCore; +using Microsoft.Extensions.Logging; +using Models.Helpers; +using Models.Interfaces; +using Models.Models; + +namespace Infrastructure.Repositories.Patients +{ + public class PhSPatientRepository(PhronCareOperationsHubContext context, ILogger logger) : IPhSPatientRepository + { + #region Declaraciones y Constructor + private readonly PhronCareOperationsHubContext _context = context; + #endregion + #region Métodos de clase + public async Task> GetAllAsync(int page = 1, int pageSize = 50) + { + var query = _context.PhSPatients + .Include(p => p.Customer) + .Include(p => p.Documenttypes) + .AsQueryable(); + + var pagedEntities = await query.ToPagedResultAsync(page, pageSize); + + return new PagedResult + { + Items = pagedEntities.Items.Select(EntityMapper.MapEntity), + TotalItems = pagedEntities.TotalItems, + Page = pagedEntities.Page, + PageSize = pagedEntities.PageSize + }; + } + public async Task GetByIdAsync(int id) + { + var patient = await _context.PhSPatients + .Include(p => p.Customer) + .Include(p => p.Documenttypes) + .FirstOrDefaultAsync(p => p.Id == id); + + return patient != null ? EntityMapper.MapEntity(patient) : null; + } + public async Task> SearchAsync( + string? name, + string? document, + int page = 1, + int pageSize = 50) + { + var query = _context.PhSPatients + .Include(p => p.Documenttypes) + .Include(p => p.Customer) + .AsQueryable(); + + if (!string.IsNullOrWhiteSpace(name)) + { + var lowered = name.ToLower(); + query = query.Where(p => + p.Firstname.ToLower().Contains(lowered) || + p.Lastname.ToLower().Contains(lowered)); + } + + if (!string.IsNullOrWhiteSpace(document)) + { + query = query.Where(p => + EF.Functions.Like(p.DocumentNumber!, $"%{document}%") || EF.Functions.Like(p.AffiliateNumber!, $"%{document}%")); + } + + var pagedEntities = await query.ToPagedResultAsync(page, pageSize); + + return new PagedResult + { + Items = pagedEntities.Items.Select(EntityMapper.MapEntity), + TotalItems = pagedEntities.TotalItems, + Page = pagedEntities.Page, + PageSize = pagedEntities.PageSize + }; + } + public async Task CreateAsync(EPatient entity) + { + if (entity == null) + throw new ArgumentNullException(nameof(entity), "El paciente no puede ser nulo."); + + try + { + var patient = EntityMapper.MapEntity(entity); + await _context.PhSPatients.AddAsync(patient); + await _context.SaveChangesAsync(); + return EntityMapper.MapEntity(patient); + } + catch (DbUpdateException dbEx) + { + throw new Exception("Error al guardar el paciente en la base de datos.", dbEx); + } + catch (Exception ex) + { + throw new Exception("Error inesperado al crear el paciente: " + ex.Message, ex); + } + } + public async Task UpdateAsync(EPatient entity) + { + if (entity == null) + throw new ArgumentNullException(nameof(entity)); + + try + { + var existingPatient = await _context.PhSPatients + .FirstOrDefaultAsync(p => p.Id == entity.Id); + + if (existingPatient == null) + return false; + + EntityMapper.MapEntityToExisting(entity, existingPatient); + + await _context.SaveChangesAsync(); + return true; + } + catch (Exception) + { + return false; + } + } + public async Task DeleteAsync(int id) + { + var patient = await _context.PhSPatients.FindAsync(id); + if (patient == null) return false; + + _context.PhSPatients.Remove(patient); + await _context.SaveChangesAsync(); + return true; + } + #endregion + } +} diff --git a/Models/obj/Models.csproj.nuget.g.props b/Models/obj/Models.csproj.nuget.g.props index 57bd42c..d21a6b0 100644 --- a/Models/obj/Models.csproj.nuget.g.props +++ b/Models/obj/Models.csproj.nuget.g.props @@ -7,7 +7,7 @@ $(UserProfile)\.nuget\packages\ C:\Users\maski\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages PackageReference - 6.13.2 + 6.13.1 diff --git a/phronCare.API/Controllers/InstitutionController.cs b/phronCare.API/Controllers/InstitutionController.cs new file mode 100644 index 0000000..4c33b1b --- /dev/null +++ b/phronCare.API/Controllers/InstitutionController.cs @@ -0,0 +1,130 @@ +using Core.Interfaces; +using Domain.Entities; +using Domain.Generics; +using Domain.SearchParams; +using Microsoft.AspNetCore.Mvc; +using System.Reflection; + +namespace phronCare.API.Controllers.Sales +{ + [Route("api/[controller]")] + [ApiController] + public class InstitutionController : ControllerBase + { + private readonly IInstitutionDom _institutionService; + public InstitutionController(IInstitutionDom institutionService) + { + _institutionService = institutionService ?? throw new ArgumentNullException(nameof(institutionService)); + } + [HttpGet("all")] + public async Task GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 50) + { + try + { + var result = await _institutionService.GetAllAsync(page, pageSize); + return Ok(result); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } + [HttpGet("search")] + public async Task Search( + [FromQuery] string? name, + [FromQuery] string? city, + [FromQuery] string? province, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 50) + { + try + { + var result = await _institutionService.SearchAsync(name, city, province, page, pageSize); + 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 institution = await _institutionService.GetByIdAsync(id); + if (institution == null) + return NotFound(); + + return Ok(institution); + } + catch (Exception ex) + { + return StatusCode(500, $"Error: {ex.Message}"); + } + } + [HttpPost("create")] + public async Task Create([FromBody] EInstitution institution) + { + try + { + if (institution == null) + return BadRequest("La institución no puede ser nula."); + + var result = await _institutionService.CreateAsync(institution); + 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] EInstitution institution) + { + try + { + if (institution == null || institution.Id <= 0) + return BadRequest("La institución es inválida o no tiene un ID válido."); + + var success = await _institutionService.UpdateAsync(institution); + + if (!success) + return NotFound($"No se encontró una institución con ID {institution.Id}."); + + return Ok("Institución actualizada correctamente."); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } + [HttpPost("exportfiltered")] + public async Task ExportFiltered([FromBody] InstitutionSearchParams searchParams) + { + try + { + var file = await _institutionService.ExportFilteredInstitutionsToExcelAsync(searchParams); + return File(file, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "Instituciones.xlsx"); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + } +} diff --git a/phronCare.API/Controllers/Sales/PatientController.cs b/phronCare.API/Controllers/Sales/PatientController.cs new file mode 100644 index 0000000..0dabb5b --- /dev/null +++ b/phronCare.API/Controllers/Sales/PatientController.cs @@ -0,0 +1,135 @@ +using Core.Interfaces; +using Domain.Entities; +using Domain.SearchParams; +using Microsoft.AspNetCore.Mvc; +using System.Reflection; + +namespace phronCare.API.Controllers.Sales +{ + [Route("api/[controller]")] + [ApiController] + public class PatientController : ControllerBase + { + private readonly IPatientDom _patientService; + + public PatientController(IPatientDom patientService) + { + _patientService = patientService ?? throw new ArgumentNullException(nameof(patientService)); + } + + [HttpGet("all")] + public async Task GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 50) + { + try + { + var result = await _patientService.GetAllAsync(page, pageSize); + return Ok(result); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } + + [HttpGet("search")] + public async Task Search( + [FromQuery] string? name, + [FromQuery] string? document, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 50) + { + try + { + var result = await _patientService.SearchAsync(name, document, page, pageSize); + 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 patient = await _patientService.GetByIdAsync(id); + if (patient == null) + return NotFound(); + + return Ok(patient); + } + catch (Exception ex) + { + return StatusCode(500, $"Error: {ex.Message}"); + } + } + + [HttpPost("create")] + public async Task Create([FromBody] EPatient patient) + { + try + { + if (patient == null) + return BadRequest("El paciente no puede ser nulo."); + + var result = await _patientService.CreateAsync(patient); + 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] EPatient patient) + { + try + { + if (patient == null || patient.Id <= 0) + return BadRequest("El paciente es inválido o no tiene un ID válido."); + + var success = await _patientService.UpdateAsync(patient); + + if (!success) + return NotFound($"No se encontró un paciente con ID {patient.Id}."); + + return Ok("Paciente actualizado correctamente."); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } + + [HttpPost("exportfiltered")] + public async Task ExportFiltered([FromBody] PatientSearchParams searchParams) + { + try + { + var file = await _patientService.ExportFilteredPatientsToExcelAsync(searchParams); + return File(file, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "Pacientes.xlsx"); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + } +} diff --git a/phronCare.API/Program.cs b/phronCare.API/Program.cs index 02f1e70..5178a35 100644 --- a/phronCare.API/Program.cs +++ b/phronCare.API/Program.cs @@ -14,6 +14,7 @@ using Services.Models; using Services.Services; using Services.Interfaces; using System.Text; +using Infrastructure.Repositories.Patients; var builder = WebApplication.CreateBuilder(args); @@ -58,6 +59,11 @@ builder.Services.AddScoped(); builder.Services.AddScoped(); +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +builder.Services.AddScoped(); +builder.Services.AddScoped(); #endregion #region Require Confirmed Email diff --git a/phronCare.API/obj/Debug/net8.0/ApiEndpoints.json b/phronCare.API/obj/Debug/net8.0/ApiEndpoints.json index eb7ae15..e785da4 100644 --- a/phronCare.API/obj/Debug/net8.0/ApiEndpoints.json +++ b/phronCare.API/obj/Debug/net8.0/ApiEndpoints.json @@ -571,6 +571,263 @@ ], "ReturnTypes": [] }, + { + "ContainingType": "phronCare.API.Controllers.Sales.InstitutionController", + "Method": "GetById", + "RelativePath": "api/Institution/{id}", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "id", + "Type": "System.Int32", + "IsRequired": true + } + ], + "ReturnTypes": [ + { + "Type": "Domain.Entities.EInstitution", + "MediaTypes": [ + "text/plain", + "application/json", + "text/json" + ], + "StatusCode": 200 + } + ] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.InstitutionController", + "Method": "GetAll", + "RelativePath": "api/Institution/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.InstitutionController", + "Method": "Create", + "RelativePath": "api/Institution/create", + "HttpMethod": "POST", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "institution", + "Type": "Domain.Entities.EInstitution", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.InstitutionController", + "Method": "ExportFiltered", + "RelativePath": "api/Institution/exportfiltered", + "HttpMethod": "POST", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "searchParams", + "Type": "Domain.Generics.InstitutionSearchParams", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.InstitutionController", + "Method": "Search", + "RelativePath": "api/Institution/search", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "name", + "Type": "System.String", + "IsRequired": false + }, + { + "Name": "city", + "Type": "System.String", + "IsRequired": false + }, + { + "Name": "province", + "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.InstitutionController", + "Method": "Update", + "RelativePath": "api/Institution/update", + "HttpMethod": "PUT", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "institution", + "Type": "Domain.Entities.EInstitution", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.PatientController", + "Method": "GetById", + "RelativePath": "api/Patient/{id}", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "id", + "Type": "System.Int32", + "IsRequired": true + } + ], + "ReturnTypes": [ + { + "Type": "Domain.Entities.EPatient", + "MediaTypes": [ + "text/plain", + "application/json", + "text/json" + ], + "StatusCode": 200 + } + ] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.PatientController", + "Method": "GetAll", + "RelativePath": "api/Patient/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.PatientController", + "Method": "Create", + "RelativePath": "api/Patient/create", + "HttpMethod": "POST", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "patient", + "Type": "Domain.Entities.EPatient", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.PatientController", + "Method": "ExportFiltered", + "RelativePath": "api/Patient/exportfiltered", + "HttpMethod": "POST", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "searchParams", + "Type": "Domain.SearchParams.PatientSearchParams", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.PatientController", + "Method": "Search", + "RelativePath": "api/Patient/search", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "name", + "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.PatientController", + "Method": "Update", + "RelativePath": "api/Patient/update", + "HttpMethod": "PUT", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "patient", + "Type": "Domain.Entities.EPatient", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, { "ContainingType": "phronCare.API.Controllers.Sales.ProductController", "Method": "GetById", diff --git a/phronCare.UIBlazor/Pages/Sales/CustomerForm.razor b/phronCare.UIBlazor/Pages/Sales/CustomerForm.razor index 7ab5372..7d2709c 100644 --- a/phronCare.UIBlazor/Pages/Sales/CustomerForm.razor +++ b/phronCare.UIBlazor/Pages/Sales/CustomerForm.razor @@ -52,17 +52,21 @@
-
-
- +
+
+ + +
-
-
- +
+
+ + +

@@ -71,7 +75,7 @@
- + @foreach (var tipo in documentTypes) { @@ -83,7 +87,7 @@
- +

@@ -113,75 +117,6 @@ }
Direcciones
-
-
- -
-
- -
-
-
-
- -
-
- -
-
-
-
- -
-
- @if (editingAddress.Country == "Argentina" && provincesByCountry.TryGetValue("Argentina", out var provincias)) - { - - } - else - { - - } -
-
-
-
- -
-
- -
-
- -
-
-
-
- -
-
-
- - @if (editingIndex != -1) - { - - } -
- @if (customer.PhSCustomerAddresses.Any()) { @@ -213,17 +148,86 @@
} +
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ @if (editingAddress.Country == "Argentina" && provincesByCountry.TryGetValue("Argentina", out var provincias)) + { + + } + else + { + + } +
+
+
+
+ +
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ @if (editingIndex != -1) + { + + } +
+
diff --git a/phronCare.UIBlazor/Pages/Sales/ProductForm.razor b/phronCare.UIBlazor/Pages/Sales/ProductForm.razor index af51469..1644af5 100644 --- a/phronCare.UIBlazor/Pages/Sales/ProductForm.razor +++ b/phronCare.UIBlazor/Pages/Sales/ProductForm.razor @@ -98,7 +98,7 @@ @@ -112,6 +112,7 @@ private EProduct _model = new(); private List _productCategories = new(); private List _businessUnits = new(); + private bool isSaving = false; protected override async Task OnInitializedAsync() {