diff --git a/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/GetAllTransactionsByFilterQuery.cs b/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/GetAllTransactionsByFilterQuery.cs index 2601756..f8f647f 100644 --- a/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/GetAllTransactionsByFilterQuery.cs +++ b/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/GetAllTransactionsByFilterQuery.cs @@ -26,4 +26,8 @@ public record GetAllTransactionsByFilterQuery : IRequest { private readonly IApplicationDbContext _context; @@ -11,26 +12,27 @@ public class GetAllTransactionsByFilterQueryHandler : IRequestHandler 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().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) + }; } } diff --git a/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/GetAllTransactionsByFilterResponseDto.cs b/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/GetAllTransactionsByFilterResponseDto.cs index 6e3937d..ed4e290 100644 --- a/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/GetAllTransactionsByFilterResponseDto.cs +++ b/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/GetAllTransactionsByFilterResponseDto.cs @@ -24,4 +24,5 @@ public class GetAllTransactionsByFilterResponseDto public string? RefId { get; set; } // public TransactionType Type { get; set; } + public DateTime Created { get; set; } } diff --git a/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/TransactionFilterExtensions.cs b/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/TransactionFilterExtensions.cs new file mode 100644 index 0000000..06dd97f --- /dev/null +++ b/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetAllTransactionsByFilter/TransactionFilterExtensions.cs @@ -0,0 +1,48 @@ +using CMSMicroservice.Domain.Entities; + +namespace CMSMicroservice.Application.TransactionsCQ.Queries.GetAllTransactionsByFilter; + +public static class TransactionFilterExtensions +{ + public static IQueryable ApplyTransactionFilter( + this IQueryable 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; + } +} diff --git a/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetTransactionSummary/GetTransactionSummaryQuery.cs b/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetTransactionSummary/GetTransactionSummaryQuery.cs new file mode 100644 index 0000000..05c24bf --- /dev/null +++ b/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetTransactionSummary/GetTransactionSummaryQuery.cs @@ -0,0 +1,17 @@ +using CMSMicroservice.Application.TransactionsCQ.Queries.GetAllTransactionsByFilter; + +namespace CMSMicroservice.Application.TransactionsCQ.Queries.GetTransactionSummary; + +public record GetTransactionSummaryQuery : IRequest +{ + 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; } +} diff --git a/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetTransactionSummary/GetTransactionSummaryQueryHandler.cs b/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetTransactionSummary/GetTransactionSummaryQueryHandler.cs new file mode 100644 index 0000000..08bc11f --- /dev/null +++ b/src/CMSMicroservice.Application/TransactionsCQ/Queries/GetTransactionSummary/GetTransactionSummaryQueryHandler.cs @@ -0,0 +1,39 @@ +using CMSMicroservice.Application.TransactionsCQ.Queries.GetAllTransactionsByFilter; +using CMSMicroservice.Domain.Enums; + +namespace CMSMicroservice.Application.TransactionsCQ.Queries.GetTransactionSummary; + +public class GetTransactionSummaryQueryHandler + : IRequestHandler +{ + private readonly IApplicationDbContext _context; + + public GetTransactionSummaryQueryHandler(IApplicationDbContext context) + { + _context = context; + } + + public async Task 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 + }; + } +} diff --git a/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj b/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj index b403094..911d4c6 100644 --- a/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj +++ b/src/CMSMicroservice.Protobuf/CMSMicroservice.Protobuf.csproj @@ -3,7 +3,7 @@ net9.0 enable enable - 0.0.202 + 0.0.203 None False False diff --git a/src/CMSMicroservice.Protobuf/Protos/public_messages.proto b/src/CMSMicroservice.Protobuf/Protos/public_messages.proto index 095918c..a3c55c6 100644 --- a/src/CMSMicroservice.Protobuf/Protos/public_messages.proto +++ b/src/CMSMicroservice.Protobuf/Protos/public_messages.proto @@ -109,6 +109,13 @@ enum TransactionType DepositIpg = 1; DepositExternal1 = 2; Withdraw = 3; + NetworkCommission = 10; + ClubActivation = 11; + DiscountWalletCharge = 12; + DiscountShopPurchase = 13; + MagicWalletDeposit = 14; + MagicWalletBonus = 15; + CreditWalletCharge = 16; } enum ContractType { diff --git a/src/CMSMicroservice.Protobuf/Protos/transactions.proto b/src/CMSMicroservice.Protobuf/Protos/transactions.proto index 2255bac..07a78ff 100644 --- a/src/CMSMicroservice.Protobuf/Protos/transactions.proto +++ b/src/CMSMicroservice.Protobuf/Protos/transactions.proto @@ -43,6 +43,11 @@ service TransactionsContract }; }; + rpc GetTransactionSummary(GetTransactionSummaryRequest) returns (GetTransactionSummaryResponse){ + option (google.api.http) = { + get: "/GetTransactionSummary" + }; + }; rpc VerifyTransaction(VerifyTransactionRequest) returns (VerifyTransactionResponse){ option (google.api.http) = { post: "/VerifyTransaction" @@ -161,6 +166,10 @@ message GetAllTransactionsByFilterFilter { messages.TransactionType type = 7; } + google.protobuf.Timestamp created_from = 8; + google.protobuf.Timestamp created_to = 9; + google.protobuf.Timestamp payment_date_from = 10; + google.protobuf.Timestamp payment_date_to = 11; } message GetAllTransactionsByFilterResponse { @@ -182,6 +191,21 @@ message GetAllTransactionsByFilterResponseModel { messages.TransactionType type = 7; } + google.protobuf.Timestamp created = 8; +} + +message GetTransactionSummaryRequest +{ + GetAllTransactionsByFilterFilter filter = 1; +} + +message GetTransactionSummaryResponse +{ + int64 total_count = 1; + int64 total_amount = 2; + int64 success_count = 3; + int64 pending_count = 4; + int64 reject_count = 5; } // VerifyTransaction Messages diff --git a/src/CMSMicroservice.WebApi/Common/Mappings/TransactionsProfile.cs b/src/CMSMicroservice.WebApi/Common/Mappings/TransactionsProfile.cs index 34689ba..f9228ad 100644 --- a/src/CMSMicroservice.WebApi/Common/Mappings/TransactionsProfile.cs +++ b/src/CMSMicroservice.WebApi/Common/Mappings/TransactionsProfile.cs @@ -1,11 +1,55 @@ +using Google.Protobuf.WellKnownTypes; +using Mapster; +using AppTx = CMSMicroservice.Application.TransactionsCQ.Queries.GetAllTransactionsByFilter; +using AppTxSummary = CMSMicroservice.Application.TransactionsCQ.Queries.GetTransactionSummary; +using ProtoTx = CMSMicroservice.Protobuf.Protos.Transactions; + namespace CMSMicroservice.WebApi.Common.Mappings; public class TransactionsProfile : IRegister { - void IRegister.Register(TypeAdapterConfig config) - { - config.NewConfig() - .IgnoreIf((src, dest) => !src.Filter.HasPaymentStatus, dest => dest.Filter.PaymentStatus) - .IgnoreIf((src, dest) => !src.Filter.HasType, dest => dest.Filter.Type); + public void Register(TypeAdapterConfig config) + { + config.NewConfig() + .Map(dest => dest.PaginationState, src => src.PaginationState) + .Map(dest => dest.SortBy, src => src.SortBy) + .Map(dest => dest.Filter, src => src.Filter); + + config.NewConfig() + .Map(dest => dest.Id, src => src.Id) + .Map(dest => dest.Amount, src => src.Amount) + .Map(dest => dest.Description, src => src.Description) + .Map(dest => dest.PaymentStatus, src => src.HasPaymentStatus ? (Domain.Enums.PaymentStatus?)src.PaymentStatus : null) + .Map(dest => dest.PaymentDate, src => src.PaymentDate != null ? src.PaymentDate.ToDateTime() : (DateTime?)null) + .Map(dest => dest.RefId, src => src.RefId) + .Map(dest => dest.Type, src => src.HasType ? (Domain.Enums.TransactionType?)src.Type : null) + .Map(dest => dest.CreatedFrom, src => src.CreatedFrom != null ? src.CreatedFrom.ToDateTime() : (DateTime?)null) + .Map(dest => dest.CreatedTo, src => src.CreatedTo != null ? src.CreatedTo.ToDateTime() : (DateTime?)null) + .Map(dest => dest.PaymentDateFrom, src => src.PaymentDateFrom != null ? src.PaymentDateFrom.ToDateTime() : (DateTime?)null) + .Map(dest => dest.PaymentDateTo, src => src.PaymentDateTo != null ? src.PaymentDateTo.ToDateTime() : (DateTime?)null); + + config.NewConfig() + .Map(dest => dest.MetaData, src => src.MetaData) + .Map(dest => dest.Models, src => src.Models); + + config.NewConfig() + .Map(dest => dest.Id, src => src.Id) + .Map(dest => dest.Amount, src => src.Amount) + .Map(dest => dest.Description, src => src.Description) + .Map(dest => dest.PaymentStatus, src => src.PaymentStatus) + .Map(dest => dest.PaymentDate, src => src.PaymentDate.HasValue ? Timestamp.FromDateTime(DateTime.SpecifyKind(src.PaymentDate.Value, DateTimeKind.Utc)) : null) + .Map(dest => dest.RefId, src => src.RefId) + .Map(dest => dest.Type, src => src.Type) + .Map(dest => dest.Created, src => Timestamp.FromDateTime(DateTime.SpecifyKind(src.Created, DateTimeKind.Utc))); + + config.NewConfig() + .Map(dest => dest.Filter, src => src.Filter); + + config.NewConfig() + .Map(dest => dest.TotalCount, src => src.TotalCount) + .Map(dest => dest.TotalAmount, src => src.TotalAmount) + .Map(dest => dest.SuccessCount, src => src.SuccessCount) + .Map(dest => dest.PendingCount, src => src.PendingCount) + .Map(dest => dest.RejectCount, src => src.RejectCount); } } diff --git a/src/CMSMicroservice.WebApi/Services/TransactionsService.cs b/src/CMSMicroservice.WebApi/Services/TransactionsService.cs index c88b48b..96c1ade 100644 --- a/src/CMSMicroservice.WebApi/Services/TransactionsService.cs +++ b/src/CMSMicroservice.WebApi/Services/TransactionsService.cs @@ -5,6 +5,7 @@ using CMSMicroservice.Application.TransactionsCQ.Commands.UpdateTransactions; using CMSMicroservice.Application.TransactionsCQ.Commands.DeleteTransactions; using CMSMicroservice.Application.TransactionsCQ.Queries.GetTransactions; using CMSMicroservice.Application.TransactionsCQ.Queries.GetAllTransactionsByFilter; +using CMSMicroservice.Application.TransactionsCQ.Queries.GetTransactionSummary; using CMSMicroservice.Application.TransactionsCQ.Commands.VerifyTransaction; using CMSMicroservice.Application.TransactionsCQ.Commands.RefundTransaction; using CMSMicroservice.Application.TransactionsCQ.Queries.GetCustomerTransaction; @@ -69,6 +70,10 @@ public class TransactionsService : TransactionsContract.TransactionsContractBase { return await _dispatchRequestToCQRS.Handle(request, context); } + + public override Task GetTransactionSummary( + GetTransactionSummaryRequest request, ServerCallContext context) => + _dispatchRequestToCQRS.Handle(request, context); public override async Task VerifyTransaction(VerifyTransactionRequest request, ServerCallContext context) {