feat(transactions): enhance transaction filtering and summary capabilities
Build and Deploy to Kubernetes / build-and-deploy (push) Has been cancelled

- Added new date range filters (CreatedFrom, CreatedTo, PaymentDateFrom, PaymentDateTo) to GetAllTransactionsByFilterQuery for improved transaction querying.
- Updated GetAllTransactionsByFilterQueryHandler to apply new filters and return detailed transaction models.
- Introduced GetTransactionSummary RPC method in Protobuf for summarizing transaction data.
- Enhanced mapping configurations to accommodate new filter properties and response models.
- Bumped Protobuf project version to reflect the addition of new features.
This commit is contained in:
masoodafar-web
2026-06-26 16:33:20 +03:30
parent 6c3fbe43b1
commit 58aeddf004
11 changed files with 214 additions and 23 deletions
@@ -26,4 +26,8 @@ public record GetAllTransactionsByFilterQuery : IRequest<GetAllTransactionsByFil
public string? RefId { get; set; }
//
public TransactionType? Type { get; set; }
public DateTime? CreatedFrom { get; set; }
public DateTime? CreatedTo { get; set; }
public DateTime? PaymentDateFrom { get; set; }
public DateTime? PaymentDateTo { get; set; }
}
@@ -1,4 +1,5 @@
namespace CMSMicroservice.Application.TransactionsCQ.Queries.GetAllTransactionsByFilter;
public class GetAllTransactionsByFilterQueryHandler : IRequestHandler<GetAllTransactionsByFilterQuery, GetAllTransactionsByFilterResponseDto>
{
private readonly IApplicationDbContext _context;
@@ -11,26 +12,27 @@ public class GetAllTransactionsByFilterQueryHandler : IRequestHandler<GetAllTran
public async Task<GetAllTransactionsByFilterResponseDto> Handle(GetAllTransactionsByFilterQuery request, CancellationToken cancellationToken)
{
var query = _context.Transactions
.ApplyOrder(sortBy: request.SortBy)
.AsNoTracking()
.AsQueryable();
if (request.Filter is not null)
{
query = query
.Where(x => request.Filter.Id == null || x.Id == request.Filter.Id)
.Where(x => request.Filter.Amount == null || x.Amount == request.Filter.Amount)
.Where(x => request.Filter.Description == null || x.Description.Contains(request.Filter.Description))
.Where(x => request.Filter.PaymentStatus == null || x.PaymentStatus== request.Filter.PaymentStatus)
.Where(x => request.Filter.PaymentDate == null || x.PaymentDate == request.Filter.PaymentDate)
.Where(x => request.Filter.RefId == null || x.RefId.Contains(request.Filter.RefId))
.Where(x => request.Filter.Type == null || x.Type == request.Filter.Type)
;
}
.ApplyTransactionFilter(request.Filter)
.ApplyOrder(sortBy: request.SortBy ?? "-Created");
return new GetAllTransactionsByFilterResponseDto
{
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
Models = await query.PaginatedListAsync(paginationState: request.PaginationState)
.ProjectToType<GetAllTransactionsByFilterResponseModel>().ToListAsync(cancellationToken)
};
Models = await query
.PaginatedListAsync(paginationState: request.PaginationState)
.Select(x => new GetAllTransactionsByFilterResponseModel
{
Id = x.Id,
Amount = x.Amount,
Description = x.Description,
PaymentStatus = x.PaymentStatus,
PaymentDate = x.PaymentDate,
RefId = x.RefId,
Type = x.Type,
Created = x.Created
})
.ToListAsync(cancellationToken)
};
}
}
@@ -24,4 +24,5 @@ public class GetAllTransactionsByFilterResponseDto
public string? RefId { get; set; }
//
public TransactionType Type { get; set; }
public DateTime Created { get; set; }
}
@@ -0,0 +1,48 @@
using CMSMicroservice.Domain.Entities;
namespace CMSMicroservice.Application.TransactionsCQ.Queries.GetAllTransactionsByFilter;
public static class TransactionFilterExtensions
{
public static IQueryable<Transaction> ApplyTransactionFilter(
this IQueryable<Transaction> query,
GetAllTransactionsByFilterFilter? filter)
{
if (filter == null) return query;
if (filter.Id.HasValue)
query = query.Where(x => x.Id == filter.Id.Value);
if (filter.Amount.HasValue)
query = query.Where(x => x.Amount == filter.Amount.Value);
if (!string.IsNullOrWhiteSpace(filter.Description))
query = query.Where(x => x.Description.Contains(filter.Description));
if (filter.PaymentStatus.HasValue)
query = query.Where(x => x.PaymentStatus == filter.PaymentStatus.Value);
if (filter.PaymentDate.HasValue)
query = query.Where(x => x.PaymentDate == filter.PaymentDate.Value);
if (!string.IsNullOrWhiteSpace(filter.RefId))
query = query.Where(x => x.RefId != null && x.RefId.Contains(filter.RefId));
if (filter.Type.HasValue)
query = query.Where(x => x.Type == filter.Type.Value);
if (filter.CreatedFrom.HasValue)
query = query.Where(x => x.Created >= filter.CreatedFrom.Value);
if (filter.CreatedTo.HasValue)
query = query.Where(x => x.Created <= filter.CreatedTo.Value);
if (filter.PaymentDateFrom.HasValue)
query = query.Where(x => x.PaymentDate >= filter.PaymentDateFrom.Value);
if (filter.PaymentDateTo.HasValue)
query = query.Where(x => x.PaymentDate <= filter.PaymentDateTo.Value);
return query;
}
}
@@ -0,0 +1,17 @@
using CMSMicroservice.Application.TransactionsCQ.Queries.GetAllTransactionsByFilter;
namespace CMSMicroservice.Application.TransactionsCQ.Queries.GetTransactionSummary;
public record GetTransactionSummaryQuery : IRequest<GetTransactionSummaryResponseDto>
{
public GetAllTransactionsByFilterFilter? Filter { get; init; }
}
public class GetTransactionSummaryResponseDto
{
public long TotalCount { get; set; }
public long TotalAmount { get; set; }
public long SuccessCount { get; set; }
public long PendingCount { get; set; }
public long RejectCount { get; set; }
}
@@ -0,0 +1,39 @@
using CMSMicroservice.Application.TransactionsCQ.Queries.GetAllTransactionsByFilter;
using CMSMicroservice.Domain.Enums;
namespace CMSMicroservice.Application.TransactionsCQ.Queries.GetTransactionSummary;
public class GetTransactionSummaryQueryHandler
: IRequestHandler<GetTransactionSummaryQuery, GetTransactionSummaryResponseDto>
{
private readonly IApplicationDbContext _context;
public GetTransactionSummaryQueryHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<GetTransactionSummaryResponseDto> Handle(
GetTransactionSummaryQuery request,
CancellationToken cancellationToken)
{
var query = _context.Transactions
.AsNoTracking()
.ApplyTransactionFilter(request.Filter);
var totalCount = await query.LongCountAsync(cancellationToken);
var totalAmount = totalCount > 0 ? await query.SumAsync(x => x.Amount, cancellationToken) : 0;
var successCount = await query.LongCountAsync(x => x.PaymentStatus == PaymentStatus.Success, cancellationToken);
var pendingCount = await query.LongCountAsync(x => x.PaymentStatus == PaymentStatus.Pending, cancellationToken);
var rejectCount = await query.LongCountAsync(x => x.PaymentStatus == PaymentStatus.Reject, cancellationToken);
return new GetTransactionSummaryResponseDto
{
TotalCount = totalCount,
TotalAmount = totalAmount,
SuccessCount = successCount,
PendingCount = pendingCount,
RejectCount = rejectCount
};
}
}