Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Refactoring Specification Query #471

Merged
merged 1 commit into from
Aug 10, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,16 @@

using CleanArchitecture.Blazor.Application.Features.AuditTrails.Caching;
using CleanArchitecture.Blazor.Application.Features.AuditTrails.DTOs;
using CleanArchitecture.Blazor.Domain.Enums;
using CleanArchitecture.Blazor.Application.Features.AuditTrails.Queries.Specification;

namespace CleanArchitecture.Blazor.Application.Features.AuditTrails.Queries.PaginationQuery;

public class AuditTrailsWithPaginationQuery : PaginationFilter, ICacheableRequest<PaginatedData<AuditTrailDto>>
public class AuditTrailsWithPaginationQuery : AuditTrailAdvancedFilter, ICacheableRequest<PaginatedData<AuditTrailDto>>
{
public AuditType? AuditType { get; set; }
public AuditTrailListView ListView { get; set; } = AuditTrailListView.All;

public string CacheKey => AuditTrailsCacheKey.GetPaginationCacheKey($"{this}");
public UserProfile? CurrentUser { get; set; }
public MemoryCacheEntryOptions? Options => AuditTrailsCacheKey.MemoryCacheEntryOptions;
public AuditTrailsQuerySpec Specification => new AuditTrailsQuerySpec(this);
public AuditTrailAdvancedSpecification Specification => new AuditTrailAdvancedSpecification(this);
public override string ToString()
{
return
Expand Down Expand Up @@ -49,32 +47,4 @@ public async Task<PaginatedData<AuditTrailDto>> Handle(AuditTrailsWithPagination
}
}

public enum AuditTrailListView
{
[Description("All")] All,
[Description("My Change Histories")] My,
[Description("Created Toady")] CreatedToday,
[Description("View of the last 30 days")]
Last30days
}
public class AuditTrailsQuerySpec : Specification<AuditTrail>
{
public AuditTrailsQuerySpec(AuditTrailsWithPaginationQuery request)
{
var today = DateTime.Now.Date;
var start = Convert.ToDateTime(today.ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 00:00:00",
CultureInfo.CurrentCulture);
var end = Convert.ToDateTime(today.ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 23:59:59",
CultureInfo.CurrentCulture);
var last30day = Convert.ToDateTime(
today.AddDays(-30).ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 00:00:00",
CultureInfo.CurrentCulture);

Query.Where(p => p.AuditType==request.AuditType, request.AuditType is not null)
.Where(p => p.UserId == request.CurrentUser.UserId, request.ListView == AuditTrailListView.My && request.CurrentUser is not null)
.Where(p => p.DateTime.Date == DateTime.Now.Date, request.ListView == AuditTrailListView.CreatedToday)
.Where(p => p.DateTime >= last30day, request.ListView == AuditTrailListView.Last30days)
.Where(x => x.TableName.Contains(request.Keyword) , !string.IsNullOrEmpty(request.Keyword));

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
using CleanArchitecture.Blazor.Domain.Enums;

namespace CleanArchitecture.Blazor.Application.Features.AuditTrails.Queries.Specification;
public enum AuditTrailListView
{
[Description("All")] All,
[Description("My Change Histories")] My,
[Description("Created Toady")] CreatedToday,
[Description("View of the last 30 days")]
Last30days
}
public class AuditTrailAdvancedFilter : PaginationFilter
{
public AuditType? AuditType { get; set; }
public AuditTrailListView ListView { get; set; } = AuditTrailListView.All;
public UserProfile? CurrentUser { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace CleanArchitecture.Blazor.Application.Features.AuditTrails.Queries.Specification;

public class AuditTrailAdvancedSpecification : Specification<AuditTrail>
{
public AuditTrailAdvancedSpecification(AuditTrailAdvancedFilter filter)
{
var today = DateTime.Now.Date;
var start = Convert.ToDateTime(today.ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 00:00:00",
CultureInfo.CurrentCulture);
var end = Convert.ToDateTime(today.ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 23:59:59",
CultureInfo.CurrentCulture);
var last30day = Convert.ToDateTime(
today.AddDays(-30).ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 00:00:00",
CultureInfo.CurrentCulture);

Query.Where(p => p.AuditType == filter.AuditType, filter.AuditType is not null)
.Where(p => p.UserId == filter.CurrentUser.UserId, filter.ListView == AuditTrailListView.My && filter.CurrentUser is not null)
.Where(p => p.DateTime.Date == DateTime.Now.Date, filter.ListView == AuditTrailListView.CreatedToday)
.Where(p => p.DateTime >= last30day, filter.ListView == AuditTrailListView.Last30days)
.Where(x => x.TableName.Contains(filter.Keyword), !string.IsNullOrEmpty(filter.Keyword));

}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel;
using CleanArchitecture.Blazor.Application.Features.Customers.DTOs;
using CleanArchitecture.Blazor.Application.Features.Customers.Caching;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.ComponentModel;
using CleanArchitecture.Blazor.Application.Features.Customers.DTOs;
using CleanArchitecture.Blazor.Application.Features.Customers.Caching;

Expand Down
1 change: 1 addition & 0 deletions src/Application/Features/Customers/DTOs/CustomerDto.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.ComponentModel;
namespace CleanArchitecture.Blazor.Application.Features.Customers.DTOs;

[Description("Customers")]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.


using CleanArchitecture.Blazor.Application.Features.Customers.DTOs;
using CleanArchitecture.Blazor.Application.Features.Customers.Queries.Pagination;
using CleanArchitecture.Blazor.Application.Features.Customers.Queries.Specification;

namespace CleanArchitecture.Blazor.Application.Features.Customers.Queries.Export;

public class ExportCustomersQuery : BaseFilter, IRequest<Result<byte[]>>
public class ExportCustomersQuery : CustomerAdvancedFilter, IRequest<Result<byte[]>>
{
public string OrderBy { get; set; } = "Id";
public string SortDirection { get; set; } = "Descending";
public CustomerListView ListView { get; set; } = CustomerListView.All;
public UserProfile? CurrentUser { get; set; }
public CustomersExportSpecification Specification => new CustomersExportSpecification(this);
public CustomerAdvancedPaginationSpec Specification => new CustomerAdvancedPaginationSpec(this);
}

public class ExportCustomersQueryHandler :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,39 @@

namespace CleanArchitecture.Blazor.Application.Features.Customers.Queries.GetAll;

public class GetAllCustomersQuery : ICacheableRequest<IEnumerable<CustomerDto>>
public class GetAllCustomersQuery : ICacheableRequest<IEnumerable<CustomerDto>>
{
public string CacheKey => CustomerCacheKey.GetAllCacheKey;
public MemoryCacheEntryOptions? Options => CustomerCacheKey.MemoryCacheEntryOptions;
}

public class GetAllCustomersQueryHandler :
IRequestHandler<GetAllCustomersQuery, IEnumerable<CustomerDto>>
{
private readonly IApplicationDbContext _context;
private readonly IMapper _mapper;
private readonly IStringLocalizer<GetAllCustomersQueryHandler> _localizer;

public GetAllCustomersQueryHandler(
IApplicationDbContext context,
IMapper mapper,
IStringLocalizer<GetAllCustomersQueryHandler> localizer
)
{
public string CacheKey => CustomerCacheKey.GetAllCacheKey;
public MemoryCacheEntryOptions? Options => CustomerCacheKey.MemoryCacheEntryOptions;
_context = context;
_mapper = mapper;
_localizer = localizer;
}

public class GetAllCustomersQueryHandler :
IRequestHandler<GetAllCustomersQuery, IEnumerable<CustomerDto>>

public async Task<IEnumerable<CustomerDto>> Handle(GetAllCustomersQuery request, CancellationToken cancellationToken)
{
private readonly IApplicationDbContext _context;
private readonly IMapper _mapper;
private readonly IStringLocalizer<GetAllCustomersQueryHandler> _localizer;

public GetAllCustomersQueryHandler(
IApplicationDbContext context,
IMapper mapper,
IStringLocalizer<GetAllCustomersQueryHandler> localizer
)
{
_context = context;
_mapper = mapper;
_localizer = localizer;
}

public async Task<IEnumerable<CustomerDto>> Handle(GetAllCustomersQuery request, CancellationToken cancellationToken)
{
// TODO: Implement GetAllCustomersQueryHandler method
var data = await _context.Customers
.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider)
.AsNoTracking()
.ToListAsync(cancellationToken);
return data;
}
// TODO: Implement GetAllCustomersQueryHandler method
var data = await _context.Customers
.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider)
.AsNoTracking()
.ToListAsync(cancellationToken);
return data;
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -6,39 +6,37 @@

namespace CleanArchitecture.Blazor.Application.Features.Customers.Queries.GetById;

public class GetCustomerByIdQuery : ICacheableRequest<CustomerDto>
{
public required int Id { get; set; }
public string CacheKey => CustomerCacheKey.GetByIdCacheKey($"{Id}");
public MemoryCacheEntryOptions? Options => CustomerCacheKey.MemoryCacheEntryOptions;
}

public class GetCustomerByIdQueryHandler :
IRequestHandler<GetCustomerByIdQuery, CustomerDto>
{
private readonly IApplicationDbContext _context;
private readonly IMapper _mapper;
private readonly IStringLocalizer<GetCustomerByIdQueryHandler> _localizer;
public class GetCustomerByIdQuery : ICacheableRequest<CustomerDto>
{
public required int Id { get; set; }
public string CacheKey => CustomerCacheKey.GetByIdCacheKey($"{Id}");
public MemoryCacheEntryOptions? Options => CustomerCacheKey.MemoryCacheEntryOptions;
}

public GetCustomerByIdQueryHandler(
IApplicationDbContext context,
IMapper mapper,
IStringLocalizer<GetCustomerByIdQueryHandler> localizer
)
{
_context = context;
_mapper = mapper;
_localizer = localizer;
}
public class GetCustomerByIdQueryHandler :
IRequestHandler<GetCustomerByIdQuery, CustomerDto>
{
private readonly IApplicationDbContext _context;
private readonly IMapper _mapper;
private readonly IStringLocalizer<GetCustomerByIdQueryHandler> _localizer;

public async Task<CustomerDto> Handle(GetCustomerByIdQuery request, CancellationToken cancellationToken)
{
// TODO: Implement GetCustomerByIdQueryHandler method
var data = await _context.Customers.Where(x => x.Id == request.Id)
.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider)
.FirstAsync(cancellationToken) ?? throw new NotFoundException($"Customer with id: [{request.Id}] not found.");;
return data;
}
public GetCustomerByIdQueryHandler(
IApplicationDbContext context,
IMapper mapper,
IStringLocalizer<GetCustomerByIdQueryHandler> localizer
)
{
_context = context;
_mapper = mapper;
_localizer = localizer;
}


public async Task<CustomerDto> Handle(GetCustomerByIdQuery request, CancellationToken cancellationToken)
{
// TODO: Implement GetCustomerByIdQueryHandler method
var data = await _context.Customers.ApplySpecification(new CustomerByIdSpec(request.Id))
.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider)
.FirstAsync(cancellationToken) ?? throw new NotFoundException($"Customer with id: [{request.Id}] not found.");;
return data;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@

using CleanArchitecture.Blazor.Application.Features.Customers.DTOs;
using CleanArchitecture.Blazor.Application.Features.Customers.Caching;
using CleanArchitecture.Blazor.Application.Features.Customers.Queries.Specification;

namespace CleanArchitecture.Blazor.Application.Features.Customers.Queries.Pagination;

public class CustomersWithPaginationQuery : PaginationFilter, ICacheableRequest<PaginatedData<CustomerDto>>
public class CustomersWithPaginationQuery : CustomerAdvancedFilter, ICacheableRequest<PaginatedData<CustomerDto>>
{
public CustomerListView ListView { get; set; } = CustomerListView.All;
public UserProfile? CurrentUser { get; set; }
public override string ToString()
{
return $"Listview:{ListView}, Search:{Keyword}, {OrderBy}, {SortDirection}, {PageNumber}, {PageSize}";
}
public string CacheKey => CustomerCacheKey.GetPaginationCacheKey($"{this}");
public MemoryCacheEntryOptions? Options => CustomerCacheKey.MemoryCacheEntryOptions;
public CustomersPaginationSpecification Specification => new CustomersPaginationSpecification(this);
public CustomerAdvancedPaginationSpec Specification => new CustomerAdvancedPaginationSpec(this);
}

public class CustomersWithPaginationQueryHandler :
Expand All @@ -41,41 +40,7 @@ public async Task<PaginatedData<CustomerDto>> Handle(CustomersWithPaginationQuer
{
// TODO: Implement CustomersWithPaginationQueryHandler method
var data = await _context.Customers.OrderBy($"{request.OrderBy} {request.SortDirection}")
.ProjectToPaginatedDataAsync<Customer, CustomerDto>(request.Specification, request.PageNumber, request.PageSize, _mapper.ConfigurationProvider, cancellationToken);
return data;
.ProjectToPaginatedDataAsync<Customer, CustomerDto>(request.Specification, request.PageNumber, request.PageSize, _mapper.ConfigurationProvider, cancellationToken);
return data;
}
}

public class CustomersPaginationSpecification : Specification<Customer>
{
public CustomersPaginationSpecification(CustomersWithPaginationQuery query)
{
var today = DateTime.Now.Date;
var start = Convert.ToDateTime(today.ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 00:00:00",
CultureInfo.CurrentCulture);
var end = Convert.ToDateTime(today.ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 23:59:59",
CultureInfo.CurrentCulture);
var last30day = Convert.ToDateTime(
today.AddDays(-30).ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 00:00:00",
CultureInfo.CurrentCulture);

Query.Where(q => q.Name != null)
.Where(q => q.Name!.Contains(query.Keyword) || q.Description!.Contains(query.Keyword), !string.IsNullOrEmpty(query.Keyword))
.Where(q => q.CreatedBy == query.CurrentUser.UserId, query.ListView == CustomerListView.My && query.CurrentUser is not null)
.Where(q => q.Created >= start && q.Created <= end, query.ListView == CustomerListView.CreatedToday)
.Where(q => q.Created >= last30day, query.ListView == CustomerListView.Created30Days);

}
}

public enum CustomerListView
{
[Description("All")]
All,
[Description("My")]
My,
[Description("Created Toady")]
CreatedToday,
[Description("Created within the last 30 days")]
Created30Days
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
namespace CleanArchitecture.Blazor.Application.Features.Customers.Queries.Specification;

public enum CustomerListView
{
[Description("All")]
All,
[Description("My")]
My,
[Description("Created Toady")]
CreatedToday,
[Description("Created within the last 30 days")]
Created30Days
}

public class CustomerAdvancedFilter: PaginationFilter
{
public CustomerListView ListView { get; set; } = CustomerListView.All;
public UserProfile? CurrentUser { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace CleanArchitecture.Blazor.Application.Features.Customers.Queries.Specification;

public class CustomerAdvancedPaginationSpec : Specification<Customer>
{
public CustomerAdvancedPaginationSpec(CustomerAdvancedFilter filter)
{
var today = DateTime.Now.Date;
var start = Convert.ToDateTime(today.ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 00:00:00",
CultureInfo.CurrentCulture);
var end = Convert.ToDateTime(today.ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 23:59:59",
CultureInfo.CurrentCulture);
var last30day = Convert.ToDateTime(
today.AddDays(-30).ToString("yyyy-MM-dd", CultureInfo.CurrentCulture) + " 00:00:00",
CultureInfo.CurrentCulture);

Query.Where(q => q.Name != null)
.Where(q => q.Name!.Contains(filter.Keyword) || q.Description!.Contains(filter.Keyword), !string.IsNullOrEmpty(filter.Keyword))
.Where(q => q.CreatedBy == filter.CurrentUser.UserId, filter.ListView == CustomerListView.My && filter.CurrentUser is not null)
.Where(q => q.Created >= start && q.Created <= end, filter.ListView == CustomerListView.CreatedToday)
.Where(q => q.Created >= last30day, filter.ListView == CustomerListView.Created30Days);

}
}
Loading