Update ADD Patients y Institutions Models in API
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m24s
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m24s
This commit is contained in:
parent
2b456f1e47
commit
8623488221
21
Core/Interfaces/IInstitutionDom.cs
Normal file
21
Core/Interfaces/IInstitutionDom.cs
Normal file
@ -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<EInstitution> CreateAsync(EInstitution entity);
|
||||
Task<bool> DeleteAsync(int id);
|
||||
Task<byte[]> ExportFilteredInstitutionsToExcelAsync(InstitutionSearchParams searchParams);
|
||||
Task<PagedResult<EInstitution>> GetAllAsync(int page = 1, int pageSize = 50);
|
||||
Task<EInstitution?> GetByIdAsync(int id);
|
||||
Task<PagedResult<EInstitution>> SearchAsync(string? name, string? city, string? province, int page = 1, int pageSize = 50);
|
||||
Task<bool> UpdateAsync(EInstitution entity);
|
||||
}
|
||||
}
|
||||
18
Core/Interfaces/IPatientDom.cs
Normal file
18
Core/Interfaces/IPatientDom.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Domain.Entities;
|
||||
using Domain.Generics;
|
||||
using Domain.SearchParams;
|
||||
|
||||
namespace Core.Interfaces
|
||||
{
|
||||
public interface IPatientDom
|
||||
{
|
||||
Task<EPatient> CreateAsync(EPatient entity);
|
||||
Task<bool> DeleteAsync(int id);
|
||||
Task<byte[]> ExportFilteredPatientsToExcelAsync(PatientSearchParams searchParams);
|
||||
Task<PagedResult<EPatient>> GetAllAsync(int page = 1, int pageSize = 50);
|
||||
Task<EPatient?> GetByIdAsync(int id);
|
||||
Task<PagedResult<EPatient>> SearchAsync(string? name, string? document, int page = 1, int pageSize = 50);
|
||||
Task<bool> UpdateAsync(EPatient entity);
|
||||
|
||||
}
|
||||
}
|
||||
124
Core/Services/InstitutionService.cs
Normal file
124
Core/Services/InstitutionService.cs
Normal file
@ -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<PagedResult<EInstitution>> 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<EInstitution?> 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<EInstitution> 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<bool> 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<PagedResult<EInstitution>> 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<bool> DeleteAsync(int id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public async Task<byte[]> 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
|
||||
}
|
||||
}
|
||||
130
Core/Services/PatientService.cs
Normal file
130
Core/Services/PatientService.cs
Normal file
@ -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<PagedResult<EPatient>> 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<EPatient?> 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<EPatient> 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<bool> 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<PagedResult<EPatient>> 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<bool> DeleteAsync(int id)
|
||||
{
|
||||
// Implementar según políticas del sistema (soft delete, etc.)
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
public async Task<byte[]> 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
|
||||
}
|
||||
20
Domain/Entities/EInstitution.cs
Normal file
20
Domain/Entities/EInstitution.cs
Normal file
@ -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; }
|
||||
|
||||
}
|
||||
}
|
||||
24
Domain/Entities/EPatient.cs
Normal file
24
Domain/Entities/EPatient.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
||||
@ -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; }
|
||||
|
||||
9
Domain/Generics/InstitutionSearchParams.cs
Normal file
9
Domain/Generics/InstitutionSearchParams.cs
Normal file
@ -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; }
|
||||
}
|
||||
}
|
||||
10
Domain/Generics/PatientSearchParams .cs
Normal file
10
Domain/Generics/PatientSearchParams .cs
Normal file
@ -0,0 +1,10 @@
|
||||
using Domain.Generics;
|
||||
|
||||
namespace Domain.SearchParams
|
||||
{
|
||||
public class PatientSearchParams : PagedRequest
|
||||
{
|
||||
public string? Name { get; set; }
|
||||
public string? Document { get; set; }
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,7 @@
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\maski\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.2</NuGetToolVersion>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.1</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="C:\Users\maski\.nuget\packages\" />
|
||||
|
||||
19
Models/Interfaces/IPhSInstitutionRepository.cs
Normal file
19
Models/Interfaces/IPhSInstitutionRepository.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using Domain.Entities;
|
||||
using Domain.Generics;
|
||||
|
||||
namespace Models.Interfaces
|
||||
{
|
||||
public interface IPhSInstitutionRepository
|
||||
{
|
||||
Task<EInstitution> CreateAsync(EInstitution model);
|
||||
Task<PagedResult<EInstitution>> GetAllAsync(int page = 1, int pageSize = 50);
|
||||
Task<EInstitution?> GetByIdAsync(int id);
|
||||
Task<PagedResult<EInstitution>> SearchAsync(
|
||||
string? name,
|
||||
string? city,
|
||||
string? province,
|
||||
int page = 1,
|
||||
int pageSize = 50);
|
||||
Task<bool> UpdateAsync(EInstitution model);
|
||||
}
|
||||
}
|
||||
20
Models/Interfaces/IPhSPatientRepository.cs
Normal file
20
Models/Interfaces/IPhSPatientRepository.cs
Normal file
@ -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<EPatient> CreateAsync(EPatient entity);
|
||||
Task<bool> DeleteAsync(int id);
|
||||
Task<PagedResult<EPatient>> GetAllAsync(int page = 1, int pageSize = 50);
|
||||
Task<EPatient?> GetByIdAsync(int id);
|
||||
Task<PagedResult<EPatient>> SearchAsync(string? name, string? document, int page = 1, int pageSize = 50);
|
||||
Task<bool> UpdateAsync(EPatient entity);
|
||||
}
|
||||
}
|
||||
@ -1,4 +1,7 @@
|
||||
namespace Models.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Models.Models;
|
||||
|
||||
public partial class PhSBusinessUnit
|
||||
{
|
||||
|
||||
@ -29,6 +29,8 @@ public partial class PhSCustomer
|
||||
|
||||
public virtual ICollection<PhSCustomerDocument> PhSCustomerDocuments { get; set; } = new List<PhSCustomerDocument>();
|
||||
|
||||
public virtual ICollection<PhSPatient> PhSPatients { get; set; } = new List<PhSPatient>();
|
||||
|
||||
public virtual ICollection<PhSQuoteHeader> PhSQuoteHeaders { get; set; } = new List<PhSQuoteHeader>();
|
||||
|
||||
public virtual PhOhTaxCondition? TaxCondition { get; set; }
|
||||
|
||||
@ -14,4 +14,6 @@ public partial class PhSDocumentType
|
||||
public string? Description { get; set; }
|
||||
|
||||
public virtual ICollection<PhSCustomerDocument> PhSCustomerDocuments { get; set; } = new List<PhSCustomerDocument>();
|
||||
|
||||
public virtual ICollection<PhSPatient> PhSPatients { get; set; } = new List<PhSPatient>();
|
||||
}
|
||||
|
||||
33
Models/Models/PhSInstitution.cs
Normal file
33
Models/Models/PhSInstitution.cs
Normal file
@ -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; }
|
||||
}
|
||||
41
Models/Models/PhSPatient.cs
Normal file
41
Models/Models/PhSPatient.cs
Normal file
@ -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; }
|
||||
}
|
||||
@ -1,4 +1,7 @@
|
||||
namespace Models.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Models.Models;
|
||||
|
||||
public partial class PhSProductCategory
|
||||
{
|
||||
|
||||
@ -1,4 +1,7 @@
|
||||
namespace Models.Models;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Models.Models;
|
||||
|
||||
public partial class PhSQuoteDetail
|
||||
{
|
||||
|
||||
@ -31,6 +31,10 @@ public partial class PhronCareOperationsHubContext : DbContext
|
||||
|
||||
public virtual DbSet<PhSDocumentType> PhSDocumentTypes { get; set; }
|
||||
|
||||
public virtual DbSet<PhSInstitution> PhSInstitutions { get; set; }
|
||||
|
||||
public virtual DbSet<PhSPatient> PhSPatients { get; set; }
|
||||
|
||||
public virtual DbSet<PhSProduct> PhSProducts { get; set; }
|
||||
|
||||
public virtual DbSet<PhSProductCategory> 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<PhSInstitution>(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<PhSPatient>(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<PhSProduct>(entity =>
|
||||
{
|
||||
entity.ToTable("PhS_Products");
|
||||
|
||||
@ -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<PagedResult<ECustomer>> GetAllAsync(int page = 1, int pageSize = 50)
|
||||
{
|
||||
var query = _context.PhSCustomers
|
||||
@ -176,5 +177,6 @@ namespace Models.Repositories
|
||||
await _context.SaveChangesAsync();
|
||||
return true;
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
111
Models/Repositories/PhSInstitutionReposotory.cs
Normal file
111
Models/Repositories/PhSInstitutionReposotory.cs
Normal file
@ -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<PagedResult<EInstitution>> 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<EInstitution>
|
||||
{
|
||||
Items = pagedEntities.Items.Select(EntityMapper.MapEntity<PhSInstitution, EInstitution>),
|
||||
TotalItems = pagedEntities.TotalItems,
|
||||
Page = pagedEntities.Page,
|
||||
PageSize = pagedEntities.PageSize
|
||||
};
|
||||
}
|
||||
public async Task<EInstitution?> GetByIdAsync(int id)
|
||||
{
|
||||
var entity = await _context.PhSInstitutions.AsNoTracking().FirstOrDefaultAsync(x => x.Id == id);
|
||||
return entity == null ? null : EntityMapper.MapEntity<PhSInstitution, EInstitution>(entity);
|
||||
}
|
||||
public async Task<PagedResult<EInstitution>> 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<EInstitution>
|
||||
{
|
||||
Items = pagedEntities.Items.Select(EntityMapper.MapEntity<PhSInstitution, EInstitution>),
|
||||
TotalItems = pagedEntities.TotalItems,
|
||||
Page = pagedEntities.Page,
|
||||
PageSize = pagedEntities.PageSize
|
||||
};
|
||||
}
|
||||
public async Task<EInstitution> CreateAsync(EInstitution model)
|
||||
{
|
||||
if (model == null)
|
||||
throw new ArgumentNullException(nameof(model), "La insitucion no puede ser nula.");
|
||||
try
|
||||
{
|
||||
var entity = EntityMapper.MapEntity<EInstitution, PhSInstitution>(model);
|
||||
_context.PhSInstitutions.Add(entity);
|
||||
await _context.SaveChangesAsync();
|
||||
return EntityMapper.MapEntity<PhSInstitution, EInstitution>(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<bool> 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
|
||||
}
|
||||
}
|
||||
133
Models/Repositories/PhSPatientRepository .cs
Normal file
133
Models/Repositories/PhSPatientRepository .cs
Normal file
@ -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<PhSPatientRepository> logger) : IPhSPatientRepository
|
||||
{
|
||||
#region Declaraciones y Constructor
|
||||
private readonly PhronCareOperationsHubContext _context = context;
|
||||
#endregion
|
||||
#region Métodos de clase
|
||||
public async Task<PagedResult<EPatient>> 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<EPatient>
|
||||
{
|
||||
Items = pagedEntities.Items.Select(EntityMapper.MapEntity<PhSPatient, EPatient>),
|
||||
TotalItems = pagedEntities.TotalItems,
|
||||
Page = pagedEntities.Page,
|
||||
PageSize = pagedEntities.PageSize
|
||||
};
|
||||
}
|
||||
public async Task<EPatient?> 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<PhSPatient, EPatient>(patient) : null;
|
||||
}
|
||||
public async Task<PagedResult<EPatient>> 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<EPatient>
|
||||
{
|
||||
Items = pagedEntities.Items.Select(EntityMapper.MapEntity<PhSPatient, EPatient>),
|
||||
TotalItems = pagedEntities.TotalItems,
|
||||
Page = pagedEntities.Page,
|
||||
PageSize = pagedEntities.PageSize
|
||||
};
|
||||
}
|
||||
public async Task<EPatient> CreateAsync(EPatient entity)
|
||||
{
|
||||
if (entity == null)
|
||||
throw new ArgumentNullException(nameof(entity), "El paciente no puede ser nulo.");
|
||||
|
||||
try
|
||||
{
|
||||
var patient = EntityMapper.MapEntity<EPatient, PhSPatient>(entity);
|
||||
await _context.PhSPatients.AddAsync(patient);
|
||||
await _context.SaveChangesAsync();
|
||||
return EntityMapper.MapEntity<PhSPatient, EPatient>(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<bool> 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<bool> 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
|
||||
}
|
||||
}
|
||||
@ -7,7 +7,7 @@
|
||||
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
|
||||
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\maski\.nuget\packages\;C:\Program Files (x86)\Microsoft Visual Studio\Shared\NuGetPackages</NuGetPackageFolders>
|
||||
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.2</NuGetToolVersion>
|
||||
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">6.13.1</NuGetToolVersion>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
|
||||
<SourceRoot Include="C:\Users\maski\.nuget\packages\" />
|
||||
|
||||
130
phronCare.API/Controllers/InstitutionController.cs
Normal file
130
phronCare.API/Controllers/InstitutionController.cs
Normal file
@ -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<IActionResult> 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<IActionResult> 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<ActionResult<EInstitution>> 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<IActionResult> 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<IActionResult> 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<IActionResult> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
135
phronCare.API/Controllers/Sales/PatientController.cs
Normal file
135
phronCare.API/Controllers/Sales/PatientController.cs
Normal file
@ -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<IActionResult> 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<IActionResult> 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<ActionResult<EPatient>> 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<IActionResult> 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<IActionResult> 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<IActionResult> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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<IPhSProductCategoryRepository, PhSProductCategoryRepo
|
||||
builder.Services.AddScoped<IBusinessUnitDom, BusinessUnitService>();
|
||||
builder.Services.AddScoped<IPhSBusinessUnitRepository, PhSBusinessUnitRepository>();
|
||||
|
||||
builder.Services.AddScoped<IPatientDom, PatientService>();
|
||||
builder.Services.AddScoped<IPhSPatientRepository, PhSPatientRepository>();
|
||||
|
||||
builder.Services.AddScoped<IInstitutionDom, InstitutionService>();
|
||||
builder.Services.AddScoped<IPhSInstitutionRepository, PhSInstitutionRepository>();
|
||||
#endregion
|
||||
|
||||
#region Require Confirmed Email
|
||||
|
||||
@ -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",
|
||||
|
||||
@ -52,17 +52,21 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<label for="HasCreditAccount">¿Cuenta Corriente?</label><br />
|
||||
<InputCheckbox id="HasCreditAccount" @bind-Value="customer.HasCreditAccount" />
|
||||
<div class="col-md-4 d-flex align-items-center justify-content-start mt-4">
|
||||
<div class="form-check form-switch">
|
||||
<InputCheckbox id="HasCreditAccount" @bind-Value="customer.HasCreditAccount" class="form-check-input" />
|
||||
<label class="form-check-label ms-2" for="HasCreditAccount">¿Cuenta Corriente?</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="CreditLimit">Límite de Crédito:</label>
|
||||
<InputNumber id="CreditLimit" @bind-Value="customer.CreditLimit" class="form-control" />
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label for="Active">Activo:</label><br />
|
||||
<InputCheckbox id="Active" @bind-Value="customer.Active" />
|
||||
<div class="col-md-4 d-flex align-items-center justify-content-start mt-4">
|
||||
<div class="form-check form-switch">
|
||||
<InputCheckbox id="Active" @bind-Value="customer.Active" class="form-check-input" />
|
||||
<label class="form-check-label ms-2" for="Active">Activo</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
@ -71,7 +75,7 @@
|
||||
<div class="col-sm-4">
|
||||
<label for="TipoDocumento">Tipo:</label>
|
||||
<InputSelect id="TipoDocumento" class="form-control" @bind-Value="documentFormModel.DocumenttypesId">
|
||||
<option value="">Seleccione</option>
|
||||
<option value="">-- Seleccionar --</option>
|
||||
@foreach (var tipo in documentTypes)
|
||||
{
|
||||
<option value="@tipo.Id">@tipo.Name</option>
|
||||
@ -83,7 +87,7 @@
|
||||
<InputText id="NumeroDocumento" class="form-control" @bind-Value="documentFormModel.DocumentNumber" />
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button type="button" class="btn btn-success" @onclick="AddCustomerDocument">Agregar</button>
|
||||
<button type="button" class="btn btn-sm btn-success" @onclick="AddCustomerDocument">Agregar documento</button>
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
@ -113,75 +117,6 @@
|
||||
}
|
||||
<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))
|
||||
{
|
||||
<select class="form-control" @bind="editingAddress.Stateprovince">
|
||||
<option value="">Seleccionar provincia</option>
|
||||
@foreach (var provincia in provincias)
|
||||
{
|
||||
<option value="@provincia">@provincia</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input class="form-control" placeholder="Estado/Provincia" @bind="editingAddress.Stateprovince" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4">
|
||||
<input class="form-control" placeholder="Código Postal" @bind="editingAddress.Postalcode" />
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control" placeholder="Teléfono" @bind="editingAddress.Phonenumber" />
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control" placeholder="Email" @bind="editingAddress.Email" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-12">
|
||||
<textarea class="form-control" placeholder="Notas" @bind="editingAddress.Notes"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<button type="button" class="btn btn-sm btn-success" @onclick="AddOrUpdateAddress">
|
||||
@((editingIndex == -1) ? "Agregar dirección" : "Actualizar dirección")
|
||||
</button>
|
||||
@if (editingIndex != -1)
|
||||
{
|
||||
<button type="button" class="btn btn-sm btn-secondary ms-2" @onclick="CancelAddressEdit">Cancelar</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (customer.PhSCustomerAddresses.Any())
|
||||
{
|
||||
<table class="table table-bordered">
|
||||
@ -213,17 +148,86 @@
|
||||
</tbody>
|
||||
</table>
|
||||
}
|
||||
<div class="row align-items-end">
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" placeholder="Nombre de sucursal" @bind="editingAddress.BusinessName" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" placeholder="Dirección línea 1" @bind="editingAddress.Streetaddress1" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" placeholder="Dirección línea 2" @bind="editingAddress.Streetaddress2" />
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<input class="form-control" placeholder="Ciudad" @bind="editingAddress.City" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-6">
|
||||
<select class="form-control" value="@editingAddress.Country" @onchange="OnCountryChanged">
|
||||
<option value="">Seleccionar país</option>
|
||||
@foreach (var country in countries)
|
||||
{
|
||||
<option value="@country">@country</option>
|
||||
}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
@if (editingAddress.Country == "Argentina" && provincesByCountry.TryGetValue("Argentina", out var provincias))
|
||||
{
|
||||
<select class="form-control" @bind="editingAddress.Stateprovince">
|
||||
<option value="">Seleccionar provincia</option>
|
||||
@foreach (var provincia in provincias)
|
||||
{
|
||||
<option value="@provincia">@provincia</option>
|
||||
}
|
||||
</select>
|
||||
}
|
||||
else
|
||||
{
|
||||
<input class="form-control" placeholder="Estado/Provincia" @bind="editingAddress.Stateprovince" />
|
||||
}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3">
|
||||
<div class="col-md-4">
|
||||
<input class="form-control" placeholder="Código Postal" @bind="editingAddress.Postalcode" />
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control" placeholder="Teléfono" @bind="editingAddress.Phonenumber" />
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<input class="form-control" placeholder="Email" @bind="editingAddress.Email" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-3 row align-items-end align-items-center">
|
||||
<div class="col-sm-8">
|
||||
<textarea class="form-control" placeholder="Notas" @bind="editingAddress.Notes"></textarea>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<button type="button" class="btn btn-sm btn-success" @onclick="AddOrUpdateAddress">
|
||||
@((editingIndex == -1) ? "Agregar dirección" : "Actualizar dirección")
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
@if (editingIndex != -1)
|
||||
{
|
||||
<button type="button" class="btn btn-sm btn-secondary ms-2" @onclick="CancelAddressEdit">Cancelar</button>
|
||||
}
|
||||
</div>
|
||||
|
||||
</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 class="d-flex justify-content-end align-items-center py-3">
|
||||
<button class="btn btn-primary me-2" type="button" @onclick="HandleValidSubmit" disabled="@isSaving">
|
||||
@(isSaving ? "Guardando..." : "Guardar Cliente") </button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="Cancel">Cancelar</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -98,7 +98,7 @@
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<div class="d-flex justify-content-end align-items-center py-3">
|
||||
<button type="submit" class="btn btn-primary me-2">Guardar</button>
|
||||
<button class="btn btn-primary me-2" type="button" @onclick="HandleValidSubmit" disabled="@isSaving"> @(isSaving ? "Guardando..." : "Guardar producto") </button>
|
||||
<button type="button" class="btn btn-secondary" @onclick="NavigateBack">Cancelar</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -112,6 +112,7 @@
|
||||
private EProduct _model = new();
|
||||
private List<EProductCategory> _productCategories = new();
|
||||
private List<EBusinessUnit> _businessUnits = new();
|
||||
private bool isSaving = false;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user