From ce75caefe6c6e7481960bb48ee00e8ba56578c42 Mon Sep 17 00:00:00 2001 From: Matheus Teixeira Date: Sun, 4 Feb 2024 21:44:18 -0300 Subject: [PATCH 1/5] =?UTF-8?q?PR104=20-=20Padr=C3=A3o=20de=20filtros=20e?= =?UTF-8?q?=20pagina=C3=A7=C3=A3o=20de=20dados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Controllers/DatatableController.cs | 74 +++++++++++ .../Injector.cs | 2 + .../Repositories/DatatableRepository.cs | 119 ++++++++++++++++++ .../DTOs/EntityDatatableDto.cs | 30 +++++ .../Interfaces/IDatatableRepository.cs | 16 +++ 5 files changed, 241 insertions(+) create mode 100644 API/Dispo.API/Controllers/DatatableController.cs create mode 100644 src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs create mode 100644 src/Modules/Shared/Dispo.Shared.Core.Domain/DTOs/EntityDatatableDto.cs create mode 100644 src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs diff --git a/API/Dispo.API/Controllers/DatatableController.cs b/API/Dispo.API/Controllers/DatatableController.cs new file mode 100644 index 0000000..13d26cb --- /dev/null +++ b/API/Dispo.API/Controllers/DatatableController.cs @@ -0,0 +1,74 @@ +using Dispo.API.ResponseBuilder; +using Dispo.Shared.Core.Domain.Interfaces; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; + +namespace Dispo.API.Controllers +{ + [Route("api/v1/datatable")] + [ApiController] + [Authorize] + public class DatatableController : ControllerBase + { + private readonly IDatatableRepository _datatableRepository; + + public DatatableController(IDatatableRepository datatableRepository) + { + _datatableRepository = datatableRepository; + } + + [HttpGet("get-count")] + public IActionResult GetCount() + { + var a = _datatableRepository.GetTotalRecords(); + + return Ok(new ResponseModelBuilder().WithData(a) + .WithSuccess(true) + .WithAlert(AlertType.Success) + .Build()); + } + + [HttpGet("get-all")] + public IActionResult Get([FromQuery] PaginationFilter paginationFilter) + { + dynamic datatableData = null; + + if (paginationFilter.Entity == "manufacturer") + { + datatableData = _datatableRepository.GetToDatatableManufacturer(paginationFilter.PageNumber, paginationFilter.PageSize).ToList(); + } + else if (paginationFilter.Entity == "product") + { + datatableData = _datatableRepository.GetToDatatableProduct(paginationFilter.PageNumber, paginationFilter.PageSize).ToList(); + } + else if (paginationFilter.Entity == "supplier") + { + datatableData = _datatableRepository.GetToDatatableSupplier(paginationFilter.PageNumber, paginationFilter.PageSize).ToList(); + } + + + return Ok(new ResponseModelBuilder().WithData(datatableData) + .WithSuccess(true) + .WithAlert(AlertType.Success) + .Build()); + } + } + + public class PaginationFilter + { + public string Entity { get; set; } + public int PageNumber { get; set; } + public int PageSize { get; set; } + + //public PaginationFilter() + //{ + // this.PageNumber = 1; + // this.PageSize = 10; + //} + //public PaginationFilter(int pageNumber, int pageSize) + //{ + // this.PageNumber = pageNumber < 1 ? 1 : pageNumber; + // this.PageSize = pageSize > 10 ? 10 : pageSize; + //} + } +} diff --git a/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Injector.cs b/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Injector.cs index d495690..15053f1 100644 --- a/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Injector.cs +++ b/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Injector.cs @@ -20,6 +20,8 @@ private static void InjectRepositories(IServiceCollection serviceColletion) serviceColletion.AddScoped(); serviceColletion.AddScoped(); serviceColletion.AddScoped(); + + serviceColletion.AddScoped(); } private static void InjectServices(IServiceCollection serviceColletion) diff --git a/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs b/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs new file mode 100644 index 0000000..ec24739 --- /dev/null +++ b/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs @@ -0,0 +1,119 @@ +using Dispo.Shared.Core.Domain.DTOs; +using Dispo.Shared.Core.Domain.Entities; +using Dispo.Shared.Core.Domain.Interfaces; +using Dispo.Shared.Infrastructure.Persistence; +using Dispo.Shared.Infrastructure.Persistence.Context; +using Dispo.Shared.Utils.Extensions; + +namespace Dispo.Infra.Infrastructure.Persistence.Repositories +{ + public class DatatableRepository : BaseRepository, IDatatableRepository + { + private readonly DispoContext _dispoContext; + + public DatatableRepository(DispoContext dispoContext) : base(dispoContext) + { + _dispoContext = dispoContext; + } + + public int GetTotalRecords() + => _dispoContext.Manufacturers.Count(); + + //public IEnumerable GetToDatatable(int pageNumber, int pageSize) + // => _dispoContext.Manufacturers.Skip((pageNumber - 1) * pageSize) + // .Take(pageSize) + // .Select(s => new ManufacturerInfoDto() + // { + // Id = s.Id, + // Name = s.Name, + // }) + // .ToList(); + + public IEnumerable GetToDatatableProduct(int pageNumber, int pageSize) + => _dispoContext.Set().Skip((pageNumber - 1) * pageSize) + .Take(pageSize) + .Select(product => new ProductDatatableDto + { + Id = product.Id, + Name = product.Name, + PurchasePrice = product.PurchasePrice.ConvertToCurrency(), + SalePrice = product.SalePrice.ConvertToCurrency(), + Category = EnumExtension.ConvertToString(product.Category), + UnitOfMeasurement = EnumExtension.ConvertToString(product.UnitOfMeasurement), + }) + .ToList(); + + public IEnumerable GetToDatatableManufacturer(int pageNumber, int pageSize) + => _dispoContext.Set().Skip((pageNumber - 1) * pageSize) + .Take(pageSize) + .Select(manufacturer => new ManufacturerDatatableDto + { + Id = manufacturer.Id, + Name = manufacturer.Name, + }) + .ToList(); + + public IEnumerable GetToDatatableSupplier(int pageNumber, int pageSize) + => _dispoContext.Set().Skip((pageNumber - 1) * pageSize) + .Take(pageSize) + .Select(supplier => new SupplierDatatableDto + { + Id = supplier.Id, + Name = supplier.Name, + ContactName = supplier.ContactName, + Cnpj = supplier.Cnpj, + Email = supplier.Email, + Phone = supplier.Phone, + }) + .ToList(); + + + + public IEnumerable GetToDatatable(int pageNumber, int pageSize) where TEntity : EntityBase + => _dispoContext.Set().Skip((pageNumber - 1) * pageSize) + .Take(pageSize) + .Select(ConvertToDatabaseDto) + .ToList(); + + private EntityDatatableDto ConvertToDatabaseDto(TEntity entity) where TEntity : EntityBase + { + if (typeof(TEntity) == typeof(Product)) + { + var product = entity as Product; + return new ProductDatatableDto + { + Id = product.Id, + Name = product.Name, + PurchasePrice = product.PurchasePrice.ConvertToCurrency(), + SalePrice = product.SalePrice.ConvertToCurrency(), + Category = EnumExtension.ConvertToString(product.Category), + UnitOfMeasurement = EnumExtension.ConvertToString(product.UnitOfMeasurement), + }; + } + else if (typeof(TEntity) == typeof(Manufacturer)) + { + var manufacturer = entity as Manufacturer; + return new ManufacturerDatatableDto + { + Id = manufacturer.Id, + Name = manufacturer.Name, + }; + } + else if (typeof(TEntity) == typeof(Supplier)) + { + var supplier = entity as Supplier; + return new SupplierDatatableDto + { + Id = supplier.Id, + Name = supplier.Name, + ContactName = supplier.ContactName, + Cnpj = supplier.Cnpj, + Email = supplier.Email, + Phone = supplier.Phone, + }; + } + + throw new NotImplementedException($"Entidade não encontrada {typeof(TEntity)}"); + } + } +} diff --git a/src/Modules/Shared/Dispo.Shared.Core.Domain/DTOs/EntityDatatableDto.cs b/src/Modules/Shared/Dispo.Shared.Core.Domain/DTOs/EntityDatatableDto.cs new file mode 100644 index 0000000..9c79706 --- /dev/null +++ b/src/Modules/Shared/Dispo.Shared.Core.Domain/DTOs/EntityDatatableDto.cs @@ -0,0 +1,30 @@ +namespace Dispo.Shared.Core.Domain.DTOs +{ + public class EntityDatatableDto + { + public long Id { get; set; } + } + + public class ProductDatatableDto : EntityDatatableDto + { + public string Name { get; set; } + public string PurchasePrice { get; set; } + public string SalePrice { get; set; } + public string UnitOfMeasurement { get; set; } + public string Category { get; set; } + } + + public class ManufacturerDatatableDto : EntityDatatableDto + { + public string Name { get; set; } + } + + public class SupplierDatatableDto : EntityDatatableDto + { + public string Name { get; set; } + public string ContactName { get; set; } + public string Cnpj { get; set; } + public string Email { get; set; } + public string Phone { get; set; } + } +} diff --git a/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs b/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs new file mode 100644 index 0000000..3977e1a --- /dev/null +++ b/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs @@ -0,0 +1,16 @@ +using Dispo.Shared.Core.Domain.DTOs; +using Dispo.Shared.Core.Domain.Entities; + +namespace Dispo.Shared.Core.Domain.Interfaces +{ + public interface IDatatableRepository + { + int GetTotalRecords(); + IEnumerable GetToDatatable(int pageNumber, int pageSize) where TEntity : EntityBase; + + + IEnumerable GetToDatatableProduct(int pageNumber, int pageSize); + IEnumerable GetToDatatableManufacturer(int pageNumber, int pageSize); + IEnumerable GetToDatatableSupplier(int pageNumber, int pageSize); + } +} From 61d0ea62715ce46667f01d8336ee6d70413a518b Mon Sep 17 00:00:00 2001 From: Matheus Teixeira Date: Wed, 14 Feb 2024 21:48:33 -0300 Subject: [PATCH 2/5] up --- .../Controllers/DatatableController.cs | 20 +++++++++++++++++++ .../Repositories/DatatableRepository.cs | 14 ++++++------- .../Interfaces/IDatatableRepository.cs | 2 -- 3 files changed, 27 insertions(+), 9 deletions(-) diff --git a/API/Dispo.API/Controllers/DatatableController.cs b/API/Dispo.API/Controllers/DatatableController.cs index 13d26cb..cfa7c8e 100644 --- a/API/Dispo.API/Controllers/DatatableController.cs +++ b/API/Dispo.API/Controllers/DatatableController.cs @@ -52,6 +52,12 @@ public IActionResult Get([FromQuery] PaginationFilter paginationFilter) .WithAlert(AlertType.Success) .Build()); } + + [HttpPost("get-by-filter")] + public IActionResult GetByFilter([FromBody] FilterModel filterModel) + { + return Ok(); + } } public class PaginationFilter @@ -71,4 +77,18 @@ public class PaginationFilter // this.PageSize = pageSize > 10 ? 10 : pageSize; //} } + + public class FilterModel + { + public FilterPropertiesModel Properties { get; set; } + public PaginationFilter PaginationConfig { get; set; } + } + + public class FilterPropertiesModel + { + public string Name { get; set; } + public string Type { get; set; } + public string Value { get; set; } + + } } diff --git a/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs b/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs index ec24739..e04c951 100644 --- a/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs +++ b/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs @@ -45,13 +45,13 @@ public IEnumerable GetToDatatableProduct(int pageNumber, in public IEnumerable GetToDatatableManufacturer(int pageNumber, int pageSize) => _dispoContext.Set().Skip((pageNumber - 1) * pageSize) - .Take(pageSize) - .Select(manufacturer => new ManufacturerDatatableDto - { - Id = manufacturer.Id, - Name = manufacturer.Name, - }) - .ToList(); + .Take(pageSize) + .Select(manufacturer => new ManufacturerDatatableDto + { + Id = manufacturer.Id, + Name = manufacturer.Name, + }) + .ToList(); public IEnumerable GetToDatatableSupplier(int pageNumber, int pageSize) => _dispoContext.Set().Skip((pageNumber - 1) * pageSize) diff --git a/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs b/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs index 3977e1a..d55b925 100644 --- a/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs +++ b/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs @@ -7,8 +7,6 @@ public interface IDatatableRepository { int GetTotalRecords(); IEnumerable GetToDatatable(int pageNumber, int pageSize) where TEntity : EntityBase; - - IEnumerable GetToDatatableProduct(int pageNumber, int pageSize); IEnumerable GetToDatatableManufacturer(int pageNumber, int pageSize); IEnumerable GetToDatatableSupplier(int pageNumber, int pageSize); From 2cc94dfec32f6534273c6b3f08d48aff5c1b7a44 Mon Sep 17 00:00:00 2001 From: Matheus Teixeira Date: Wed, 14 Feb 2024 23:44:54 -0300 Subject: [PATCH 3/5] up --- .../Controllers/DatatableController.cs | 64 +++++++++---------- API/Dispo.API/Dispo.API.csproj | 1 + API/Dispo.API/Dispo.API.sln | 9 ++- .../Dispo.Infra.Infrastructure.Ioc.csproj | 1 + .../Injector.cs | 2 + .../Dispo.Shared.Filter.csproj | 14 ++++ .../Dispo.Shared.Filter/Model/FilterModel.cs | 8 +++ .../Model/PaginationFilter.cs | 9 +++ .../Model/PropertyModel.cs | 8 +++ .../Services/FilterService.cs | 51 +++++++++++++++ .../Services/IFilterService.cs | 10 +++ 11 files changed, 143 insertions(+), 34 deletions(-) create mode 100644 src/Modules/Shared/Dispo.Shared.Filter/Dispo.Shared.Filter.csproj create mode 100644 src/Modules/Shared/Dispo.Shared.Filter/Model/FilterModel.cs create mode 100644 src/Modules/Shared/Dispo.Shared.Filter/Model/PaginationFilter.cs create mode 100644 src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs create mode 100644 src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs create mode 100644 src/Modules/Shared/Dispo.Shared.Filter/Services/IFilterService.cs diff --git a/API/Dispo.API/Controllers/DatatableController.cs b/API/Dispo.API/Controllers/DatatableController.cs index cfa7c8e..08885ac 100644 --- a/API/Dispo.API/Controllers/DatatableController.cs +++ b/API/Dispo.API/Controllers/DatatableController.cs @@ -1,5 +1,7 @@ using Dispo.API.ResponseBuilder; using Dispo.Shared.Core.Domain.Interfaces; +using Dispo.Shared.Filter.Model; +using Dispo.Shared.Filter.Services; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; @@ -11,10 +13,12 @@ namespace Dispo.API.Controllers public class DatatableController : ControllerBase { private readonly IDatatableRepository _datatableRepository; + private readonly IFilterService _filterService; - public DatatableController(IDatatableRepository datatableRepository) + public DatatableController(IDatatableRepository datatableRepository, IFilterService filterService) { _datatableRepository = datatableRepository; + _filterService = filterService; } [HttpGet("get-count")] @@ -54,41 +58,35 @@ public IActionResult Get([FromQuery] PaginationFilter paginationFilter) } [HttpPost("get-by-filter")] - public IActionResult GetByFilter([FromBody] FilterModel filterModel) + public IActionResult GetByFilter([FromBody] FilterModel filter) { - return Ok(); - } - } - - public class PaginationFilter - { - public string Entity { get; set; } - public int PageNumber { get; set; } - public int PageSize { get; set; } - - //public PaginationFilter() - //{ - // this.PageNumber = 1; - // this.PageSize = 10; - //} - //public PaginationFilter(int pageNumber, int pageSize) - //{ - // this.PageNumber = pageNumber < 1 ? 1 : pageNumber; - // this.PageSize = pageSize > 10 ? 10 : pageSize; - //} - } + try + { + var type = Type.GetType($"Dispo.Shared.Core.Domain.Entities.{filter.Entity}, Dispo.Shared.Core.Domain"); + if (type is null) + { + return BadRequest("Entidade inválida."); + } - public class FilterModel - { - public FilterPropertiesModel Properties { get; set; } - public PaginationFilter PaginationConfig { get; set; } - } + var method = _filterService.GetType().GetMethod("Get"); + if (method is null) + { + return BadRequest($"Método 'Get' não implementado para a entidade '{filter.Entity}'"); + } - public class FilterPropertiesModel - { - public string Name { get; set; } - public string Type { get; set; } - public string Value { get; set; } + var genericMethod = method.MakeGenericMethod(type); + var result = genericMethod.Invoke(_filterService, new object[] { filter }); + return Ok(new ResponseModelBuilder().WithData(result) + .WithSuccess(true) + .Build()); + } + catch (Exception ex) + { + return BadRequest(new ResponseModelBuilder().WithMessage(ex.Message) + .WithSuccess(false) + .Build()); ; + } + } } } diff --git a/API/Dispo.API/Dispo.API.csproj b/API/Dispo.API/Dispo.API.csproj index 9ffae8d..6800f96 100644 --- a/API/Dispo.API/Dispo.API.csproj +++ b/API/Dispo.API/Dispo.API.csproj @@ -31,6 +31,7 @@ + diff --git a/API/Dispo.API/Dispo.API.sln b/API/Dispo.API/Dispo.API.sln index f540800..32fba8e 100644 --- a/API/Dispo.API/Dispo.API.sln +++ b/API/Dispo.API/Dispo.API.sln @@ -65,7 +65,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dispo.Infra.Infrastructure. EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dispo.Infra.Plugin", "..\..\src\Modules\Infra\Dispo.Infra.Plugin\Dispo.Infra.Plugin.csproj", "{FC7852D4-961C-4A2E-A77D-F32F72D12608}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dispo.Shared.Log", "..\..\src\Modules\Shared\Dispo.Shared.Log\Dispo.Shared.Log.csproj", "{9DF2CC91-7E5B-450D-B281-EA8D0C66A474}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Dispo.Shared.Log", "..\..\src\Modules\Shared\Dispo.Shared.Log\Dispo.Shared.Log.csproj", "{9DF2CC91-7E5B-450D-B281-EA8D0C66A474}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Dispo.Shared.Filter", "..\..\src\Modules\Shared\Dispo.Shared.Filter\Dispo.Shared.Filter.csproj", "{98098519-4E21-4796-A422-0451709588EA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -161,6 +163,10 @@ Global {9DF2CC91-7E5B-450D-B281-EA8D0C66A474}.Debug|Any CPU.Build.0 = Debug|Any CPU {9DF2CC91-7E5B-450D-B281-EA8D0C66A474}.Release|Any CPU.ActiveCfg = Release|Any CPU {9DF2CC91-7E5B-450D-B281-EA8D0C66A474}.Release|Any CPU.Build.0 = Release|Any CPU + {98098519-4E21-4796-A422-0451709588EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {98098519-4E21-4796-A422-0451709588EA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {98098519-4E21-4796-A422-0451709588EA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {98098519-4E21-4796-A422-0451709588EA}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -195,6 +201,7 @@ Global {16FD027B-42F0-4176-AD7D-FC83ED649ED5} = {B6DEED8C-370C-4FC7-858B-73A9CCB41F86} {FC7852D4-961C-4A2E-A77D-F32F72D12608} = {B6DEED8C-370C-4FC7-858B-73A9CCB41F86} {9DF2CC91-7E5B-450D-B281-EA8D0C66A474} = {A26E43DA-73D5-449E-BE45-9E7A88E5E4A2} + {98098519-4E21-4796-A422-0451709588EA} = {A26E43DA-73D5-449E-BE45-9E7A88E5E4A2} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {C3375A49-13C9-4341-A913-D223CE4E41FC} diff --git a/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Dispo.Infra.Infrastructure.Ioc.csproj b/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Dispo.Infra.Infrastructure.Ioc.csproj index 1d01ddc..ba5f395 100644 --- a/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Dispo.Infra.Infrastructure.Ioc.csproj +++ b/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Dispo.Infra.Infrastructure.Ioc.csproj @@ -12,6 +12,7 @@ + diff --git a/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Injector.cs b/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Injector.cs index 15053f1..7616429 100644 --- a/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Injector.cs +++ b/src/Modules/Infra/Dispo.Infra.Infrastructure.Ioc/Injector.cs @@ -2,6 +2,7 @@ using Dispo.Infra.Core.Application.Services; using Dispo.Infra.Infrastructure.Persistence.Repositories; using Dispo.Shared.Core.Domain.Interfaces; +using Dispo.Shared.Filter.Services; using Microsoft.Extensions.DependencyInjection; namespace Dispo.Infra.Infrastructure.Ioc @@ -31,6 +32,7 @@ private static void InjectServices(IServiceCollection serviceColletion) serviceColletion.AddScoped(); serviceColletion.AddScoped(); serviceColletion.AddScoped(); + serviceColletion.AddScoped(); } } } \ No newline at end of file diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Dispo.Shared.Filter.csproj b/src/Modules/Shared/Dispo.Shared.Filter/Dispo.Shared.Filter.csproj new file mode 100644 index 0000000..f7657de --- /dev/null +++ b/src/Modules/Shared/Dispo.Shared.Filter/Dispo.Shared.Filter.csproj @@ -0,0 +1,14 @@ + + + + net7.0 + enable + enable + + + + + + + + diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Model/FilterModel.cs b/src/Modules/Shared/Dispo.Shared.Filter/Model/FilterModel.cs new file mode 100644 index 0000000..ae818dd --- /dev/null +++ b/src/Modules/Shared/Dispo.Shared.Filter/Model/FilterModel.cs @@ -0,0 +1,8 @@ +namespace Dispo.Shared.Filter.Model +{ + public class FilterModel + { + public required string Entity { get; set; } + public required List Properties { get; set; } + } +} diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Model/PaginationFilter.cs b/src/Modules/Shared/Dispo.Shared.Filter/Model/PaginationFilter.cs new file mode 100644 index 0000000..0489078 --- /dev/null +++ b/src/Modules/Shared/Dispo.Shared.Filter/Model/PaginationFilter.cs @@ -0,0 +1,9 @@ +namespace Dispo.Shared.Filter.Model +{ + public class PaginationFilter + { + public string Entity { get; set; } + public int PageNumber { get; set; } + public int PageSize { get; set; } + } +} diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs b/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs new file mode 100644 index 0000000..6b910ee --- /dev/null +++ b/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs @@ -0,0 +1,8 @@ +namespace Dispo.Shared.Filter.Model +{ + public class PropertyModel + { + public string Name { get; set; } + public string Value { get; set; } + } +} diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs b/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs new file mode 100644 index 0000000..1c67fc6 --- /dev/null +++ b/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs @@ -0,0 +1,51 @@ +using Dispo.Shared.Core.Domain.Entities; +using Dispo.Shared.Filter.Model; +using Dispo.Shared.Infrastructure.Persistence.Context; +using Microsoft.EntityFrameworkCore; +using System.Linq.Expressions; + +namespace Dispo.Shared.Filter.Services +{ + public class FilterService : IFilterService + { + private readonly DispoContext _dispoContext; + + public FilterService(DispoContext dispoContext) + { + _dispoContext = dispoContext; + } + + public List Get(FilterModel filterModel) where T : EntityBase + { + return _dispoContext.Set() + .AsNoTracking() + .Where(BuildExpression(filterModel)) + .ToList(); + } + + private Func BuildExpression(FilterModel filterModel) + { + var parameter = Expression.Parameter(typeof(T), filterModel.Entity); + Expression filterExpression = null; + foreach (var property in filterModel.Properties) + { + var memberExpression = Expression.Property(parameter, property.Name); + var constant = Expression.Constant(property.Value); + Expression comparison; + if (memberExpression.Type == typeof(string)) + { + comparison = Expression.Call(memberExpression, "Contains", Type.EmptyTypes, constant); + } + else + { + constant = Expression.Constant(Convert.ToInt32(property.Value)); + comparison = Expression.Equal(memberExpression, constant); + } + + filterExpression = filterExpression == null ? comparison : Expression.And(filterExpression, comparison); + } + + return Expression.Lambda>(filterExpression, parameter).Compile(); + } + } +} diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Services/IFilterService.cs b/src/Modules/Shared/Dispo.Shared.Filter/Services/IFilterService.cs new file mode 100644 index 0000000..d0edca9 --- /dev/null +++ b/src/Modules/Shared/Dispo.Shared.Filter/Services/IFilterService.cs @@ -0,0 +1,10 @@ +using Dispo.Shared.Core.Domain.Entities; +using Dispo.Shared.Filter.Model; + +namespace Dispo.Shared.Filter.Services +{ + public interface IFilterService + { + List Get(FilterModel filterModel) where T : EntityBase; + } +} From ceafb6ca4d134f405d771aad3c4d28345a29a911 Mon Sep 17 00:00:00 2001 From: Matheus Teixeira Date: Tue, 20 Feb 2024 00:36:13 -0300 Subject: [PATCH 4/5] up --- .../Controllers/DatatableController.cs | 33 +++++++++----- .../Dispo.Infra.Core.Application.csproj | 4 +- .../Repositories/DatatableRepository.cs | 7 ++- .../Interfaces/IDatatableRepository.cs | 2 +- .../Dispo.Shared.Filter/Model/FilterModel.cs | 7 +++ .../Model/PaginationFilter.cs | 2 +- .../Model/PropertyModel.cs | 13 ++++++ .../Services/FilterService.cs | 43 ++++++++++++++++++- .../Services/IFilterService.cs | 2 +- 9 files changed, 94 insertions(+), 19 deletions(-) diff --git a/API/Dispo.API/Controllers/DatatableController.cs b/API/Dispo.API/Controllers/DatatableController.cs index 08885ac..12fa7af 100644 --- a/API/Dispo.API/Controllers/DatatableController.cs +++ b/API/Dispo.API/Controllers/DatatableController.cs @@ -22,32 +22,45 @@ public DatatableController(IDatatableRepository datatableRepository, IFilterServ } [HttpGet("get-count")] - public IActionResult GetCount() + public IActionResult GetCount([FromQuery] string entity) { - var a = _datatableRepository.GetTotalRecords(); + var type = Type.GetType($"Dispo.Shared.Core.Domain.Entities.{entity}, Dispo.Shared.Core.Domain"); + if (type is null) + { + return BadRequest("Entidade inválida."); + } + + var method = _datatableRepository.GetType().GetMethod("GetTotalRecords"); + if (method is null) + { + return BadRequest($"Método 'GetTotalRecords' não implementado para a entidade '{entity}'"); + } + + var genericMethod = method.MakeGenericMethod(type); + var result = genericMethod.Invoke(_datatableRepository, new object[] {}); - return Ok(new ResponseModelBuilder().WithData(a) + return Ok(new ResponseModelBuilder().WithData(result) .WithSuccess(true) .WithAlert(AlertType.Success) .Build()); } [HttpGet("get-all")] - public IActionResult Get([FromQuery] PaginationFilter paginationFilter) + public IActionResult Get([FromQuery] PaginationModel paginationModel) { dynamic datatableData = null; - if (paginationFilter.Entity == "manufacturer") + if (paginationModel.Entity == "manufacturer") { - datatableData = _datatableRepository.GetToDatatableManufacturer(paginationFilter.PageNumber, paginationFilter.PageSize).ToList(); + datatableData = _datatableRepository.GetToDatatableManufacturer(paginationModel.PageNumber, paginationModel.PageSize).ToList(); } - else if (paginationFilter.Entity == "product") + else if (paginationModel.Entity == "product") { - datatableData = _datatableRepository.GetToDatatableProduct(paginationFilter.PageNumber, paginationFilter.PageSize).ToList(); + datatableData = _datatableRepository.GetToDatatableProduct(paginationModel.PageNumber, paginationModel.PageSize).ToList(); } - else if (paginationFilter.Entity == "supplier") + else if (paginationModel.Entity == "supplier") { - datatableData = _datatableRepository.GetToDatatableSupplier(paginationFilter.PageNumber, paginationFilter.PageSize).ToList(); + datatableData = _datatableRepository.GetToDatatableSupplier(paginationModel.PageNumber, paginationModel.PageSize).ToList(); } diff --git a/src/Modules/Infra/Dispo.Infra.Core.Application/Dispo.Infra.Core.Application.csproj b/src/Modules/Infra/Dispo.Infra.Core.Application/Dispo.Infra.Core.Application.csproj index 9b2c1f3..50e206a 100644 --- a/src/Modules/Infra/Dispo.Infra.Core.Application/Dispo.Infra.Core.Application.csproj +++ b/src/Modules/Infra/Dispo.Infra.Core.Application/Dispo.Infra.Core.Application.csproj @@ -12,8 +12,8 @@ - - + + diff --git a/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs b/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs index e04c951..0a0024b 100644 --- a/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs +++ b/src/Modules/Infra/Dispo.Infra.Infrastructure.Persistence/Repositories/DatatableRepository.cs @@ -4,6 +4,7 @@ using Dispo.Shared.Infrastructure.Persistence; using Dispo.Shared.Infrastructure.Persistence.Context; using Dispo.Shared.Utils.Extensions; +using Microsoft.EntityFrameworkCore; namespace Dispo.Infra.Infrastructure.Persistence.Repositories { @@ -16,8 +17,10 @@ public DatatableRepository(DispoContext dispoContext) : base(dispoContext) _dispoContext = dispoContext; } - public int GetTotalRecords() - => _dispoContext.Manufacturers.Count(); + public int GetTotalRecords() where T : EntityBase + => _dispoContext.Set() + .AsNoTracking() + .Count(); //public IEnumerable GetToDatatable(int pageNumber, int pageSize) // => _dispoContext.Manufacturers.Skip((pageNumber - 1) * pageSize) diff --git a/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs b/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs index d55b925..0f18ddf 100644 --- a/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs +++ b/src/Modules/Shared/Dispo.Shared.Core.Domain/Interfaces/IDatatableRepository.cs @@ -5,7 +5,7 @@ namespace Dispo.Shared.Core.Domain.Interfaces { public interface IDatatableRepository { - int GetTotalRecords(); + int GetTotalRecords() where T : EntityBase; IEnumerable GetToDatatable(int pageNumber, int pageSize) where TEntity : EntityBase; IEnumerable GetToDatatableProduct(int pageNumber, int pageSize); IEnumerable GetToDatatableManufacturer(int pageNumber, int pageSize); diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Model/FilterModel.cs b/src/Modules/Shared/Dispo.Shared.Filter/Model/FilterModel.cs index ae818dd..994c5c3 100644 --- a/src/Modules/Shared/Dispo.Shared.Filter/Model/FilterModel.cs +++ b/src/Modules/Shared/Dispo.Shared.Filter/Model/FilterModel.cs @@ -4,5 +4,12 @@ public class FilterModel { public required string Entity { get; set; } public required List Properties { get; set; } + public required PaginationFilter PaginationConfig { get; set; } + } + + public class PaginationFilter + { + public int PageNumber { get; set; } + public int PageSize { get; set; } } } diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Model/PaginationFilter.cs b/src/Modules/Shared/Dispo.Shared.Filter/Model/PaginationFilter.cs index 0489078..54ef0f4 100644 --- a/src/Modules/Shared/Dispo.Shared.Filter/Model/PaginationFilter.cs +++ b/src/Modules/Shared/Dispo.Shared.Filter/Model/PaginationFilter.cs @@ -1,6 +1,6 @@ namespace Dispo.Shared.Filter.Model { - public class PaginationFilter + public class PaginationModel { public string Entity { get; set; } public int PageNumber { get; set; } diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs b/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs index 6b910ee..c7a8996 100644 --- a/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs +++ b/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs @@ -4,5 +4,18 @@ public class PropertyModel { public string Name { get; set; } public string Value { get; set; } + public SearchType SearchType { get; set; } + } + + public enum SearchType + { + Equals, + Contains, + StartsWith, + EndsWith, + GreaterThan, + GreaterThanOrEqual, + LessThan, + LessThanOrEqual } } diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs b/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs index 1c67fc6..7e2f7ca 100644 --- a/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs +++ b/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs @@ -15,12 +15,29 @@ public FilterService(DispoContext dispoContext) _dispoContext = dispoContext; } - public List Get(FilterModel filterModel) where T : EntityBase + public object Get(FilterModel filterModel) where T : EntityBase { - return _dispoContext.Set() + var a = _dispoContext.Products.Where(x => x.Name.Contains("cola")).ToList(); + + var recordCount = _dispoContext.Set() + .AsNoTracking() + .Where(BuildExpression(filterModel)) + .Count(); + + var records = _dispoContext.Set() .AsNoTracking() .Where(BuildExpression(filterModel)) + .Skip((filterModel.PaginationConfig.PageNumber - 1) * filterModel.PaginationConfig.PageSize) + .Take(filterModel.PaginationConfig.PageSize) .ToList(); + + var obj = new + { + RecordCount = recordCount, + Records = records + }; + + return obj; } private Func BuildExpression(FilterModel filterModel) @@ -35,11 +52,33 @@ private Func BuildExpression(FilterModel filterModel) if (memberExpression.Type == typeof(string)) { comparison = Expression.Call(memberExpression, "Contains", Type.EmptyTypes, constant); + comparison = Expression.Call(memberExpression, property.SearchType.ToString(), Type.EmptyTypes, constant); } else { constant = Expression.Constant(Convert.ToInt32(property.Value)); comparison = Expression.Equal(memberExpression, constant); + //switch (property.SearchType) + //{ + // case SearchType.Equals: + // comparison = Expression.Equal(memberExpression, constant.Value); + // break; + // case SearchType.GreaterThan: + // comparison = Expression.GreaterThan(memberExpression, constant.Value); + // break; + // case SearchType.GreaterThanOrEqual: + // comparison = Expression.GreaterThanOrEqual(memberExpression, constant.Value); + // break; + // case SearchType.LessThan: + // comparison = Expression.LessThan(memberExpression, constant.Value); + // break; + // case SearchType.LessThanOrEqual: + // comparison = Expression.LessThanOrEqual(memberExpression, constant.Value); + // break; + // default: + // comparison = Expression.Equal(memberExpression, constant.Value); + // break; + //} } filterExpression = filterExpression == null ? comparison : Expression.And(filterExpression, comparison); diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Services/IFilterService.cs b/src/Modules/Shared/Dispo.Shared.Filter/Services/IFilterService.cs index d0edca9..16ff635 100644 --- a/src/Modules/Shared/Dispo.Shared.Filter/Services/IFilterService.cs +++ b/src/Modules/Shared/Dispo.Shared.Filter/Services/IFilterService.cs @@ -5,6 +5,6 @@ namespace Dispo.Shared.Filter.Services { public interface IFilterService { - List Get(FilterModel filterModel) where T : EntityBase; + object Get(FilterModel filterModel) where T : EntityBase; } } From ab95d1c39b92c9cd42615b40cf9e516ace83e468 Mon Sep 17 00:00:00 2001 From: Matheus Teixeira Date: Tue, 27 Feb 2024 01:04:59 -0300 Subject: [PATCH 5/5] UP --- .../Controllers/DatatableController.cs | 6 +- .../Model/PropertyModel.cs | 2 +- .../Services/FilterService.cs | 131 +++++++++++++----- 3 files changed, 104 insertions(+), 35 deletions(-) diff --git a/API/Dispo.API/Controllers/DatatableController.cs b/API/Dispo.API/Controllers/DatatableController.cs index 12fa7af..b8108f4 100644 --- a/API/Dispo.API/Controllers/DatatableController.cs +++ b/API/Dispo.API/Controllers/DatatableController.cs @@ -50,15 +50,15 @@ public IActionResult Get([FromQuery] PaginationModel paginationModel) { dynamic datatableData = null; - if (paginationModel.Entity == "manufacturer") + if (paginationModel.Entity == "Manufacturer") { datatableData = _datatableRepository.GetToDatatableManufacturer(paginationModel.PageNumber, paginationModel.PageSize).ToList(); } - else if (paginationModel.Entity == "product") + else if (paginationModel.Entity == "Product") { datatableData = _datatableRepository.GetToDatatableProduct(paginationModel.PageNumber, paginationModel.PageSize).ToList(); } - else if (paginationModel.Entity == "supplier") + else if (paginationModel.Entity == "Supplier") { datatableData = _datatableRepository.GetToDatatableSupplier(paginationModel.PageNumber, paginationModel.PageSize).ToList(); } diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs b/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs index c7a8996..d85bcae 100644 --- a/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs +++ b/src/Modules/Shared/Dispo.Shared.Filter/Model/PropertyModel.cs @@ -3,7 +3,7 @@ public class PropertyModel { public string Name { get; set; } - public string Value { get; set; } + public dynamic Value { get; set; } public SearchType SearchType { get; set; } } diff --git a/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs b/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs index 7e2f7ca..a66b273 100644 --- a/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs +++ b/src/Modules/Shared/Dispo.Shared.Filter/Services/FilterService.cs @@ -1,13 +1,17 @@ using Dispo.Shared.Core.Domain.Entities; +using Dispo.Shared.Core.Domain.Enums; using Dispo.Shared.Filter.Model; using Dispo.Shared.Infrastructure.Persistence.Context; using Microsoft.EntityFrameworkCore; using System.Linq.Expressions; +using System.Reflection.Metadata; +using System.Text.Json; namespace Dispo.Shared.Filter.Services { public class FilterService : IFilterService { + private const string UnsupportedSearchTypeMessage = "Unsupported search type for property of type:"; private readonly DispoContext _dispoContext; public FilterService(DispoContext dispoContext) @@ -17,16 +21,21 @@ public FilterService(DispoContext dispoContext) public object Get(FilterModel filterModel) where T : EntityBase { - var a = _dispoContext.Products.Where(x => x.Name.Contains("cola")).ToList(); + if (filterModel is null) + { + throw new ArgumentNullException(nameof(filterModel)); + } + + var buildExpression = BuildExpression(filterModel); var recordCount = _dispoContext.Set() .AsNoTracking() - .Where(BuildExpression(filterModel)) + .Where(buildExpression) .Count(); var records = _dispoContext.Set() .AsNoTracking() - .Where(BuildExpression(filterModel)) + .Where(buildExpression) .Skip((filterModel.PaginationConfig.PageNumber - 1) * filterModel.PaginationConfig.PageSize) .Take(filterModel.PaginationConfig.PageSize) .ToList(); @@ -46,45 +55,105 @@ private Func BuildExpression(FilterModel filterModel) Expression filterExpression = null; foreach (var property in filterModel.Properties) { - var memberExpression = Expression.Property(parameter, property.Name); - var constant = Expression.Constant(property.Value); + JsonElement jsonElementValue = property.Value; + + var valueType = jsonElementValue.ValueKind; Expression comparison; - if (memberExpression.Type == typeof(string)) + var memberExpression = Expression.Property(parameter, property.Name); + + if (valueType == JsonValueKind.String) // String { - comparison = Expression.Call(memberExpression, "Contains", Type.EmptyTypes, constant); + var valor = jsonElementValue.GetString(); + var constant = Expression.Constant(valor); + comparison = Expression.Call(memberExpression, property.SearchType.ToString(), Type.EmptyTypes, constant); } - else + else if (IsNumericType(memberExpression.Type, property.Value, out ConstantExpression convertedConstant) && valueType == JsonValueKind.Number) // Numerico + { + comparison = GetGenericComparisonExpression(memberExpression, property, convertedConstant); + } + else if (valueType == JsonValueKind.Object) // Enum { - constant = Expression.Constant(Convert.ToInt32(property.Value)); + var valor = jsonElementValue.GetProperty("value").GetInt64(); + var convertedValue = Enum.Parse(memberExpression.Type, valor.ToString()); + var constant = Expression.Constant(convertedValue); comparison = Expression.Equal(memberExpression, constant); - //switch (property.SearchType) - //{ - // case SearchType.Equals: - // comparison = Expression.Equal(memberExpression, constant.Value); - // break; - // case SearchType.GreaterThan: - // comparison = Expression.GreaterThan(memberExpression, constant.Value); - // break; - // case SearchType.GreaterThanOrEqual: - // comparison = Expression.GreaterThanOrEqual(memberExpression, constant.Value); - // break; - // case SearchType.LessThan: - // comparison = Expression.LessThan(memberExpression, constant.Value); - // break; - // case SearchType.LessThanOrEqual: - // comparison = Expression.LessThanOrEqual(memberExpression, constant.Value); - // break; - // default: - // comparison = Expression.Equal(memberExpression, constant.Value); - // break; - //} + + } + else if (IsDateTimeType(memberExpression.Type, property.Value, out DateTime convertedDateTime)) + { + comparison = GetGenericComparisonExpression(memberExpression, property, Expression.Constant(convertedDateTime)); + } + else + { + throw new NotSupportedException($"{UnsupportedSearchTypeMessage} {property.SearchType}"); } filterExpression = filterExpression == null ? comparison : Expression.And(filterExpression, comparison); } - return Expression.Lambda>(filterExpression, parameter).Compile(); + return Expression.Lambda>(filterExpression ?? Expression.Constant(true), parameter).Compile(); + } + + private Expression GetStringComparisonExpression(MemberExpression memberExpression, PropertyModel property) + { + string convertedValue = Convert.ToString(property.Value); + var constant = Expression.Constant(convertedValue); + + // Ao enviar o SearchType.Equals está disparando uma exceção. + return Expression.Call(memberExpression, property.SearchType.ToString(), Type.EmptyTypes, constant); } + + private Expression GetGenericComparisonExpression(MemberExpression memberExpression, PropertyModel property, ConstantExpression convertedConstant) + { + switch (property.SearchType) + { + case SearchType.Equals: + return Expression.Equal(memberExpression, convertedConstant); + case SearchType.GreaterThan: + return Expression.GreaterThan(memberExpression, convertedConstant); + case SearchType.GreaterThanOrEqual: + return Expression.GreaterThanOrEqual(memberExpression, convertedConstant); + case SearchType.LessThan: + return Expression.LessThan(memberExpression, convertedConstant); + case SearchType.LessThanOrEqual: + return Expression.LessThanOrEqual(memberExpression, convertedConstant); + default: + throw new NotSupportedException($"{UnsupportedSearchTypeMessage} {property.SearchType}"); + } + } + + private bool IsNumericType(Type type, object value, out ConstantExpression convertedConstant) + { + convertedConstant = null; + if (NumericTypes.Contains(type)) + { + try + { + var convertedValue = Convert.ChangeType(Convert.ToString(value), type); + convertedConstant = Expression.Constant(convertedValue); + return true; + } + catch (InvalidCastException) + { + return false; + } + } + + return false; + } + + private bool IsDateTimeType(Type type, object value, out DateTime convertedDateTime) + { + convertedDateTime = DateTime.MinValue; + return type == typeof(DateTime) && DateTime.TryParse(Convert.ToString(value), out convertedDateTime); + } + + private static readonly HashSet NumericTypes = new HashSet + { + typeof(int), typeof(double), typeof(float), typeof(decimal), + typeof(long), typeof(short), typeof(byte), typeof(uint), + typeof(ulong), typeof(ushort), typeof(sbyte) + }; } }