From e14fecc455e3854253303ff661d0dec083869757 Mon Sep 17 00:00:00 2001 From: Leandro Hernan Rojas Date: Fri, 18 Apr 2025 02:01:12 -0300 Subject: [PATCH] Add BusinessUnits y ProductCatergories in API --- Core/Interfaces/IBusinessUnitDom.cs | 14 + Core/Interfaces/IProductCategoryDom.cs | 14 + Core/Interfaces/IProductDom.cs | 16 + Core/Services/BusinessUnitService.cs | 97 ++++++ Core/Services/ProductCategoryService.cs | 87 +++++ Core/Services/ProductService .cs | 126 +++++++ Domain/Generics/ProductSearchParams.cs | 7 + Domain/obj/Domain.csproj.nuget.g.props | 2 +- .../Interfaces/IPhSBusinessUnitRepository.cs | 14 + .../IPhSProductCategoryRepository.cs | 14 + Models/Interfaces/IPhSProductRepository.cs | 15 + Models/Models/PhSBusinessUnit.cs | 5 +- Models/Models/PhSProductCategory.cs | 5 +- Models/Models/PhSQuoteDetail.cs | 5 +- .../PhOhTaxConditionRepository.cs | 4 +- .../PhSBusinessUnitRepository..cs | 97 ++++++ Models/Repositories/PhSCustomerRepository.cs | 1 - .../PhSProductCategoryRepository.cs | 88 +++++ Models/Repositories/PhSProductRepository.cs | 125 +++++++ Models/obj/Models.csproj.nuget.g.props | 2 +- .../Sales/BusinessUnitController.cs | 134 ++++++++ .../Sales/ProductCategoryController.cs | 133 ++++++++ .../Controllers/Sales/ProductController.cs | 134 ++++++++ phronCare.API/Program.cs | 17 + .../obj/Debug/net8.0/ApiEndpoints.json | 321 ++++++++++++++++++ 25 files changed, 1460 insertions(+), 17 deletions(-) create mode 100644 Core/Interfaces/IBusinessUnitDom.cs create mode 100644 Core/Interfaces/IProductCategoryDom.cs create mode 100644 Core/Interfaces/IProductDom.cs create mode 100644 Core/Services/BusinessUnitService.cs create mode 100644 Core/Services/ProductCategoryService.cs create mode 100644 Core/Services/ProductService .cs create mode 100644 Domain/Generics/ProductSearchParams.cs create mode 100644 Models/Interfaces/IPhSBusinessUnitRepository.cs create mode 100644 Models/Interfaces/IPhSProductCategoryRepository.cs create mode 100644 Models/Interfaces/IPhSProductRepository.cs create mode 100644 Models/Repositories/PhSBusinessUnitRepository..cs create mode 100644 Models/Repositories/PhSProductCategoryRepository.cs create mode 100644 Models/Repositories/PhSProductRepository.cs create mode 100644 phronCare.API/Controllers/Sales/BusinessUnitController.cs create mode 100644 phronCare.API/Controllers/Sales/ProductCategoryController.cs create mode 100644 phronCare.API/Controllers/Sales/ProductController.cs diff --git a/Core/Interfaces/IBusinessUnitDom.cs b/Core/Interfaces/IBusinessUnitDom.cs new file mode 100644 index 0000000..a00f514 --- /dev/null +++ b/Core/Interfaces/IBusinessUnitDom.cs @@ -0,0 +1,14 @@ +using Domain.Entities; + +namespace Core.Interfaces +{ + public interface IBusinessUnitDom + { + Task> GetAllAsync(); + Task GetByIdAsync(int id); + Task> SearchAsync(string term); + Task CreateAsync(EBusinessUnit unit); + Task UpdateAsync(EBusinessUnit unit); + Task DeleteAsync(int id); + } +} diff --git a/Core/Interfaces/IProductCategoryDom.cs b/Core/Interfaces/IProductCategoryDom.cs new file mode 100644 index 0000000..677d466 --- /dev/null +++ b/Core/Interfaces/IProductCategoryDom.cs @@ -0,0 +1,14 @@ +using Domain.Entities; + +namespace Core.Interfaces +{ + public interface IProductCategoryDom + { + Task CreateAsync(EProductCategory unit); + Task> GetAllAsync(); + Task GetByIdAsync(int id); + Task> SearchAsync(string term); + Task UpdateAsync(EProductCategory unit); + Task DeleteAsync(int id); + } +} diff --git a/Core/Interfaces/IProductDom.cs b/Core/Interfaces/IProductDom.cs new file mode 100644 index 0000000..fc81167 --- /dev/null +++ b/Core/Interfaces/IProductDom.cs @@ -0,0 +1,16 @@ +using Domain.Entities; +using Domain.Generics; + +namespace Core.Interfaces +{ + public interface IProductDom + { + Task CreateAsync(EProduct entity); + Task DeleteAsync(int id); + Task ExportFilteredProductsToExcelAsync(ProductSearchParams searchParams); + Task> GetAllAsync(int page = 1, int pageSize = 50); + Task GetByIdAsync(int id); + Task> SearchAsync(string? term, int page = 1, int pageSize = 50); + Task UpdateAsync(EProduct entity); + } +} diff --git a/Core/Services/BusinessUnitService.cs b/Core/Services/BusinessUnitService.cs new file mode 100644 index 0000000..50a8030 --- /dev/null +++ b/Core/Services/BusinessUnitService.cs @@ -0,0 +1,97 @@ +using Core.Interfaces; +using Domain.Entities; +using Models.Interfaces; +using System.Reflection; + +namespace Core.Services +{ + public class BusinessUnitService: IBusinessUnitDom + { + #region Declaraciones y Constructor + private readonly IPhSBusinessUnitRepository _repository; + public BusinessUnitService(IPhSBusinessUnitRepository repository) + { + _repository = repository ?? throw new ArgumentNullException(nameof(repository)); + } + #endregion + #region Metodos de clases + public async Task> GetAllAsync() + { + try + { + return await _repository.GetAllAsync(); + } + catch (Exception ex) + { + var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{method} Message: {ex.Message}", ex); + } + } + public async Task GetByIdAsync(int id) + { + try + { + return await _repository.GetByIdAsync(id); + } + catch (Exception ex) + { + var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{method} Message: {ex.Message}", ex); + } + } + public async Task> SearchAsync(string term) + { + try + { + return await _repository.SearchAsync(term); + } + catch (Exception ex) + { + var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{method} Message: {ex.Message}", ex); + } + } + public async Task CreateAsync(EBusinessUnit entity) + { + if (entity == null) + throw new ArgumentNullException(nameof(entity), "La unidad de negocio no puede ser nula."); + try + { + return await _repository.CreateAsync(entity); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{ex.Message}", ex); + } + } + public async Task UpdateAsync(EBusinessUnit unit) + { + if (unit == null) + throw new ArgumentNullException(nameof(unit), "La unidad de negocio no puede ser nula."); + + try + { + return await _repository.UpdateAsync(unit); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } + } + public async Task DeleteAsync(int id) + { + try + { + return await _repository.DeleteAsync(id); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } + } + #endregion + } +} diff --git a/Core/Services/ProductCategoryService.cs b/Core/Services/ProductCategoryService.cs new file mode 100644 index 0000000..034e779 --- /dev/null +++ b/Core/Services/ProductCategoryService.cs @@ -0,0 +1,87 @@ +using Models.Repositories; +using System.Reflection; +using Core.Interfaces; +using Domain.Entities; +using Models.Interfaces; + +namespace Core.Services +{ + public class ProductCategoryService : IProductCategoryDom + { + private readonly IPhSProductCategoryRepository _repository; + public ProductCategoryService(IPhSProductCategoryRepository repository) + { + _repository = repository ?? throw new ArgumentNullException(nameof(repository)); + } + public async Task> GetAllAsync() + { + try + { + return await _repository.GetAllAsync(); + } + catch (Exception ex) + { + var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{method} Message: {ex.Message}", ex); + } + } + public async Task GetByIdAsync(int id) + { + try + { + return await _repository.GetByIdAsync(id); + } + catch (Exception ex) + { + var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{method} Message: {ex.Message}", ex); + } + } + public async Task> SearchAsync(string term) + { + try + { + return await _repository.SearchAsync(term); + } + catch (Exception ex) + { + var method = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{method} Message: {ex.Message}", ex); + } + } + public async Task CreateAsync(EProductCategory entity) + { + if (entity == null) + throw new ArgumentNullException(nameof(entity), "La categoría no puede ser nula."); + + return await _repository.CreateAsync(entity); + } + public async Task DeleteAsync(int id) + { + try + { + return await _repository.DeleteAsync(id); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } + } + public async Task UpdateAsync(EProductCategory unit) + { + if (unit == null) + throw new ArgumentNullException(nameof(unit), "La categoría no puede ser nula."); + + try + { + return await _repository.UpdateAsync(unit); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } + } + } +} diff --git a/Core/Services/ProductService .cs b/Core/Services/ProductService .cs new file mode 100644 index 0000000..cd16990 --- /dev/null +++ b/Core/Services/ProductService .cs @@ -0,0 +1,126 @@ +using Core.Interfaces; +using Domain.Entities; +using Domain.Generics; +using Models.Interfaces; +using System.Reflection; +using Transversal.Services; + + +namespace Core.Services +{ + public class ProductService : IProductDom + { + #region Declaraciones y Constructor + private readonly IPhSProductRepository _repository; + public ProductService(IPhSProductRepository 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 method = MethodBase.GetCurrentMethod()?.Name ?? "Unknown"; + throw new Exception($"{method} Message: {ex.Message}", ex); + } + } + public async Task> SearchAsync(string? name, int page = 1, int pageSize = 50) + { + try + { + return await _repository.SearchAsync(name, page, pageSize); + } + catch (Exception ex) + { + var method = MethodBase.GetCurrentMethod()?.Name ?? "Unknown"; + throw new Exception($"{method} Message: {ex.Message}", ex); + } + } + public async Task GetByIdAsync(int id) + { + try + { + return await _repository.GetByIdAsync(id); + } + catch (Exception ex) + { + var method = MethodBase.GetCurrentMethod()?.Name ?? "Unknown"; + throw new Exception($"{method} Message: {ex.Message}", ex); + } + } + public async Task CreateAsync(EProduct entity) + { + if (entity == null) + throw new ArgumentNullException(nameof(entity), "El producto no puede ser nulo."); + + if (string.IsNullOrWhiteSpace(entity.Name)) + throw new ArgumentException("El producto debe tener un nombre válido."); + + if (entity.Baseprice < 0) + throw new ArgumentException("El precio base no puede ser negativo."); + + return await _repository.CreateAsync(entity); + } + public async Task UpdateAsync(EProduct entity) + { + if (entity == null) + throw new ArgumentNullException(nameof(entity), "El producto no puede ser nulo."); + + if (string.IsNullOrWhiteSpace(entity.Name)) + throw new ArgumentException("El producto debe tener un nombre válido."); + + if (entity.Baseprice < 0) + throw new ArgumentException("El precio base no puede ser negativo."); + + return await _repository.UpdateAsync(entity); + } + public async Task DeleteAsync(int id) + { + return await _repository.DeleteAsync(id); + } + public async Task ExportFilteredProductsToExcelAsync(ProductSearchParams searchParams) + { + try + { + // Realiza la búsqueda de productos con los parámetros proporcionados + var searchResult = await SearchAsync(searchParams.Term, searchParams.Page, searchParams.PageSize); + if (searchResult?.Items is null || !searchResult.Items.Any()) + { + throw new Exception("No se encontraron productos para exportar."); + } + // Llamamos a un método que exporta los datos a Excel + var stream = new XLSXExportBase(); + // Convertimos los resultados de la búsqueda a un formato adecuado para el exportador + var productData = searchResult.Items.Select(p => new + { + p.Id, + p.Name, + p.Description, + BusinessUnit = p.Businessunits?.Code, + Category = p.Category?.Name, + p.Origin, + p.Baseprice, + p.Currency, + p.Isactive + }).ToList(); + // Genera el archivo Excel + var excelFile = stream.ExportExcel(productData); + // Devuelve el archivo Excel como un array de bytes + return excelFile; + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + throw new Exception($"{methodName} Message: {ex.Message}", ex); + } + } + #endregion + } +} diff --git a/Domain/Generics/ProductSearchParams.cs b/Domain/Generics/ProductSearchParams.cs new file mode 100644 index 0000000..3ab863e --- /dev/null +++ b/Domain/Generics/ProductSearchParams.cs @@ -0,0 +1,7 @@ +namespace Domain.Generics +{ + public class ProductSearchParams: PagedRequest + { + public string? Term { get; set; } + } +} diff --git a/Domain/obj/Domain.csproj.nuget.g.props b/Domain/obj/Domain.csproj.nuget.g.props index 3efed38..8b4eb7e 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.1 + 6.13.2 diff --git a/Models/Interfaces/IPhSBusinessUnitRepository.cs b/Models/Interfaces/IPhSBusinessUnitRepository.cs new file mode 100644 index 0000000..3d7915d --- /dev/null +++ b/Models/Interfaces/IPhSBusinessUnitRepository.cs @@ -0,0 +1,14 @@ +using Domain.Entities; + +namespace Models.Interfaces +{ + public interface IPhSBusinessUnitRepository + { + Task> GetAllAsync(); + Task GetByIdAsync(int id); + Task> SearchAsync(string term); + Task CreateAsync(EBusinessUnit unit); + Task UpdateAsync(EBusinessUnit unit); + Task DeleteAsync(int id); + } +} \ No newline at end of file diff --git a/Models/Interfaces/IPhSProductCategoryRepository.cs b/Models/Interfaces/IPhSProductCategoryRepository.cs new file mode 100644 index 0000000..673b595 --- /dev/null +++ b/Models/Interfaces/IPhSProductCategoryRepository.cs @@ -0,0 +1,14 @@ +using Domain.Entities; + +namespace Models.Interfaces +{ + public interface IPhSProductCategoryRepository + { + Task> GetAllAsync(); + Task GetByIdAsync(int id); + Task> SearchAsync(string term); + Task CreateAsync(EProductCategory unit); + Task UpdateAsync(EProductCategory unit); + Task DeleteAsync(int id); + } +} diff --git a/Models/Interfaces/IPhSProductRepository.cs b/Models/Interfaces/IPhSProductRepository.cs new file mode 100644 index 0000000..66206cf --- /dev/null +++ b/Models/Interfaces/IPhSProductRepository.cs @@ -0,0 +1,15 @@ +using Domain.Entities; +using Domain.Generics; + +namespace Models.Interfaces +{ + public interface IPhSProductRepository + { + Task CreateAsync(EProduct entity); + Task DeleteAsync(int id); + Task> GetAllAsync(int page = 1, int pageSize = 50); + Task GetByIdAsync(int id); + Task> SearchAsync(string? term, int page = 1, int pageSize = 50); + Task UpdateAsync(EProduct entity); + } +} diff --git a/Models/Models/PhSBusinessUnit.cs b/Models/Models/PhSBusinessUnit.cs index 64f5e0f..9f517b6 100644 --- a/Models/Models/PhSBusinessUnit.cs +++ b/Models/Models/PhSBusinessUnit.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; - -namespace Models.Models; +namespace Models.Models; public partial class PhSBusinessUnit { diff --git a/Models/Models/PhSProductCategory.cs b/Models/Models/PhSProductCategory.cs index c767a05..1da13f5 100644 --- a/Models/Models/PhSProductCategory.cs +++ b/Models/Models/PhSProductCategory.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; - -namespace Models.Models; +namespace Models.Models; public partial class PhSProductCategory { diff --git a/Models/Models/PhSQuoteDetail.cs b/Models/Models/PhSQuoteDetail.cs index 5a5acb1..494992c 100644 --- a/Models/Models/PhSQuoteDetail.cs +++ b/Models/Models/PhSQuoteDetail.cs @@ -1,7 +1,4 @@ -using System; -using System.Collections.Generic; - -namespace Models.Models; +namespace Models.Models; public partial class PhSQuoteDetail { diff --git a/Models/Repositories/PhOhTaxConditionRepository.cs b/Models/Repositories/PhOhTaxConditionRepository.cs index 5f878fe..2b3c607 100644 --- a/Models/Repositories/PhOhTaxConditionRepository.cs +++ b/Models/Repositories/PhOhTaxConditionRepository.cs @@ -1,7 +1,7 @@ using Domain.Entities; using Microsoft.EntityFrameworkCore; -using Models.Helpers; using Models.Interfaces; +using Models.Helpers; using Models.Models; namespace Models.Repositories @@ -22,6 +22,6 @@ namespace Models.Repositories var taxCondition = await _context.PhOhTaxConditions.FirstOrDefaultAsync(a => a.Description.Contains(name)); return taxCondition != null ? EntityMapper.MapEntity(taxCondition) : null; } - #endregion + #endregion } } diff --git a/Models/Repositories/PhSBusinessUnitRepository..cs b/Models/Repositories/PhSBusinessUnitRepository..cs new file mode 100644 index 0000000..8429069 --- /dev/null +++ b/Models/Repositories/PhSBusinessUnitRepository..cs @@ -0,0 +1,97 @@ +using Microsoft.EntityFrameworkCore; +using Models.Interfaces; +using Domain.Entities; +using Models.Helpers; +using Models.Models; + +namespace Models.Repositories +{ + public class PhSBusinessUnitRepository(PhronCareOperationsHubContext context) : IPhSBusinessUnitRepository + { + #region Declaraciones y Constructor + private readonly PhronCareOperationsHubContext _context = context; + #endregion + #region Metodos de clase + public async Task> GetAllAsync() + { + var businessUnits = await _context.PhSBusinessUnits.ToListAsync(); + return businessUnits.Select(EntityMapper.MapEntity); + } + public async Task GetByIdAsync(int id) + { + var entity = await _context.PhSBusinessUnits.FindAsync(id); + return entity is null ? null : EntityMapper.MapEntity(entity); + } + public async Task> SearchAsync(string term) + { + var query = _context.PhSBusinessUnits.AsQueryable(); + + if (!string.IsNullOrWhiteSpace(term)) + { + term = term.ToLower(); + query = query.Where(x => + x.Description.ToLower().Contains(term) || + x.Code.ToLower().Contains(term) || + x.Manager.ToLower().Contains(term)); + } + + var result = await query.ToListAsync(); + return result.Select(EntityMapper.MapEntity); + } + public async Task CreateAsync(EBusinessUnit unit) + { + if (unit == null) throw new ArgumentNullException(nameof(unit), "La unidad de negocio no puede ser nulo."); + try + { + var businessUnit = EntityMapper.MapEntity(unit); + await _context.PhSBusinessUnits.AddAsync(businessUnit); + await _context.SaveChangesAsync(); + return EntityMapper.MapEntity(businessUnit); + } + catch (DbUpdateException dbEx) + { + // Error relacionado con la base de datos (como violación de integridad referencial) + throw new Exception("Error al guardar la unidad de negocio en la base de datos. Es posible que haya un problema con la integridad de los datos.", dbEx); + } + catch (Exception ex) + { + // Captura cualquier otro tipo de excepción + throw new Exception("Error inesperado al crear la unidad de negocio: " + ex.Message, ex); + } + } + public async Task UpdateAsync(EBusinessUnit unit) + { + if (unit == null) throw new ArgumentNullException(nameof(unit), "La unidad de negocio no puede ser nula."); + + try + { + var existingUnit = await _context.PhSBusinessUnits + .FirstOrDefaultAsync(c => c.Id == unit.Id); + + if (existingUnit == null) + return false; + + // Mapea los cambios del modelo EBusinessUnit a la entidad trackeada por EF + EntityMapper.MapEntityToExisting(unit, existingUnit); + + await _context.SaveChangesAsync(); + return true; + } + catch (Exception ex) + { + return false; + } + } + public async Task DeleteAsync(int id) + { + var entity = await _context.PhSBusinessUnits.FindAsync(id); + if (entity != null) + { + _context.PhSBusinessUnits.Remove(entity); + await _context.SaveChangesAsync(); + } + return true; + } + #endregion + } +} \ No newline at end of file diff --git a/Models/Repositories/PhSCustomerRepository.cs b/Models/Repositories/PhSCustomerRepository.cs index 8248cec..ef008ce 100644 --- a/Models/Repositories/PhSCustomerRepository.cs +++ b/Models/Repositories/PhSCustomerRepository.cs @@ -5,7 +5,6 @@ using Microsoft.Extensions.Logging; using Models.Helpers; using Models.Interfaces; using Models.Models; -using System.Xml.Linq; namespace Models.Repositories { diff --git a/Models/Repositories/PhSProductCategoryRepository.cs b/Models/Repositories/PhSProductCategoryRepository.cs new file mode 100644 index 0000000..e0aadc1 --- /dev/null +++ b/Models/Repositories/PhSProductCategoryRepository.cs @@ -0,0 +1,88 @@ +using Microsoft.EntityFrameworkCore; +using Models.Interfaces; +using Domain.Entities; +using Models.Helpers; +using Models.Models; + +namespace Models.Repositories +{ + public class PhSProductCategoryRepository(PhronCareOperationsHubContext context) : IPhSProductCategoryRepository + { + #region Declaraciones y Constructor + private readonly PhronCareOperationsHubContext _context = context; + #endregion + #region Metodos de clase + public async Task> GetAllAsync() + { + var businessUnits = await _context.PhSProductCategories.ToListAsync(); + return businessUnits.Select(EntityMapper.MapEntity); + } + public async Task GetByIdAsync(int id) + { + var entity = await _context.PhSProductCategories.FindAsync(id); + return entity is null ? null : EntityMapper.MapEntity(entity); + } + public async Task> SearchAsync(string term) + { + var query = _context.PhSProductCategories.AsQueryable(); + if (!string.IsNullOrWhiteSpace(term)) + { + term = term.ToLower(); + query = query.Where(x => + x.Description.ToLower().Contains(term) || + x.Name.ToLower().Contains(term)); + } + + var result = await query.ToListAsync(); + return result.Select(EntityMapper.MapEntity); + } + public async Task CreateAsync(EProductCategory unit) + { + if (unit == null) throw new ArgumentNullException(nameof(unit), "La categoria no puede ser nula."); + try + { + var category = EntityMapper.MapEntity(unit); + + await _context.PhSProductCategories.AddAsync(category); + await _context.SaveChangesAsync(); + return EntityMapper.MapEntity(category); + } + catch (DbUpdateException dbEx) + { + // Error relacionado con la base de datos (como violación de integridad referencial) + throw new Exception("Error al guardar la categoria en la base de datos. Es posible que haya un problema con la integridad de los datos.", dbEx); + } + catch (Exception ex) + { + // Captura cualquier otro tipo de excepción + throw new Exception("Error inesperado al crear la categoria: " + ex.Message, ex); + } + } + public async Task UpdateAsync(EProductCategory category) + { + if (category == null || category.Id <= 0) + throw new ArgumentNullException(nameof(category), "La categoría no puede ser nula o tener un ID inválido."); + + var existingCategory = await _context.PhSProductCategories + .FirstOrDefaultAsync(c => c.Id == category.Id); + + if (existingCategory == null) + return false; + + EntityMapper.MapEntityToExisting(category, existingCategory); + await _context.SaveChangesAsync(); + return true; + } + public async Task DeleteAsync(int id) + { + var entity = await _context.PhSProductCategories.FindAsync(id); + if (entity != null) + { + _context.PhSProductCategories.Remove(entity); + await _context.SaveChangesAsync(); + } + return true; + } + #endregion + } +} \ No newline at end of file diff --git a/Models/Repositories/PhSProductRepository.cs b/Models/Repositories/PhSProductRepository.cs new file mode 100644 index 0000000..709e980 --- /dev/null +++ b/Models/Repositories/PhSProductRepository.cs @@ -0,0 +1,125 @@ +using Models.Interfaces; +using Domain.Entities; +using Models.Helpers; +using Models.Models; +using Microsoft.EntityFrameworkCore; +using Domain.Generics; + +namespace Models.Repositories +{ + public class PhSProductRepository(PhronCareOperationsHubContext context) : IPhSProductRepository + { + #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.PhSProducts + .Include(p => p.Businessunits) + .Include(p => p.Category) + .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 product = await _context.PhSProducts + .Include(p => p.Businessunits) + .Include(p => p.Category) + .FirstOrDefaultAsync(p => p.Id == id); + return product is null ? null : EntityMapper.MapEntity(product); + } + public async Task> SearchAsync(string? term, int page = 1, int pageSize = 50) + { + var query = _context.PhSProducts + .Include(p => p.Businessunits) + .Include(p => p.Category) + .AsQueryable(); + + if (!string.IsNullOrWhiteSpace(term)) + { + term = term.ToLower(); + query = query.Where(p => + p.Name.ToLower().Contains(term) || + p.Description.ToLower().Contains(term)); + } + + 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(EProduct entity) + { + if (entity == null) + throw new ArgumentNullException(nameof(entity), "El producto no puede ser nulo."); + try + { + var product = EntityMapper.MapEntity(entity); + + await _context.PhSProducts.AddAsync(product); + await _context.SaveChangesAsync(); + + return EntityMapper.MapEntity(product); + } + catch (DbUpdateException dbEx) + { + throw new Exception("Error al guardar el producto en la base de datos. Verificá integridad de datos.", dbEx); + } + catch (Exception ex) + { + throw new Exception("Error inesperado al crear el producto: " + ex.Message, ex); + } + } + public async Task UpdateAsync(EProduct entity) + { + if (entity == null) + throw new ArgumentNullException(nameof(entity)); + try + { + var existingProduct = await _context.PhSProducts + .Include(p => p.Businessunits) + .Include(p => p.Category) + .FirstOrDefaultAsync(p => p.Id == entity.Id); + + if (existingProduct == null) + return false; + + EntityMapper.MapEntityToExisting(entity, existingProduct); + await _context.SaveChangesAsync(); + + return true; + } + catch (Exception ex) + { + return false; + } + } + public async Task DeleteAsync(int id) + { + var product = await _context.PhSProducts.FindAsync(id); + if (product == null) return false; + + _context.PhSProducts.Remove(product); + 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 d21a6b0..57bd42c 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.1 + 6.13.2 diff --git a/phronCare.API/Controllers/Sales/BusinessUnitController.cs b/phronCare.API/Controllers/Sales/BusinessUnitController.cs new file mode 100644 index 0000000..792a812 --- /dev/null +++ b/phronCare.API/Controllers/Sales/BusinessUnitController.cs @@ -0,0 +1,134 @@ +using Core.Interfaces; +using Domain.Entities; +using Domain.Generics; +using Microsoft.AspNetCore.Mvc; +using System.Reflection; + +namespace phronCare.API.Controllers.Sales +{ + [Route("api/[controller]")] + [ApiController] + public class BusinessUnitController : ControllerBase + { + private readonly IBusinessUnitDom _businessUnitService; + + public BusinessUnitController(IBusinessUnitDom businessUnitService) + { + _businessUnitService = businessUnitService ?? throw new ArgumentNullException(nameof(businessUnitService)); + } + + [HttpGet("all")] + public async Task GetAll() + { + try + { + var result = await _businessUnitService.GetAllAsync(); + 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? term) + { + try + { + var result = await _businessUnitService.SearchAsync(term ?? string.Empty); + 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 result = await _businessUnitService.GetByIdAsync(id); + if (result == null) + return NotFound($"No se encontró una unidad de negocio con ID {id}."); + + return Ok(result); + } + catch (Exception ex) + { + return StatusCode(500, $"Error: {ex.Message}"); + } + } + + [HttpPost("create")] + public async Task Create([FromBody] EBusinessUnit unit) + { + try + { + if (unit == null) + return BadRequest("La unidad de negocio no puede ser nula."); + + var result = await _businessUnitService.CreateAsync(unit); + 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] EBusinessUnit unit) + { + try + { + if (unit == null || unit.Id <= 0) + return BadRequest("La unidad de negocio es inválida o no tiene un ID válido."); + + var success = await _businessUnitService.UpdateAsync(unit); + + if (!success) + return NotFound($"No se encontró una unidad de negocio con ID {unit.Id}."); + + return Ok("Unidad de negocio actualizada correctamente."); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } + + [HttpDelete("{id:int}")] + public async Task Delete(int id) + { + try + { + var success = await _businessUnitService.DeleteAsync(id); + + if (!success) + return NotFound($"No se encontró una unidad de negocio con ID {id}."); + + return Ok("Unidad de negocio eliminada correctamente."); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } + } +} diff --git a/phronCare.API/Controllers/Sales/ProductCategoryController.cs b/phronCare.API/Controllers/Sales/ProductCategoryController.cs new file mode 100644 index 0000000..b7824df --- /dev/null +++ b/phronCare.API/Controllers/Sales/ProductCategoryController.cs @@ -0,0 +1,133 @@ +using Core.Interfaces; +using Domain.Entities; +using Microsoft.AspNetCore.Mvc; +using System.Reflection; + +namespace phronCare.API.Controllers.Sales +{ + [Route("api/[controller]")] + [ApiController] + public class ProductCategoryController : ControllerBase + { + private readonly IProductCategoryDom _productCategoryService; + + public ProductCategoryController(IProductCategoryDom productCategoryService) + { + _productCategoryService = productCategoryService ?? throw new ArgumentNullException(nameof(productCategoryService)); + } + + [HttpGet("all")] + public async Task GetAll() + { + try + { + var result = await _productCategoryService.GetAllAsync(); + 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? term) + { + try + { + var result = await _productCategoryService.SearchAsync(term ?? string.Empty); + 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 result = await _productCategoryService.GetByIdAsync(id); + if (result == null) + return NotFound($"No se encontró una categoría de producto con ID {id}."); + + return Ok(result); + } + catch (Exception ex) + { + return StatusCode(500, $"Error: {ex.Message}"); + } + } + + [HttpPost("create")] + public async Task Create([FromBody] EProductCategory category) + { + try + { + if (category == null) + return BadRequest("La categoría de producto no puede ser nula."); + + var result = await _productCategoryService.CreateAsync(category); + 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] EProductCategory category) + { + try + { + if (category == null || category.Id <= 0) + return BadRequest("La categoría de producto es inválida o no tiene un ID válido."); + + var success = await _productCategoryService.UpdateAsync(category); + + if (!success) + return NotFound($"No se encontró una categoría de producto con ID {category.Id}."); + + return Ok("Categoría de producto actualizada correctamente."); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } + + [HttpDelete("{id:int}")] + public async Task Delete(int id) + { + try + { + var success = await _productCategoryService.DeleteAsync(id); + + if (!success) + return NotFound($"No se encontró una categoría de producto con ID {id}."); + + return Ok("Categoría de producto eliminada correctamente."); + } + catch (Exception ex) + { + var methodName = MethodBase.GetCurrentMethod()?.Name ?? "UnknownMethod"; + return StatusCode(500, $"{methodName} Message: {ex.Message}"); + } + } + } +} diff --git a/phronCare.API/Controllers/Sales/ProductController.cs b/phronCare.API/Controllers/Sales/ProductController.cs new file mode 100644 index 0000000..5417bda --- /dev/null +++ b/phronCare.API/Controllers/Sales/ProductController.cs @@ -0,0 +1,134 @@ +using Core.Interfaces; +using Domain.Entities; +using Domain.Generics; +using Microsoft.AspNetCore.Mvc; +using System.Reflection; + +namespace phronCare.API.Controllers.Sales +{ + [Route("api/[controller]")] + [ApiController] + public class ProductController : ControllerBase + { + private readonly IProductDom _productService; + + public ProductController(IProductDom productService) + { + _productService = productService ?? throw new ArgumentNullException(nameof(productService)); + } + + [HttpGet("all")] + public async Task GetAll([FromQuery] int page = 1, [FromQuery] int pageSize = 50) + { + try + { + var result = await _productService.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? term, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 50) + { + try + { + var result = await _productService.SearchAsync(term, 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 product = await _productService.GetByIdAsync(id); + if (product == null) + return NotFound(); + + return Ok(product); + } + catch (Exception ex) + { + return StatusCode(500, $"Error: {ex.Message}"); + } + } + + [HttpPost("create")] + public async Task Create([FromBody] EProduct product) + { + try + { + if (product == null) + return BadRequest("El producto no puede ser nulo."); + + var result = await _productService.CreateAsync(product); + 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] EProduct product) + { + try + { + if (product == null || product.Id <= 0) + return BadRequest("El producto es inválido o no tiene un ID válido."); + + var success = await _productService.UpdateAsync(product); + + if (!success) + return NotFound($"No se encontró un producto con ID {product.Id}."); + + return Ok("Producto 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] ProductSearchParams searchParams) + { + try + { + var file = await _productService.ExportFilteredProductsToExcelAsync(searchParams); + return File(file, + "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + "Productos.xlsx"); + } + catch (Exception ex) + { + return BadRequest(ex.Message); + } + } + } +} diff --git a/phronCare.API/Program.cs b/phronCare.API/Program.cs index c22ff99..02f1e70 100644 --- a/phronCare.API/Program.cs +++ b/phronCare.API/Program.cs @@ -33,14 +33,31 @@ builder.Services.AddDbContext(options => #region Repositorios y Servicios builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); + builder.Services.AddScoped(); builder.Services.AddScoped(); + +builder.Services.AddScoped(); +builder.Services.AddScoped(); + +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 8a436f4..eb7ae15 100644 --- a/phronCare.API/obj/Debug/net8.0/ApiEndpoints.json +++ b/phronCare.API/obj/Debug/net8.0/ApiEndpoints.json @@ -304,6 +304,106 @@ ], "ReturnTypes": [] }, + { + "ContainingType": "phronCare.API.Controllers.Sales.BusinessUnitController", + "Method": "GetById", + "RelativePath": "api/BusinessUnit/{id}", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "id", + "Type": "System.Int32", + "IsRequired": true + } + ], + "ReturnTypes": [ + { + "Type": "Domain.Entities.EBusinessUnit", + "MediaTypes": [ + "text/plain", + "application/json", + "text/json" + ], + "StatusCode": 200 + } + ] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.BusinessUnitController", + "Method": "Delete", + "RelativePath": "api/BusinessUnit/{id}", + "HttpMethod": "DELETE", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "id", + "Type": "System.Int32", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.BusinessUnitController", + "Method": "GetAll", + "RelativePath": "api/BusinessUnit/all", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.BusinessUnitController", + "Method": "Create", + "RelativePath": "api/BusinessUnit/create", + "HttpMethod": "POST", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "unit", + "Type": "Domain.Entities.EBusinessUnit", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.BusinessUnitController", + "Method": "Search", + "RelativePath": "api/BusinessUnit/search", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "term", + "Type": "System.String", + "IsRequired": false + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.BusinessUnitController", + "Method": "Update", + "RelativePath": "api/BusinessUnit/update", + "HttpMethod": "PUT", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "unit", + "Type": "Domain.Entities.EBusinessUnit", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, { "ContainingType": "phronCare.API.Controllers.Sales.CustomerController", "Method": "GetById", @@ -471,6 +571,227 @@ ], "ReturnTypes": [] }, + { + "ContainingType": "phronCare.API.Controllers.Sales.ProductController", + "Method": "GetById", + "RelativePath": "api/Product/{id}", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "id", + "Type": "System.Int32", + "IsRequired": true + } + ], + "ReturnTypes": [ + { + "Type": "Domain.Entities.EProduct", + "MediaTypes": [ + "text/plain", + "application/json", + "text/json" + ], + "StatusCode": 200 + } + ] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.ProductController", + "Method": "GetAll", + "RelativePath": "api/Product/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.ProductController", + "Method": "Create", + "RelativePath": "api/Product/create", + "HttpMethod": "POST", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "product", + "Type": "Domain.Entities.EProduct", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.ProductController", + "Method": "ExportFiltered", + "RelativePath": "api/Product/exportfiltered", + "HttpMethod": "POST", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "searchParams", + "Type": "Domain.Generics.ProductSearchParams", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.ProductController", + "Method": "Search", + "RelativePath": "api/Product/search", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "term", + "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.ProductController", + "Method": "Update", + "RelativePath": "api/Product/update", + "HttpMethod": "PUT", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "product", + "Type": "Domain.Entities.EProduct", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.ProductCategoryController", + "Method": "GetById", + "RelativePath": "api/ProductCategory/{id}", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "id", + "Type": "System.Int32", + "IsRequired": true + } + ], + "ReturnTypes": [ + { + "Type": "Domain.Entities.EProductCategory", + "MediaTypes": [ + "text/plain", + "application/json", + "text/json" + ], + "StatusCode": 200 + } + ] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.ProductCategoryController", + "Method": "Delete", + "RelativePath": "api/ProductCategory/{id}", + "HttpMethod": "DELETE", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "id", + "Type": "System.Int32", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.ProductCategoryController", + "Method": "GetAll", + "RelativePath": "api/ProductCategory/all", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.ProductCategoryController", + "Method": "Create", + "RelativePath": "api/ProductCategory/create", + "HttpMethod": "POST", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "category", + "Type": "Domain.Entities.EProductCategory", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.ProductCategoryController", + "Method": "Search", + "RelativePath": "api/ProductCategory/search", + "HttpMethod": "GET", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "term", + "Type": "System.String", + "IsRequired": false + } + ], + "ReturnTypes": [] + }, + { + "ContainingType": "phronCare.API.Controllers.Sales.ProductCategoryController", + "Method": "Update", + "RelativePath": "api/ProductCategory/update", + "HttpMethod": "PUT", + "IsController": true, + "Order": 0, + "Parameters": [ + { + "Name": "category", + "Type": "Domain.Entities.EProductCategory", + "IsRequired": true + } + ], + "ReturnTypes": [] + }, { "ContainingType": "phronCare.API.Controllers.Sales.TaxConditionController", "Method": "GetAll",