Merge branch 'kub-stage' into production
Build and Deploy to Production / build-and-deploy (push) Failing after 19m40s
Build and Deploy to Production / build-and-deploy (push) Failing after 19m40s
This commit is contained in:
@@ -24,6 +24,8 @@ stringData:
|
||||
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
||||
"UseSandbox": true
|
||||
},
|
||||
"CmsBaseUrl": "https://cms.se.kbs1.ir",
|
||||
"FrontOfficeBaseUrl": "https://frontoffice.se.kbs1.ir",
|
||||
"FMS": {
|
||||
"Address": "https://dl.afrino.co"
|
||||
},
|
||||
|
||||
+5
@@ -1,4 +1,5 @@
|
||||
using CMSMicroservice.Application.Common.Exceptions;
|
||||
using CMSMicroservice.Application.Common.Helpers;
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Application.Common.Models;
|
||||
using CMSMicroservice.Domain.Common;
|
||||
@@ -272,6 +273,7 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
||||
foreach (var prevCycle in previousCycles)
|
||||
{
|
||||
prevCycle.IsCurrentCycle = false;
|
||||
ClubMembershipCycleHistoryWriter.WriteCycleClosed(_context, prevCycle, reason: "شروع دوره جدید");
|
||||
}
|
||||
|
||||
var maxCycleNumber = await _context.ClubMembershipCycles
|
||||
@@ -293,6 +295,9 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
||||
_context.ClubMembershipCycles.Add(newCycle);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
ClubMembershipCycleHistoryWriter.WriteCycleStarted(_context, newCycle, reason: "فعالسازی عضویت باشگاه");
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
_logger.LogInformation(
|
||||
"Created ClubMembershipCycle #{CycleNumber} for UserId {UserId}, MembershipId {MembershipId}",
|
||||
newCycle.CycleNumber,
|
||||
|
||||
+4
-1
@@ -13,6 +13,7 @@ public class GetAllClubMembershipsQueryHandler : IRequestHandler<GetAllClubMembe
|
||||
{
|
||||
var query = _context.ClubMemberships
|
||||
.Include(x => x.User)
|
||||
.Include(x => x.LastPackage)
|
||||
.ApplyOrder(sortBy: request.SortBy)
|
||||
.AsNoTracking()
|
||||
.AsQueryable();
|
||||
@@ -35,8 +36,10 @@ public class GetAllClubMembershipsQueryHandler : IRequestHandler<GetAllClubMembe
|
||||
Id = x.Id,
|
||||
UserId = x.UserId,
|
||||
UserName = x.User != null ? $"{x.User.FirstName} {x.User.LastName}" : string.Empty,
|
||||
PackageId = x.LastPackageId ?? 0,
|
||||
PackageName = x.LastPackage != null ? x.LastPackage.Title : string.Empty,
|
||||
IsActive = x.IsActive,
|
||||
ActivatedAt = x.ActivatedAt,
|
||||
ActivatedAt = x.LastActivationDate ?? x.ActivatedAt,
|
||||
InitialContribution = x.InitialContribution,
|
||||
TotalEarned = x.TotalEarned,
|
||||
Created = x.Created,
|
||||
|
||||
+2
@@ -11,6 +11,8 @@ public class GetAllClubMembershipsResponseModel
|
||||
public long Id { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public long PackageId { get; set; }
|
||||
public string PackageName { get; set; } = string.Empty;
|
||||
public bool IsActive { get; set; }
|
||||
public DateTime? ActivatedAt { get; set; }
|
||||
public long InitialContribution { get; set; }
|
||||
|
||||
+10
-20
@@ -1,27 +1,17 @@
|
||||
namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembershipHistory;
|
||||
|
||||
/// <summary>
|
||||
/// Query برای دریافت تاریخچه تغییرات عضویت باشگاه
|
||||
/// </summary>
|
||||
public record GetClubMembershipHistoryQuery : IRequest<GetClubMembershipHistoryResponseDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// شناسه عضویت (اختیاری)
|
||||
/// </summary>
|
||||
public long? MembershipId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// شناسه کاربر (اختیاری)
|
||||
/// </summary>
|
||||
public long? UserId { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// موقعیت صفحهبندی
|
||||
/// </summary>
|
||||
public PaginationState? PaginationState { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// مرتبسازی بر اساس
|
||||
/// </summary>
|
||||
public string? SortBy { get; init; }
|
||||
public GetClubMembershipHistoryFilter? Filter { get; init; }
|
||||
}
|
||||
|
||||
public class GetClubMembershipHistoryFilter
|
||||
{
|
||||
public long? UserId { get; set; }
|
||||
public long? ClubMembershipId { get; set; }
|
||||
public ClubMembershipAction? Action { get; set; }
|
||||
public DateTime? CreatedFrom { get; set; }
|
||||
public DateTime? CreatedTo { get; set; }
|
||||
}
|
||||
|
||||
+21
-8
@@ -12,20 +12,30 @@ public class GetClubMembershipHistoryQueryHandler : IRequestHandler<GetClubMembe
|
||||
public async Task<GetClubMembershipHistoryResponseDto> Handle(GetClubMembershipHistoryQuery request, CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.ClubMembershipHistories
|
||||
.Include(x => x.ClubMembership)
|
||||
.ThenInclude(m => m!.User)
|
||||
.AsNoTracking()
|
||||
.AsQueryable();
|
||||
|
||||
if (request.MembershipId.HasValue)
|
||||
if (request.Filter != null)
|
||||
{
|
||||
query = query.Where(x => x.ClubMembershipId == request.MembershipId.Value);
|
||||
if (request.Filter.ClubMembershipId.HasValue)
|
||||
query = query.Where(x => x.ClubMembershipId == request.Filter.ClubMembershipId.Value);
|
||||
|
||||
if (request.Filter.UserId.HasValue)
|
||||
query = query.Where(x => x.UserId == request.Filter.UserId.Value);
|
||||
|
||||
if (request.Filter.Action.HasValue)
|
||||
query = query.Where(x => x.Action == request.Filter.Action.Value);
|
||||
|
||||
if (request.Filter.CreatedFrom.HasValue)
|
||||
query = query.Where(x => x.Created >= request.Filter.CreatedFrom.Value);
|
||||
|
||||
if (request.Filter.CreatedTo.HasValue)
|
||||
query = query.Where(x => x.Created <= request.Filter.CreatedTo.Value);
|
||||
}
|
||||
|
||||
if (request.UserId.HasValue)
|
||||
{
|
||||
query = query.Where(x => x.UserId == request.UserId.Value);
|
||||
}
|
||||
|
||||
query = query.ApplyOrder(sortBy: request.SortBy ?? "Created"); // پیشفرض: جدیدترین اول
|
||||
query = query.ApplyOrder(sortBy: request.SortBy ?? "-Created");
|
||||
|
||||
var meta = await query.GetMetaData(request.PaginationState, cancellationToken);
|
||||
|
||||
@@ -36,6 +46,9 @@ public class GetClubMembershipHistoryQueryHandler : IRequestHandler<GetClubMembe
|
||||
Id = x.Id,
|
||||
ClubMembershipId = x.ClubMembershipId,
|
||||
UserId = x.UserId,
|
||||
UserName = x.ClubMembership != null && x.ClubMembership.User != null
|
||||
? $"{x.ClubMembership.User.FirstName} {x.ClubMembership.User.LastName}"
|
||||
: string.Empty,
|
||||
OldIsActive = x.OldIsActive,
|
||||
NewIsActive = x.NewIsActive,
|
||||
OldInitialContribution = x.OldInitialContribution,
|
||||
|
||||
+1
-26
@@ -4,31 +4,6 @@ public class GetClubMembershipHistoryQueryValidator : AbstractValidator<GetClubM
|
||||
{
|
||||
public GetClubMembershipHistoryQueryValidator()
|
||||
{
|
||||
RuleFor(x => x.MembershipId)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه عضویت معتبر نیست")
|
||||
.When(x => x.MembershipId.HasValue);
|
||||
|
||||
RuleFor(x => x.UserId)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه کاربر معتبر نیست")
|
||||
.When(x => x.UserId.HasValue);
|
||||
|
||||
RuleFor(x => x)
|
||||
.Must(x => x.MembershipId.HasValue || x.UserId.HasValue)
|
||||
.WithMessage("حداقل یکی از MembershipId یا UserId باید مقداردهی شود");
|
||||
// Admin report: filters are all optional
|
||||
}
|
||||
|
||||
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
|
||||
{
|
||||
var result = await ValidateAsync(
|
||||
ValidationContext<GetClubMembershipHistoryQuery>.CreateWithOptions(
|
||||
(GetClubMembershipHistoryQuery)model,
|
||||
x => x.IncludeProperties(propertyName)));
|
||||
|
||||
if (result.IsValid)
|
||||
return Array.Empty<string>();
|
||||
|
||||
return result.Errors.Select(e => e.ErrorMessage);
|
||||
};
|
||||
}
|
||||
|
||||
+1
@@ -11,6 +11,7 @@ public class GetClubMembershipHistoryResponseModel
|
||||
public long Id { get; set; }
|
||||
public long ClubMembershipId { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public bool OldIsActive { get; set; }
|
||||
public bool NewIsActive { get; set; }
|
||||
public long? OldInitialContribution { get; set; }
|
||||
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
using CMSMicroservice.Domain.Entities.Club;
|
||||
|
||||
namespace CMSMicroservice.Application.ClubMembershipCycleCQ.Queries.GetAllClubMembershipCycleByFilter;
|
||||
|
||||
public static class ClubMembershipCycleFilterExtensions
|
||||
{
|
||||
public static IQueryable<ClubMembershipCycle> ApplyClubMembershipCycleFilter(
|
||||
this IQueryable<ClubMembershipCycle> query,
|
||||
GetAllClubMembershipCycleByFilterFilter? filter)
|
||||
{
|
||||
if (filter == null) return query;
|
||||
|
||||
if (filter.UserId.HasValue)
|
||||
query = query.Where(x => x.UserId == filter.UserId.Value);
|
||||
|
||||
if (filter.IsCurrentCycle.HasValue)
|
||||
query = query.Where(x => x.IsCurrentCycle == filter.IsCurrentCycle.Value);
|
||||
|
||||
if (filter.PackageId.HasValue)
|
||||
query = query.Where(x => x.PackageId == filter.PackageId.Value);
|
||||
|
||||
if (filter.CycleNumber.HasValue)
|
||||
query = query.Where(x => x.CycleNumber == filter.CycleNumber.Value);
|
||||
|
||||
if (filter.PurchaseMethod.HasValue)
|
||||
query = query.Where(x => x.PurchaseMethod == filter.PurchaseMethod.Value);
|
||||
|
||||
if (filter.MagicState.HasValue)
|
||||
{
|
||||
query = filter.MagicState.Value switch
|
||||
{
|
||||
1 => query.Where(x => x.MagicStartedAt != null && x.MagicCompletedAt == null),
|
||||
2 => query.Where(x => x.MagicCompletedAt != null),
|
||||
_ => query.Where(x => x.MagicStartedAt == null && x.MagicCompletedAt == null)
|
||||
};
|
||||
}
|
||||
|
||||
if (filter.PackagePurchasedFrom.HasValue)
|
||||
query = query.Where(x => x.PackagePurchasedAt >= filter.PackagePurchasedFrom.Value);
|
||||
|
||||
if (filter.PackagePurchasedTo.HasValue)
|
||||
query = query.Where(x => x.PackagePurchasedAt <= filter.PackagePurchasedTo.Value);
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
|
||||
namespace CMSMicroservice.Application.ClubMembershipCycleCQ.Queries.GetAllClubMembershipCycleByFilter;
|
||||
|
||||
public record GetAllClubMembershipCycleByFilterQuery : IRequest<GetAllClubMembershipCycleByFilterResponseDto>
|
||||
{
|
||||
public PaginationState? PaginationState { get; init; }
|
||||
public string? SortBy { get; init; }
|
||||
public GetAllClubMembershipCycleByFilterFilter? Filter { get; init; }
|
||||
}
|
||||
|
||||
public class GetAllClubMembershipCycleByFilterFilter
|
||||
{
|
||||
public long? UserId { get; set; }
|
||||
public bool? IsCurrentCycle { get; set; }
|
||||
public long? PackageId { get; set; }
|
||||
public int? CycleNumber { get; set; }
|
||||
public PackagePurchaseMethod? PurchaseMethod { get; set; }
|
||||
/// <summary>0=none, 1=active magic, 2=completed magic</summary>
|
||||
public int? MagicState { get; set; }
|
||||
public DateTime? PackagePurchasedFrom { get; set; }
|
||||
public DateTime? PackagePurchasedTo { get; set; }
|
||||
}
|
||||
|
||||
public class GetAllClubMembershipCycleByFilterResponseDto
|
||||
{
|
||||
public MetaData MetaData { get; set; }
|
||||
public List<GetAllClubMembershipCycleByFilterResponseModel>? Models { get; set; }
|
||||
}
|
||||
|
||||
public class GetAllClubMembershipCycleByFilterResponseModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public long ClubMembershipId { get; set; }
|
||||
public int CycleNumber { get; set; }
|
||||
public long PackageId { get; set; }
|
||||
public string PackageName { get; set; } = string.Empty;
|
||||
public long PackageAmount { get; set; }
|
||||
public PackagePurchaseMethod PurchaseMethod { get; set; }
|
||||
public DateTime PackagePurchasedAt { get; set; }
|
||||
public DateTime? MagicStartedAt { get; set; }
|
||||
public DateTime? MagicCompletedAt { get; set; }
|
||||
public bool IsCurrentCycle { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
}
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
namespace CMSMicroservice.Application.ClubMembershipCycleCQ.Queries.GetAllClubMembershipCycleByFilter;
|
||||
|
||||
public class GetAllClubMembershipCycleByFilterQueryHandler
|
||||
: IRequestHandler<GetAllClubMembershipCycleByFilterQuery, GetAllClubMembershipCycleByFilterResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetAllClubMembershipCycleByFilterQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetAllClubMembershipCycleByFilterResponseDto> Handle(
|
||||
GetAllClubMembershipCycleByFilterQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.ClubMembershipCycles
|
||||
.Include(x => x.User)
|
||||
.Include(x => x.Package)
|
||||
.AsNoTracking()
|
||||
.ApplyClubMembershipCycleFilter(request.Filter)
|
||||
.ApplyOrder(sortBy: request.SortBy ?? "-PackagePurchasedAt");
|
||||
|
||||
return new GetAllClubMembershipCycleByFilterResponseDto
|
||||
{
|
||||
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
|
||||
Models = await query
|
||||
.PaginatedListAsync(paginationState: request.PaginationState)
|
||||
.Select(x => new GetAllClubMembershipCycleByFilterResponseModel
|
||||
{
|
||||
Id = x.Id,
|
||||
UserId = x.UserId,
|
||||
UserName = x.User != null ? $"{x.User.FirstName} {x.User.LastName}" : string.Empty,
|
||||
ClubMembershipId = x.ClubMembershipId,
|
||||
CycleNumber = x.CycleNumber,
|
||||
PackageId = x.PackageId,
|
||||
PackageName = x.Package != null ? x.Package.Title : string.Empty,
|
||||
PackageAmount = x.PackageAmount,
|
||||
PurchaseMethod = x.PurchaseMethod,
|
||||
PackagePurchasedAt = x.PackagePurchasedAt,
|
||||
MagicStartedAt = x.MagicStartedAt,
|
||||
MagicCompletedAt = x.MagicCompletedAt,
|
||||
IsCurrentCycle = x.IsCurrentCycle,
|
||||
Created = x.Created
|
||||
})
|
||||
.ToListAsync(cancellationToken)
|
||||
};
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
namespace CMSMicroservice.Application.ClubMembershipCycleCQ.Queries.GetClubMembershipCycleSummary;
|
||||
|
||||
public record GetClubMembershipCycleSummaryQuery : IRequest<GetClubMembershipCycleSummaryResponseDto>
|
||||
{
|
||||
public GetAllClubMembershipCycleByFilter.GetAllClubMembershipCycleByFilterFilter? Filter { get; init; }
|
||||
}
|
||||
|
||||
public class GetClubMembershipCycleSummaryResponseDto
|
||||
{
|
||||
public long TotalCount { get; set; }
|
||||
public long CurrentCycleCount { get; set; }
|
||||
public long MagicActiveCount { get; set; }
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using CMSMicroservice.Application.ClubMembershipCycleCQ.Queries.GetAllClubMembershipCycleByFilter;
|
||||
|
||||
namespace CMSMicroservice.Application.ClubMembershipCycleCQ.Queries.GetClubMembershipCycleSummary;
|
||||
|
||||
public class GetClubMembershipCycleSummaryQueryHandler
|
||||
: IRequestHandler<GetClubMembershipCycleSummaryQuery, GetClubMembershipCycleSummaryResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetClubMembershipCycleSummaryQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetClubMembershipCycleSummaryResponseDto> Handle(
|
||||
GetClubMembershipCycleSummaryQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.ClubMembershipCycles
|
||||
.AsNoTracking()
|
||||
.ApplyClubMembershipCycleFilter(request.Filter);
|
||||
|
||||
var totalCount = await query.LongCountAsync(cancellationToken);
|
||||
var currentCycleCount = await query.LongCountAsync(x => x.IsCurrentCycle, cancellationToken);
|
||||
var magicActiveCount = await query.LongCountAsync(
|
||||
x => x.MagicStartedAt != null && x.MagicCompletedAt == null,
|
||||
cancellationToken);
|
||||
|
||||
return new GetClubMembershipCycleSummaryResponseDto
|
||||
{
|
||||
TotalCount = totalCount,
|
||||
CurrentCycleCount = currentCycleCount,
|
||||
MagicActiveCount = magicActiveCount
|
||||
};
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
using CMSMicroservice.Domain.Entities.History;
|
||||
|
||||
namespace CMSMicroservice.Application.ClubMembershipCycleHistoryCQ.Queries.GetAllClubMembershipCycleHistoryByFilter;
|
||||
|
||||
public static class ClubMembershipCycleHistoryFilterExtensions
|
||||
{
|
||||
public static IQueryable<ClubMembershipCycleHistory> ApplyClubMembershipCycleHistoryFilter(
|
||||
this IQueryable<ClubMembershipCycleHistory> query,
|
||||
GetAllClubMembershipCycleHistoryByFilterFilter? filter)
|
||||
{
|
||||
if (filter == null) return query;
|
||||
|
||||
if (filter.UserId.HasValue)
|
||||
query = query.Where(x => x.UserId == filter.UserId.Value);
|
||||
|
||||
if (filter.ClubMembershipCycleId.HasValue)
|
||||
query = query.Where(x => x.ClubMembershipCycleId == filter.ClubMembershipCycleId.Value);
|
||||
|
||||
if (filter.CycleNumber.HasValue)
|
||||
query = query.Where(x => x.CycleNumber == filter.CycleNumber.Value);
|
||||
|
||||
if (filter.Action.HasValue)
|
||||
query = query.Where(x => x.Action == filter.Action.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);
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
|
||||
namespace CMSMicroservice.Application.ClubMembershipCycleHistoryCQ.Queries.GetAllClubMembershipCycleHistoryByFilter;
|
||||
|
||||
public record GetAllClubMembershipCycleHistoryByFilterQuery : IRequest<GetAllClubMembershipCycleHistoryByFilterResponseDto>
|
||||
{
|
||||
public PaginationState? PaginationState { get; init; }
|
||||
public string? SortBy { get; init; }
|
||||
public GetAllClubMembershipCycleHistoryByFilterFilter? Filter { get; init; }
|
||||
}
|
||||
|
||||
public class GetAllClubMembershipCycleHistoryByFilterFilter
|
||||
{
|
||||
public long? UserId { get; set; }
|
||||
public long? ClubMembershipCycleId { get; set; }
|
||||
public int? CycleNumber { get; set; }
|
||||
public ClubMembershipCycleAction? Action { get; set; }
|
||||
public DateTime? CreatedFrom { get; set; }
|
||||
public DateTime? CreatedTo { get; set; }
|
||||
}
|
||||
|
||||
public class GetAllClubMembershipCycleHistoryByFilterResponseDto
|
||||
{
|
||||
public MetaData MetaData { get; set; }
|
||||
public List<GetAllClubMembershipCycleHistoryByFilterResponseModel>? Models { get; set; }
|
||||
}
|
||||
|
||||
public class GetAllClubMembershipCycleHistoryByFilterResponseModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long ClubMembershipCycleId { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public int CycleNumber { get; set; }
|
||||
public bool OldIsCurrentCycle { get; set; }
|
||||
public bool NewIsCurrentCycle { get; set; }
|
||||
public DateTime? OldMagicStartedAt { get; set; }
|
||||
public DateTime? NewMagicStartedAt { get; set; }
|
||||
public DateTime? OldMagicCompletedAt { get; set; }
|
||||
public DateTime? NewMagicCompletedAt { get; set; }
|
||||
public ClubMembershipCycleAction Action { get; set; }
|
||||
public string? PerformedBy { get; set; }
|
||||
public string? Reason { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
namespace CMSMicroservice.Application.ClubMembershipCycleHistoryCQ.Queries.GetAllClubMembershipCycleHistoryByFilter;
|
||||
|
||||
public class GetAllClubMembershipCycleHistoryByFilterQueryHandler
|
||||
: IRequestHandler<GetAllClubMembershipCycleHistoryByFilterQuery, GetAllClubMembershipCycleHistoryByFilterResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetAllClubMembershipCycleHistoryByFilterQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetAllClubMembershipCycleHistoryByFilterResponseDto> Handle(
|
||||
GetAllClubMembershipCycleHistoryByFilterQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.ClubMembershipCycleHistories
|
||||
.Include(x => x.ClubMembershipCycle)
|
||||
.ThenInclude(c => c!.User)
|
||||
.AsNoTracking()
|
||||
.ApplyClubMembershipCycleHistoryFilter(request.Filter)
|
||||
.ApplyOrder(sortBy: request.SortBy ?? "-Created");
|
||||
|
||||
return new GetAllClubMembershipCycleHistoryByFilterResponseDto
|
||||
{
|
||||
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
|
||||
Models = await query
|
||||
.PaginatedListAsync(paginationState: request.PaginationState)
|
||||
.Select(x => new GetAllClubMembershipCycleHistoryByFilterResponseModel
|
||||
{
|
||||
Id = x.Id,
|
||||
ClubMembershipCycleId = x.ClubMembershipCycleId,
|
||||
UserId = x.UserId,
|
||||
UserName = x.ClubMembershipCycle != null && x.ClubMembershipCycle.User != null
|
||||
? $"{x.ClubMembershipCycle.User.FirstName} {x.ClubMembershipCycle.User.LastName}"
|
||||
: string.Empty,
|
||||
CycleNumber = x.CycleNumber,
|
||||
OldIsCurrentCycle = x.OldIsCurrentCycle,
|
||||
NewIsCurrentCycle = x.NewIsCurrentCycle,
|
||||
OldMagicStartedAt = x.OldMagicStartedAt,
|
||||
NewMagicStartedAt = x.NewMagicStartedAt,
|
||||
OldMagicCompletedAt = x.OldMagicCompletedAt,
|
||||
NewMagicCompletedAt = x.NewMagicCompletedAt,
|
||||
Action = x.Action,
|
||||
PerformedBy = x.PerformedBy,
|
||||
Reason = x.Reason,
|
||||
Created = x.Created
|
||||
})
|
||||
.ToListAsync(cancellationToken)
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -8,16 +8,31 @@ public static class SortByExtensions
|
||||
public static IQueryable<TSource> ApplyOrder<TSource>(this IQueryable<TSource> source,
|
||||
string? sortBy) where TSource : BaseAuditableEntity
|
||||
{
|
||||
// default sort approach
|
||||
if (sortBy is null or "")
|
||||
{
|
||||
source = source.OrderByDescending(p => p.Created);
|
||||
return source;
|
||||
return source.OrderByDescending(p => p.Created);
|
||||
}
|
||||
|
||||
// sort using dynamic linq
|
||||
source = source.OrderBy(sortBy);
|
||||
return source.OrderBy(NormalizeSortBy(sortBy));
|
||||
}
|
||||
|
||||
return source;
|
||||
/// <summary>
|
||||
/// Dynamic LINQ treats "-Created" as unary minus on DateTime (invalid).
|
||||
/// Project convention: leading '-' means descending sort.
|
||||
/// </summary>
|
||||
private static string NormalizeSortBy(string sortBy)
|
||||
{
|
||||
sortBy = sortBy.Trim();
|
||||
if (sortBy.StartsWith('-') && sortBy.Length > 1)
|
||||
{
|
||||
return $"{sortBy[1..]} descending";
|
||||
}
|
||||
|
||||
if (sortBy.StartsWith('+') && sortBy.Length > 1)
|
||||
{
|
||||
return $"{sortBy[1..]} ascending";
|
||||
}
|
||||
|
||||
return sortBy;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
using CMSMicroservice.Domain.Entities.Club;
|
||||
using CMSMicroservice.Domain.Entities.History;
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
|
||||
namespace CMSMicroservice.Application.Common.Helpers;
|
||||
|
||||
public static class ClubMembershipCycleHistoryWriter
|
||||
{
|
||||
public static void WriteCycleStarted(
|
||||
IApplicationDbContext context,
|
||||
ClubMembershipCycle cycle,
|
||||
string? performedBy = "System",
|
||||
string? reason = null)
|
||||
{
|
||||
context.ClubMembershipCycleHistories.Add(new ClubMembershipCycleHistory
|
||||
{
|
||||
ClubMembershipCycleId = cycle.Id,
|
||||
UserId = cycle.UserId,
|
||||
CycleNumber = cycle.CycleNumber,
|
||||
OldIsCurrentCycle = false,
|
||||
NewIsCurrentCycle = cycle.IsCurrentCycle,
|
||||
OldMagicStartedAt = null,
|
||||
NewMagicStartedAt = cycle.MagicStartedAt,
|
||||
OldMagicCompletedAt = null,
|
||||
NewMagicCompletedAt = cycle.MagicCompletedAt,
|
||||
Action = ClubMembershipCycleAction.Started,
|
||||
PerformedBy = performedBy,
|
||||
Reason = reason
|
||||
});
|
||||
}
|
||||
|
||||
public static void WriteCycleClosed(
|
||||
IApplicationDbContext context,
|
||||
ClubMembershipCycle cycle,
|
||||
string? performedBy = "System",
|
||||
string? reason = null)
|
||||
{
|
||||
context.ClubMembershipCycleHistories.Add(new ClubMembershipCycleHistory
|
||||
{
|
||||
ClubMembershipCycleId = cycle.Id,
|
||||
UserId = cycle.UserId,
|
||||
CycleNumber = cycle.CycleNumber,
|
||||
OldIsCurrentCycle = true,
|
||||
NewIsCurrentCycle = false,
|
||||
OldMagicStartedAt = cycle.MagicStartedAt,
|
||||
NewMagicStartedAt = cycle.MagicStartedAt,
|
||||
OldMagicCompletedAt = cycle.MagicCompletedAt,
|
||||
NewMagicCompletedAt = cycle.MagicCompletedAt,
|
||||
Action = ClubMembershipCycleAction.Completed,
|
||||
PerformedBy = performedBy,
|
||||
Reason = reason ?? "دوره جدید جایگزین شد"
|
||||
});
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
namespace CMSMicroservice.Application.PaymentTransactionCQ.Queries.GetAllPaymentTransactionByFilter;
|
||||
|
||||
public record GetAllPaymentTransactionByFilterQuery : IRequest<GetAllPaymentTransactionByFilterResponseDto>
|
||||
{
|
||||
public PaginationState? PaginationState { get; init; }
|
||||
public string? SortBy { get; init; }
|
||||
public GetAllPaymentTransactionByFilterFilter? Filter { get; init; }
|
||||
}
|
||||
|
||||
public class GetAllPaymentTransactionByFilterFilter
|
||||
{
|
||||
public long? UserId { get; set; }
|
||||
public string? Mobile { get; set; }
|
||||
public string? GatewayProvider { get; set; }
|
||||
public bool? PaymentStatus { get; set; }
|
||||
public string? Authority { get; set; }
|
||||
public string? RefId { get; set; }
|
||||
public string? OrderId { get; set; }
|
||||
public DateTime? CreatedFrom { get; set; }
|
||||
public DateTime? CreatedTo { get; set; }
|
||||
}
|
||||
|
||||
public class GetAllPaymentTransactionByFilterResponseDto
|
||||
{
|
||||
public MetaData MetaData { get; set; }
|
||||
public List<GetAllPaymentTransactionByFilterResponseModel>? Models { get; set; }
|
||||
}
|
||||
|
||||
public class GetAllPaymentTransactionByFilterResponseModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long? UserId { get; set; }
|
||||
public string? Mobile { get; set; }
|
||||
public string GatewayProvider { get; set; } = string.Empty;
|
||||
public long Amount { get; set; }
|
||||
public string? Authority { get; set; }
|
||||
public bool PaymentStatus { get; set; }
|
||||
public int? VerificationStatusCode { get; set; }
|
||||
public string? VerificationStatusMessage { get; set; }
|
||||
public string? RefId { get; set; }
|
||||
public string? CardPan { get; set; }
|
||||
public string? OrderId { get; set; }
|
||||
public long? TransactionId { get; set; }
|
||||
public string? Description { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
namespace CMSMicroservice.Application.PaymentTransactionCQ.Queries.GetAllPaymentTransactionByFilter;
|
||||
|
||||
public class GetAllPaymentTransactionByFilterQueryHandler
|
||||
: IRequestHandler<GetAllPaymentTransactionByFilterQuery, GetAllPaymentTransactionByFilterResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetAllPaymentTransactionByFilterQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetAllPaymentTransactionByFilterResponseDto> Handle(
|
||||
GetAllPaymentTransactionByFilterQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.PaymentTransactions
|
||||
.AsNoTracking()
|
||||
.ApplyPaymentTransactionFilter(request.Filter)
|
||||
.ApplyOrder(sortBy: request.SortBy ?? "-Created");
|
||||
|
||||
return new GetAllPaymentTransactionByFilterResponseDto
|
||||
{
|
||||
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
|
||||
Models = await query
|
||||
.PaginatedListAsync(paginationState: request.PaginationState)
|
||||
.Select(x => new GetAllPaymentTransactionByFilterResponseModel
|
||||
{
|
||||
Id = x.Id,
|
||||
UserId = x.UserId,
|
||||
Mobile = x.Mobile,
|
||||
GatewayProvider = x.GatewayProvider,
|
||||
Amount = x.Amount,
|
||||
Authority = x.Authority,
|
||||
PaymentStatus = x.PaymentStatus,
|
||||
VerificationStatusCode = x.VerificationStatusCode,
|
||||
VerificationStatusMessage = x.VerificationStatusMessage,
|
||||
RefId = x.RefId,
|
||||
CardPan = x.CardPan,
|
||||
OrderId = x.OrderId,
|
||||
TransactionId = x.TransactionId,
|
||||
Description = x.Description,
|
||||
Created = x.Created
|
||||
})
|
||||
.ToListAsync(cancellationToken)
|
||||
};
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
using CMSMicroservice.Domain.Entities.Payment;
|
||||
|
||||
namespace CMSMicroservice.Application.PaymentTransactionCQ.Queries.GetAllPaymentTransactionByFilter;
|
||||
|
||||
public static class PaymentTransactionFilterExtensions
|
||||
{
|
||||
public static IQueryable<PaymentTransaction> ApplyPaymentTransactionFilter(
|
||||
this IQueryable<PaymentTransaction> query,
|
||||
GetAllPaymentTransactionByFilterFilter? filter)
|
||||
{
|
||||
if (filter == null) return query;
|
||||
|
||||
if (filter.UserId.HasValue)
|
||||
query = query.Where(x => x.UserId == filter.UserId.Value);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filter.Mobile))
|
||||
query = query.Where(x => x.Mobile != null && x.Mobile.Contains(filter.Mobile));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filter.GatewayProvider))
|
||||
query = query.Where(x => x.GatewayProvider == filter.GatewayProvider);
|
||||
|
||||
if (filter.PaymentStatus.HasValue)
|
||||
query = query.Where(x => x.PaymentStatus == filter.PaymentStatus.Value);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filter.Authority))
|
||||
query = query.Where(x => x.Authority != null && x.Authority.Contains(filter.Authority));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filter.RefId))
|
||||
query = query.Where(x => x.RefId != null && x.RefId.Contains(filter.RefId));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filter.OrderId))
|
||||
query = query.Where(x => x.OrderId != null && x.OrderId.Contains(filter.OrderId));
|
||||
|
||||
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);
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
namespace CMSMicroservice.Application.PaymentTransactionCQ.Queries.GetPaymentTransactionSummary;
|
||||
|
||||
public record GetPaymentTransactionSummaryQuery : IRequest<GetPaymentTransactionSummaryResponseDto>
|
||||
{
|
||||
public GetAllPaymentTransactionByFilter.GetAllPaymentTransactionByFilterFilter? Filter { get; init; }
|
||||
}
|
||||
|
||||
public class GetPaymentTransactionSummaryResponseDto
|
||||
{
|
||||
public long TotalCount { get; set; }
|
||||
public long TotalAmount { get; set; }
|
||||
public long SuccessfulCount { get; set; }
|
||||
public long PendingCount { get; set; }
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using CMSMicroservice.Application.PaymentTransactionCQ.Queries.GetAllPaymentTransactionByFilter;
|
||||
|
||||
namespace CMSMicroservice.Application.PaymentTransactionCQ.Queries.GetPaymentTransactionSummary;
|
||||
|
||||
public class GetPaymentTransactionSummaryQueryHandler
|
||||
: IRequestHandler<GetPaymentTransactionSummaryQuery, GetPaymentTransactionSummaryResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetPaymentTransactionSummaryQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetPaymentTransactionSummaryResponseDto> Handle(
|
||||
GetPaymentTransactionSummaryQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.PaymentTransactions
|
||||
.AsNoTracking()
|
||||
.ApplyPaymentTransactionFilter(request.Filter);
|
||||
|
||||
var totalCount = await query.LongCountAsync(cancellationToken);
|
||||
var totalAmount = totalCount > 0 ? await query.SumAsync(x => x.Amount, cancellationToken) : 0;
|
||||
var successfulCount = await query.LongCountAsync(x => x.PaymentStatus, cancellationToken);
|
||||
var pendingCount = await query.LongCountAsync(x => !x.PaymentStatus, cancellationToken);
|
||||
|
||||
return new GetPaymentTransactionSummaryResponseDto
|
||||
{
|
||||
TotalCount = totalCount,
|
||||
TotalAmount = totalAmount,
|
||||
SuccessfulCount = successfulCount,
|
||||
PendingCount = pendingCount
|
||||
};
|
||||
}
|
||||
}
|
||||
+4
@@ -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; }
|
||||
}
|
||||
|
||||
+19
-17
@@ -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)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
+1
@@ -24,4 +24,5 @@ public class GetAllTransactionsByFilterResponseDto
|
||||
public string? RefId { get; set; }
|
||||
//
|
||||
public TransactionType Type { get; set; }
|
||||
public DateTime Created { get; set; }
|
||||
}
|
||||
|
||||
+48
@@ -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;
|
||||
}
|
||||
}
|
||||
+17
@@ -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; }
|
||||
}
|
||||
+39
@@ -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
|
||||
};
|
||||
}
|
||||
}
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
|
||||
namespace CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetAllUserPackagePurchaseByFilter;
|
||||
|
||||
public record GetAllUserPackagePurchaseByFilterQuery : IRequest<GetAllUserPackagePurchaseByFilterResponseDto>
|
||||
{
|
||||
public PaginationState? PaginationState { get; init; }
|
||||
public string? SortBy { get; init; }
|
||||
public GetAllUserPackagePurchaseByFilterFilter? Filter { get; init; }
|
||||
}
|
||||
|
||||
public class GetAllUserPackagePurchaseByFilterFilter
|
||||
{
|
||||
public long? UserId { get; set; }
|
||||
public long? PackageId { get; set; }
|
||||
public PackagePurchaseMethod? PurchaseMethod { get; set; }
|
||||
public DateTime? PurchasedFrom { get; set; }
|
||||
public DateTime? PurchasedTo { get; set; }
|
||||
public long? MinAmount { get; set; }
|
||||
public long? MaxAmount { get; set; }
|
||||
}
|
||||
|
||||
public class GetAllUserPackagePurchaseByFilterResponseDto
|
||||
{
|
||||
public MetaData MetaData { get; set; }
|
||||
public List<GetAllUserPackagePurchaseByFilterResponseModel>? Models { get; set; }
|
||||
}
|
||||
|
||||
public class GetAllUserPackagePurchaseByFilterResponseModel
|
||||
{
|
||||
public long Id { get; set; }
|
||||
public long UserId { get; set; }
|
||||
public string UserName { get; set; } = string.Empty;
|
||||
public string UserMobile { get; set; } = string.Empty;
|
||||
public long PackageId { get; set; }
|
||||
public string PackageName { get; set; } = string.Empty;
|
||||
public PackagePurchaseMethod PurchaseMethod { get; set; }
|
||||
public DateTime PurchasedAt { get; set; }
|
||||
public long Amount { get; set; }
|
||||
public long? OrderId { get; set; }
|
||||
public long? TransactionId { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
namespace CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetAllUserPackagePurchaseByFilter;
|
||||
|
||||
public class GetAllUserPackagePurchaseByFilterQueryHandler
|
||||
: IRequestHandler<GetAllUserPackagePurchaseByFilterQuery, GetAllUserPackagePurchaseByFilterResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetAllUserPackagePurchaseByFilterQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetAllUserPackagePurchaseByFilterResponseDto> Handle(
|
||||
GetAllUserPackagePurchaseByFilterQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.UserPackagePurchases
|
||||
.Include(x => x.User)
|
||||
.Include(x => x.Package)
|
||||
.AsNoTracking()
|
||||
.ApplyUserPackagePurchaseFilter(request.Filter)
|
||||
.ApplyOrder(sortBy: request.SortBy ?? "-PurchasedAt");
|
||||
|
||||
return new GetAllUserPackagePurchaseByFilterResponseDto
|
||||
{
|
||||
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
|
||||
Models = await query
|
||||
.PaginatedListAsync(paginationState: request.PaginationState)
|
||||
.Select(x => new GetAllUserPackagePurchaseByFilterResponseModel
|
||||
{
|
||||
Id = x.Id,
|
||||
UserId = x.UserId,
|
||||
UserName = x.User != null ? $"{x.User.FirstName} {x.User.LastName}" : string.Empty,
|
||||
UserMobile = x.User != null ? x.User.Mobile : string.Empty,
|
||||
PackageId = x.PackageId,
|
||||
PackageName = x.Package != null ? x.Package.Title : string.Empty,
|
||||
PurchaseMethod = x.PurchaseMethod,
|
||||
PurchasedAt = x.PurchasedAt,
|
||||
Amount = x.Amount,
|
||||
OrderId = x.OrderId,
|
||||
TransactionId = x.TransactionId,
|
||||
Created = x.Created
|
||||
})
|
||||
.ToListAsync(cancellationToken)
|
||||
};
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
|
||||
namespace CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetAllUserPackagePurchaseByFilter;
|
||||
|
||||
public static class UserPackagePurchaseFilterExtensions
|
||||
{
|
||||
public static IQueryable<UserPackagePurchase> ApplyUserPackagePurchaseFilter(
|
||||
this IQueryable<UserPackagePurchase> query,
|
||||
GetAllUserPackagePurchaseByFilterFilter? filter)
|
||||
{
|
||||
if (filter == null) return query;
|
||||
|
||||
if (filter.UserId.HasValue)
|
||||
query = query.Where(x => x.UserId == filter.UserId.Value);
|
||||
|
||||
if (filter.PackageId.HasValue)
|
||||
query = query.Where(x => x.PackageId == filter.PackageId.Value);
|
||||
|
||||
if (filter.PurchaseMethod.HasValue)
|
||||
query = query.Where(x => x.PurchaseMethod == filter.PurchaseMethod.Value);
|
||||
|
||||
if (filter.PurchasedFrom.HasValue)
|
||||
query = query.Where(x => x.PurchasedAt >= filter.PurchasedFrom.Value);
|
||||
|
||||
if (filter.PurchasedTo.HasValue)
|
||||
query = query.Where(x => x.PurchasedAt <= filter.PurchasedTo.Value);
|
||||
|
||||
if (filter.MinAmount.HasValue)
|
||||
query = query.Where(x => x.Amount >= filter.MinAmount.Value);
|
||||
|
||||
if (filter.MaxAmount.HasValue)
|
||||
query = query.Where(x => x.Amount <= filter.MaxAmount.Value);
|
||||
|
||||
return query;
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
namespace CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetUserPackagePurchaseSummary;
|
||||
|
||||
public record GetUserPackagePurchaseSummaryQuery : IRequest<GetUserPackagePurchaseSummaryResponseDto>
|
||||
{
|
||||
public GetAllUserPackagePurchaseByFilter.GetAllUserPackagePurchaseByFilterFilter? Filter { get; init; }
|
||||
}
|
||||
|
||||
public class GetUserPackagePurchaseSummaryResponseDto
|
||||
{
|
||||
public long TotalCount { get; set; }
|
||||
public long TotalAmount { get; set; }
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
using CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetAllUserPackagePurchaseByFilter;
|
||||
|
||||
namespace CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetUserPackagePurchaseSummary;
|
||||
|
||||
public class GetUserPackagePurchaseSummaryQueryHandler
|
||||
: IRequestHandler<GetUserPackagePurchaseSummaryQuery, GetUserPackagePurchaseSummaryResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public GetUserPackagePurchaseSummaryQueryHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<GetUserPackagePurchaseSummaryResponseDto> Handle(
|
||||
GetUserPackagePurchaseSummaryQuery request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var query = _context.UserPackagePurchases
|
||||
.AsNoTracking()
|
||||
.ApplyUserPackagePurchaseFilter(request.Filter);
|
||||
|
||||
var totalCount = await query.LongCountAsync(cancellationToken);
|
||||
var totalAmount = totalCount > 0 ? await query.SumAsync(x => x.Amount, cancellationToken) : 0;
|
||||
|
||||
return new GetUserPackagePurchaseSummaryResponseDto
|
||||
{
|
||||
TotalCount = totalCount,
|
||||
TotalAmount = totalAmount
|
||||
};
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
using CMSMicroservice.Application.Common.Models;
|
||||
using MediatR;
|
||||
|
||||
namespace CMSMicroservice.Application.WalletCQ.Commands.ChargeCreditWallet;
|
||||
|
||||
/// <summary>
|
||||
/// دستور شارژ کیف پول اصلی از طریق درگاه
|
||||
/// </summary>
|
||||
public class ChargeCreditWalletCommand : IRequest<PaymentInitiateResult>
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
public long Amount { get; set; }
|
||||
}
|
||||
+123
@@ -0,0 +1,123 @@
|
||||
using CMSMicroservice.Application.Common;
|
||||
using CMSMicroservice.Application.Common.Exceptions;
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Application.Common.Models;
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
using CMSMicroservice.Domain.Entities.Payment;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CMSMicroservice.Application.WalletCQ.Commands.ChargeCreditWallet;
|
||||
|
||||
public class ChargeCreditWalletCommandHandler
|
||||
: IRequestHandler<ChargeCreditWalletCommand, PaymentInitiateResult>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
private readonly IPaymentGatewayService _paymentGateway;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<ChargeCreditWalletCommandHandler> _logger;
|
||||
private readonly IUserPaymentLock _paymentLock;
|
||||
|
||||
public ChargeCreditWalletCommandHandler(
|
||||
IApplicationDbContext context,
|
||||
IPaymentGatewayService paymentGateway,
|
||||
IConfiguration configuration,
|
||||
ILogger<ChargeCreditWalletCommandHandler> logger,
|
||||
IUserPaymentLock paymentLock)
|
||||
{
|
||||
_context = context;
|
||||
_paymentGateway = paymentGateway;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
_paymentLock = paymentLock;
|
||||
}
|
||||
|
||||
public Task<PaymentInitiateResult> Handle(
|
||||
ChargeCreditWalletCommand request,
|
||||
CancellationToken cancellationToken) =>
|
||||
_paymentLock.ExecuteAsync(
|
||||
PaymentLockScopes.Initiate(request.UserId),
|
||||
PaymentLockStrategy.FailFast,
|
||||
ct => HandleCore(request, ct),
|
||||
cancellationToken);
|
||||
|
||||
private async Task<PaymentInitiateResult> HandleCore(
|
||||
ChargeCreditWalletCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Charging credit wallet for UserId: {UserId}, Amount: {Amount}",
|
||||
request.UserId,
|
||||
request.Amount);
|
||||
|
||||
var user = await _context.Users
|
||||
.FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken)
|
||||
?? throw new NotFoundException(nameof(User), request.UserId);
|
||||
|
||||
var wallet = await _context.UserWallets
|
||||
.FirstOrDefaultAsync(w => w.UserId == request.UserId, cancellationToken)
|
||||
?? throw new NotFoundException("کیف پول کاربر یافت نشد");
|
||||
|
||||
var frontOfficeBaseUrl = _configuration["FrontOfficeBaseUrl"] ?? "https://localhost:5268";
|
||||
var callbackUrl = $"{frontOfficeBaseUrl}/profile/payment-callback?type=credit-wallet";
|
||||
|
||||
var paymentRequest = new PaymentRequest
|
||||
{
|
||||
Amount = request.Amount,
|
||||
UserId = user.Id,
|
||||
Mobile = user.Mobile ?? "",
|
||||
CallbackUrl = callbackUrl,
|
||||
Description = $"شارژ کیف پول اصلی - کاربر {user.Id}"
|
||||
};
|
||||
|
||||
var paymentResult = await _paymentGateway.InitiatePaymentAsync(paymentRequest);
|
||||
|
||||
if (!paymentResult.IsSuccess)
|
||||
{
|
||||
_logger.LogError(
|
||||
"Payment gateway failed for UserId {UserId}: {ErrorMessage}",
|
||||
user.Id,
|
||||
paymentResult.ErrorMessage);
|
||||
|
||||
throw new Exception($"خطا در ارتباط با درگاه پرداخت: {paymentResult.ErrorMessage}");
|
||||
}
|
||||
|
||||
var paymentTx = new PaymentTransaction
|
||||
{
|
||||
GatewayProvider = _configuration["PaymentProvider"] ?? "zarinpal",
|
||||
MerchantId = _configuration["ZarinPal:MerchantId"] ?? "",
|
||||
Amount = request.Amount,
|
||||
CallbackUrl = callbackUrl,
|
||||
Description = $"شارژ کیف پول اصلی - کاربر {user.Id}",
|
||||
Mobile = user.Mobile,
|
||||
UserId = user.Id,
|
||||
RequestStatusCode = 100,
|
||||
RequestStatusMessage = "Success",
|
||||
Authority = paymentResult.RefId,
|
||||
PaymentStatus = false
|
||||
};
|
||||
_context.PaymentTransactions.Add(paymentTx);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
_logger.LogInformation(
|
||||
"Credit wallet charge initiated. UserId: {UserId}, RefId: {RefId}, PaymentTxId: {PaymentTxId}",
|
||||
user.Id,
|
||||
paymentResult.RefId,
|
||||
paymentTx.Id);
|
||||
|
||||
return paymentResult;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(
|
||||
ex,
|
||||
"Error in ChargeCreditWalletCommand for UserId: {UserId}",
|
||||
request.UserId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
using CMSMicroservice.Domain.Common;
|
||||
using FluentValidation;
|
||||
|
||||
namespace CMSMicroservice.Application.WalletCQ.Commands.ChargeCreditWallet;
|
||||
|
||||
public class ChargeCreditWalletCommandValidator : AbstractValidator<ChargeCreditWalletCommand>
|
||||
{
|
||||
public ChargeCreditWalletCommandValidator()
|
||||
{
|
||||
RuleFor(x => x.UserId)
|
||||
.GreaterThan(0)
|
||||
.WithMessage("شناسه کاربر باید بزرگتر از صفر باشد");
|
||||
|
||||
RuleFor(x => x.Amount)
|
||||
.GreaterThanOrEqualTo(SystemConstants.DiscountWalletMinCharge)
|
||||
.WithMessage("حداقل مبلغ شارژ ۱۰,۰۰۰ تومان است")
|
||||
.LessThanOrEqualTo(SystemConstants.WalletMaxSafeAmount)
|
||||
.WithMessage("مبلغ وارد شده بیش از حد مجاز است");
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
using MediatR;
|
||||
|
||||
namespace CMSMicroservice.Application.WalletCQ.Commands.VerifyCreditWalletCharge;
|
||||
|
||||
/// <summary>
|
||||
/// دستور تأیید شارژ کیف پول اصلی
|
||||
/// </summary>
|
||||
public class VerifyCreditWalletChargeCommand : IRequest<bool>
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
public long Amount { get; set; }
|
||||
public string Authority { get; set; } = string.Empty;
|
||||
}
|
||||
+157
@@ -0,0 +1,157 @@
|
||||
using CMSMicroservice.Application.Common;
|
||||
using CMSMicroservice.Application.Common.Exceptions;
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
using MediatR;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace CMSMicroservice.Application.WalletCQ.Commands.VerifyCreditWalletCharge;
|
||||
|
||||
public class VerifyCreditWalletChargeCommandHandler
|
||||
: IRequestHandler<VerifyCreditWalletChargeCommand, bool>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
private readonly IPaymentGatewayService _paymentGateway;
|
||||
private readonly ILogger<VerifyCreditWalletChargeCommandHandler> _logger;
|
||||
private readonly IUserPaymentLock _paymentLock;
|
||||
|
||||
public VerifyCreditWalletChargeCommandHandler(
|
||||
IApplicationDbContext context,
|
||||
IPaymentGatewayService paymentGateway,
|
||||
ILogger<VerifyCreditWalletChargeCommandHandler> logger,
|
||||
IUserPaymentLock paymentLock)
|
||||
{
|
||||
_context = context;
|
||||
_paymentGateway = paymentGateway;
|
||||
_logger = logger;
|
||||
_paymentLock = paymentLock;
|
||||
}
|
||||
|
||||
public Task<bool> Handle(
|
||||
VerifyCreditWalletChargeCommand request,
|
||||
CancellationToken cancellationToken) =>
|
||||
_paymentLock.ExecuteAsync(
|
||||
PaymentLockScopes.Verify(request.UserId, request.Authority),
|
||||
PaymentLockStrategy.WaitForRelease,
|
||||
ct => HandleCore(request, ct),
|
||||
cancellationToken);
|
||||
|
||||
private async Task<bool> HandleCore(
|
||||
VerifyCreditWalletChargeCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
_logger.LogInformation(
|
||||
"Verifying credit wallet charge. UserId: {UserId}, Amount: {Amount}, Authority: {Authority}",
|
||||
request.UserId,
|
||||
request.Amount,
|
||||
request.Authority);
|
||||
|
||||
var user = await _context.Users
|
||||
.FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken)
|
||||
?? throw new NotFoundException(nameof(User), request.UserId);
|
||||
|
||||
var paymentTx = await _context.PaymentTransactions
|
||||
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, cancellationToken);
|
||||
|
||||
if (paymentTx?.PaymentStatus == true)
|
||||
{
|
||||
_logger.LogWarning("PaymentTransaction already verified: {Authority}", request.Authority);
|
||||
return true;
|
||||
}
|
||||
|
||||
var amountInToman = (decimal)(paymentTx?.Amount ?? 0);
|
||||
|
||||
var verifyResult = await _paymentGateway.VerifyPaymentAsync(
|
||||
request.Authority,
|
||||
"OK",
|
||||
amountInToman,
|
||||
cancellationToken);
|
||||
|
||||
if (paymentTx != null)
|
||||
{
|
||||
paymentTx.PaymentStatus = verifyResult.IsSuccess;
|
||||
paymentTx.VerificationStatusCode = verifyResult.VerificationCode;
|
||||
paymentTx.VerificationStatusMessage = verifyResult.Message;
|
||||
paymentTx.CardPan = verifyResult.CardPan;
|
||||
paymentTx.CardHash = verifyResult.CardHash;
|
||||
paymentTx.RefId = verifyResult.TrackingCode;
|
||||
}
|
||||
|
||||
if (!verifyResult.IsSuccess)
|
||||
{
|
||||
_logger.LogWarning(
|
||||
"Credit wallet charge verification failed for UserId {UserId}: {Message}",
|
||||
request.UserId,
|
||||
verifyResult.Message);
|
||||
|
||||
throw new Exception($"تراکنش ناموفق: {verifyResult.Message}");
|
||||
}
|
||||
|
||||
var wallet = await _context.UserWallets
|
||||
.FirstOrDefaultAsync(w => w.UserId == user.Id, cancellationToken)
|
||||
?? throw new NotFoundException($"کیف پول کاربر با شناسه {request.UserId} یافت نشد");
|
||||
|
||||
var oldBalance = wallet.Balance;
|
||||
wallet.Balance += request.Amount;
|
||||
|
||||
_logger.LogInformation(
|
||||
"Charging credit balance for UserId {UserId}: {OldBalance} -> {NewBalance}",
|
||||
request.UserId,
|
||||
oldBalance,
|
||||
wallet.Balance);
|
||||
|
||||
var transaction = new Transaction
|
||||
{
|
||||
Amount = request.Amount,
|
||||
Description = $"شارژ کیف پول اصلی - کاربر {user.Id}",
|
||||
PaymentStatus = PaymentStatus.Success,
|
||||
PaymentDate = DateTime.Now,
|
||||
RefId = verifyResult.RefId,
|
||||
Type = TransactionType.CreditWalletCharge
|
||||
};
|
||||
|
||||
_context.Transactions.Add(transaction);
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
_context.UserWalletHistories.Add(new Domain.Entities.UserWalletHistory
|
||||
{
|
||||
WalletId = wallet.Id,
|
||||
CurrentBalance = wallet.Balance,
|
||||
ChangeValue = request.Amount,
|
||||
CurrentNetworkBalance = wallet.NetworkBalance,
|
||||
ChangeNerworkValue = 0,
|
||||
CurrentDiscountBalance = wallet.DiscountBalance,
|
||||
ChangeDiscountValue = 0,
|
||||
IsIncrease = true,
|
||||
RefrenceId = transaction.Id
|
||||
});
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
|
||||
if (paymentTx != null)
|
||||
{
|
||||
paymentTx.TransactionId = transaction.Id;
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
}
|
||||
|
||||
_logger.LogInformation(
|
||||
"Credit wallet charged successfully. UserId: {UserId}, TransactionId: {TransactionId}, RefId: {RefId}",
|
||||
user.Id,
|
||||
transaction.Id,
|
||||
verifyResult.RefId);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(
|
||||
ex,
|
||||
"Error in VerifyCreditWalletChargeCommand for UserId: {UserId}",
|
||||
request.UserId);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,4 +36,9 @@ public enum TransactionType
|
||||
/// بونوس داخلی کیفپول جادویی (مبلغ × 1.5)
|
||||
/// </summary>
|
||||
MagicWalletBonus = 15,
|
||||
|
||||
/// <summary>
|
||||
/// شارژ کیف پول اصلی از درگاه
|
||||
/// </summary>
|
||||
CreditWalletCharge = 16,
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ using CMSMicroservice.Application.PackageCQ.Commands.VerifyUserPackagePurchasePa
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Application.DiscountShopCQ.Commands.CompleteOrderPayment;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyDiscountWalletCharge;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyCreditWalletCharge;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyMagicWalletCharge;
|
||||
using CMSMicroservice.Domain.Entities;
|
||||
using CMSMicroservice.Domain.Entities.Payment;
|
||||
@@ -174,6 +175,19 @@ public class ZarinpalReconciliationJob
|
||||
}, ct);
|
||||
break;
|
||||
|
||||
case "credit-wallet":
|
||||
if (!paymentTx.UserId.HasValue)
|
||||
throw new InvalidOperationException(
|
||||
$"UserId is null for credit-wallet authority {authority}");
|
||||
|
||||
await _sender.Send(new VerifyCreditWalletChargeCommand
|
||||
{
|
||||
Authority = authority,
|
||||
UserId = paymentTx.UserId.Value,
|
||||
Amount = paymentTx.Amount
|
||||
}, ct);
|
||||
break;
|
||||
|
||||
case "discount-order":
|
||||
await ReconcileDiscountOrderAsync(paymentTx, ct);
|
||||
break;
|
||||
@@ -194,6 +208,8 @@ public class ZarinpalReconciliationJob
|
||||
return "magic-wallet";
|
||||
if (callbackUrl.Contains("type=discount-wallet", StringComparison.OrdinalIgnoreCase))
|
||||
return "discount-wallet";
|
||||
if (callbackUrl.Contains("type=credit-wallet", StringComparison.OrdinalIgnoreCase))
|
||||
return "credit-wallet";
|
||||
if (callbackUrl.Contains("type=discount-order", StringComparison.OrdinalIgnoreCase))
|
||||
return "discount-order";
|
||||
// Package callbacks have orderId= but no type= parameter
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<TargetFramework>net9.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Version>0.0.200</Version>
|
||||
<Version>0.0.203</Version>
|
||||
<DebugType>None</DebugType>
|
||||
<DebugSymbols>False</DebugSymbols>
|
||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||
@@ -74,6 +74,11 @@
|
||||
<Protobuf Include="Protos\sitepagesettings.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
||||
<!-- Image Resolver Service -->
|
||||
<Protobuf Include="Protos\imageresolver.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
||||
<!-- Admin Report APIs -->
|
||||
<Protobuf Include="Protos\paymenttransaction.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
||||
<Protobuf Include="Protos\userpackagepurchase.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
||||
<Protobuf Include="Protos\clubmembershipcycle.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
||||
<Protobuf Include="Protos\clubmembershipcyclehistory.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PushToFoursatNuget" AfterTargets="Pack" Condition="'$(CI)' != 'true'">
|
||||
|
||||
@@ -164,11 +164,19 @@ message ClubMembershipModel
|
||||
|
||||
// GetHistory Query
|
||||
message GetClubMembershipHistoryRequest
|
||||
{
|
||||
messages.PaginationState pagination_state = 1;
|
||||
google.protobuf.StringValue sort_by = 2;
|
||||
GetClubMembershipHistoryFilter filter = 3;
|
||||
}
|
||||
|
||||
message GetClubMembershipHistoryFilter
|
||||
{
|
||||
google.protobuf.Int64Value user_id = 1;
|
||||
google.protobuf.Int64Value package_id = 2;
|
||||
int32 page_index = 3;
|
||||
int32 page_size = 4;
|
||||
google.protobuf.Int64Value club_membership_id = 2;
|
||||
google.protobuf.Int32Value action = 3;
|
||||
google.protobuf.Timestamp created_from = 4;
|
||||
google.protobuf.Timestamp created_to = 5;
|
||||
}
|
||||
|
||||
message GetClubMembershipHistoryResponse
|
||||
@@ -182,16 +190,15 @@ message ClubMembershipHistoryModel
|
||||
int64 id = 1;
|
||||
int64 club_membership_id = 2;
|
||||
int64 user_id = 3;
|
||||
google.protobuf.Int64Value old_package_id = 4;
|
||||
google.protobuf.Int64Value new_package_id = 5;
|
||||
google.protobuf.Timestamp old_activated_at = 6;
|
||||
google.protobuf.Timestamp new_activated_at = 7;
|
||||
google.protobuf.Timestamp old_expires_at = 8;
|
||||
google.protobuf.Timestamp new_expires_at = 9;
|
||||
int32 action = 10; // ClubMembershipAction enum
|
||||
string performed_by = 11;
|
||||
string reason = 12;
|
||||
google.protobuf.Timestamp created = 13;
|
||||
string user_name = 4;
|
||||
bool old_is_active = 5;
|
||||
bool new_is_active = 6;
|
||||
google.protobuf.Int64Value old_initial_contribution = 7;
|
||||
google.protobuf.Int64Value new_initial_contribution = 8;
|
||||
int32 action = 9; // ClubMembershipAction enum
|
||||
string performed_by = 10;
|
||||
string reason = 11;
|
||||
google.protobuf.Timestamp created_at = 12;
|
||||
}
|
||||
|
||||
// GetClubStatistics Query
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package clubmembershipcycle;
|
||||
|
||||
import "public_messages.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/api/annotations.proto";
|
||||
|
||||
option csharp_namespace = "CMSMicroservice.Protobuf.Protos.ClubMembershipCycle";
|
||||
|
||||
service ClubMembershipCycleContract
|
||||
{
|
||||
rpc GetAllClubMembershipCycleByFilter(GetAllClubMembershipCycleByFilterRequest) returns (GetAllClubMembershipCycleByFilterResponse){
|
||||
option (google.api.http) = {
|
||||
get: "/ClubMembershipCycle/GetAllByFilter"
|
||||
};
|
||||
};
|
||||
rpc GetClubMembershipCycleSummary(GetClubMembershipCycleSummaryRequest) returns (GetClubMembershipCycleSummaryResponse){
|
||||
option (google.api.http) = {
|
||||
get: "/ClubMembershipCycle/GetSummary"
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
message GetAllClubMembershipCycleByFilterRequest
|
||||
{
|
||||
messages.PaginationState pagination_state = 1;
|
||||
google.protobuf.StringValue sort_by = 2;
|
||||
GetAllClubMembershipCycleByFilterFilter filter = 3;
|
||||
}
|
||||
|
||||
message GetAllClubMembershipCycleByFilterFilter
|
||||
{
|
||||
google.protobuf.Int64Value user_id = 1;
|
||||
google.protobuf.BoolValue is_current_cycle = 2;
|
||||
google.protobuf.Int64Value package_id = 3;
|
||||
google.protobuf.Int32Value cycle_number = 4;
|
||||
google.protobuf.Int32Value purchase_method = 5;
|
||||
google.protobuf.Int32Value magic_state = 6; // 0=none, 1=active, 2=completed
|
||||
google.protobuf.Timestamp package_purchased_from = 7;
|
||||
google.protobuf.Timestamp package_purchased_to = 8;
|
||||
}
|
||||
|
||||
message GetAllClubMembershipCycleByFilterResponse
|
||||
{
|
||||
messages.MetaData meta_data = 1;
|
||||
repeated ClubMembershipCycleModel models = 2;
|
||||
}
|
||||
|
||||
message ClubMembershipCycleModel
|
||||
{
|
||||
int64 id = 1;
|
||||
int64 user_id = 2;
|
||||
string user_name = 3;
|
||||
int64 club_membership_id = 4;
|
||||
int32 cycle_number = 5;
|
||||
int64 package_id = 6;
|
||||
string package_name = 7;
|
||||
int64 package_amount = 8;
|
||||
int32 purchase_method = 9;
|
||||
google.protobuf.Timestamp package_purchased_at = 10;
|
||||
google.protobuf.Timestamp magic_started_at = 11;
|
||||
google.protobuf.Timestamp magic_completed_at = 12;
|
||||
bool is_current_cycle = 13;
|
||||
google.protobuf.Timestamp created_at = 14;
|
||||
}
|
||||
|
||||
message GetClubMembershipCycleSummaryRequest
|
||||
{
|
||||
GetAllClubMembershipCycleByFilterFilter filter = 1;
|
||||
}
|
||||
|
||||
message GetClubMembershipCycleSummaryResponse
|
||||
{
|
||||
int64 total_count = 1;
|
||||
int64 current_cycle_count = 2;
|
||||
int64 magic_active_count = 3;
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package clubmembershipcyclehistory;
|
||||
|
||||
import "public_messages.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/api/annotations.proto";
|
||||
|
||||
option csharp_namespace = "CMSMicroservice.Protobuf.Protos.ClubMembershipCycleHistory";
|
||||
|
||||
service ClubMembershipCycleHistoryContract
|
||||
{
|
||||
rpc GetAllClubMembershipCycleHistoryByFilter(GetAllClubMembershipCycleHistoryByFilterRequest) returns (GetAllClubMembershipCycleHistoryByFilterResponse){
|
||||
option (google.api.http) = {
|
||||
get: "/ClubMembershipCycleHistory/GetAllByFilter"
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
message GetAllClubMembershipCycleHistoryByFilterRequest
|
||||
{
|
||||
messages.PaginationState pagination_state = 1;
|
||||
google.protobuf.StringValue sort_by = 2;
|
||||
GetAllClubMembershipCycleHistoryByFilterFilter filter = 3;
|
||||
}
|
||||
|
||||
message GetAllClubMembershipCycleHistoryByFilterFilter
|
||||
{
|
||||
google.protobuf.Int64Value user_id = 1;
|
||||
google.protobuf.Int64Value club_membership_cycle_id = 2;
|
||||
google.protobuf.Int32Value cycle_number = 3;
|
||||
google.protobuf.Int32Value action = 4;
|
||||
google.protobuf.Timestamp created_from = 5;
|
||||
google.protobuf.Timestamp created_to = 6;
|
||||
}
|
||||
|
||||
message GetAllClubMembershipCycleHistoryByFilterResponse
|
||||
{
|
||||
messages.MetaData meta_data = 1;
|
||||
repeated ClubMembershipCycleHistoryModel models = 2;
|
||||
}
|
||||
|
||||
message ClubMembershipCycleHistoryModel
|
||||
{
|
||||
int64 id = 1;
|
||||
int64 club_membership_cycle_id = 2;
|
||||
int64 user_id = 3;
|
||||
string user_name = 4;
|
||||
int32 cycle_number = 5;
|
||||
bool old_is_current_cycle = 6;
|
||||
bool new_is_current_cycle = 7;
|
||||
google.protobuf.Timestamp old_magic_started_at = 8;
|
||||
google.protobuf.Timestamp new_magic_started_at = 9;
|
||||
google.protobuf.Timestamp old_magic_completed_at = 10;
|
||||
google.protobuf.Timestamp new_magic_completed_at = 11;
|
||||
int32 action = 12;
|
||||
string performed_by = 13;
|
||||
string reason = 14;
|
||||
google.protobuf.Timestamp created_at = 15;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package paymenttransaction;
|
||||
|
||||
import "public_messages.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/api/annotations.proto";
|
||||
|
||||
option csharp_namespace = "CMSMicroservice.Protobuf.Protos.PaymentTransaction";
|
||||
|
||||
service PaymentTransactionContract
|
||||
{
|
||||
rpc GetAllPaymentTransactionByFilter(GetAllPaymentTransactionByFilterRequest) returns (GetAllPaymentTransactionByFilterResponse){
|
||||
option (google.api.http) = {
|
||||
get: "/PaymentTransaction/GetAllByFilter"
|
||||
};
|
||||
};
|
||||
rpc GetPaymentTransactionSummary(GetPaymentTransactionSummaryRequest) returns (GetPaymentTransactionSummaryResponse){
|
||||
option (google.api.http) = {
|
||||
get: "/PaymentTransaction/GetSummary"
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
message GetAllPaymentTransactionByFilterRequest
|
||||
{
|
||||
messages.PaginationState pagination_state = 1;
|
||||
google.protobuf.StringValue sort_by = 2;
|
||||
GetAllPaymentTransactionByFilterFilter filter = 3;
|
||||
}
|
||||
|
||||
message GetAllPaymentTransactionByFilterFilter
|
||||
{
|
||||
google.protobuf.Int64Value user_id = 1;
|
||||
google.protobuf.StringValue mobile = 2;
|
||||
google.protobuf.StringValue gateway_provider = 3;
|
||||
google.protobuf.BoolValue payment_status = 4;
|
||||
google.protobuf.StringValue authority = 5;
|
||||
google.protobuf.StringValue ref_id = 6;
|
||||
google.protobuf.StringValue order_id = 7;
|
||||
google.protobuf.Timestamp created_from = 8;
|
||||
google.protobuf.Timestamp created_to = 9;
|
||||
}
|
||||
|
||||
message GetAllPaymentTransactionByFilterResponse
|
||||
{
|
||||
messages.MetaData meta_data = 1;
|
||||
repeated PaymentTransactionModel models = 2;
|
||||
}
|
||||
|
||||
message PaymentTransactionModel
|
||||
{
|
||||
int64 id = 1;
|
||||
int64 user_id = 2;
|
||||
string mobile = 3;
|
||||
string gateway_provider = 4;
|
||||
int64 amount = 5;
|
||||
string authority = 6;
|
||||
bool payment_status = 7;
|
||||
google.protobuf.Int32Value verification_status_code = 8;
|
||||
string verification_status_message = 9;
|
||||
string ref_id = 10;
|
||||
string card_pan = 11;
|
||||
string order_id = 12;
|
||||
google.protobuf.Int64Value transaction_id = 13;
|
||||
string description = 14;
|
||||
google.protobuf.Timestamp created_at = 15;
|
||||
}
|
||||
|
||||
message GetPaymentTransactionSummaryRequest
|
||||
{
|
||||
GetAllPaymentTransactionByFilterFilter filter = 1;
|
||||
}
|
||||
|
||||
message GetPaymentTransactionSummaryResponse
|
||||
{
|
||||
int64 total_count = 1;
|
||||
int64 total_amount = 2;
|
||||
int64 successful_count = 3;
|
||||
int64 pending_count = 4;
|
||||
}
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
syntax = "proto3";
|
||||
|
||||
package userpackagepurchase;
|
||||
|
||||
import "public_messages.proto";
|
||||
import "google/protobuf/wrappers.proto";
|
||||
import "google/protobuf/timestamp.proto";
|
||||
import "google/api/annotations.proto";
|
||||
|
||||
option csharp_namespace = "CMSMicroservice.Protobuf.Protos.UserPackagePurchase";
|
||||
|
||||
service UserPackagePurchaseContract
|
||||
{
|
||||
rpc GetAllUserPackagePurchaseByFilter(GetAllUserPackagePurchaseByFilterRequest) returns (GetAllUserPackagePurchaseByFilterResponse){
|
||||
option (google.api.http) = {
|
||||
get: "/UserPackagePurchase/GetAllByFilter"
|
||||
};
|
||||
};
|
||||
rpc GetUserPackagePurchaseSummary(GetUserPackagePurchaseSummaryRequest) returns (GetUserPackagePurchaseSummaryResponse){
|
||||
option (google.api.http) = {
|
||||
get: "/UserPackagePurchase/GetSummary"
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
message GetAllUserPackagePurchaseByFilterRequest
|
||||
{
|
||||
messages.PaginationState pagination_state = 1;
|
||||
google.protobuf.StringValue sort_by = 2;
|
||||
GetAllUserPackagePurchaseByFilterFilter filter = 3;
|
||||
}
|
||||
|
||||
message GetAllUserPackagePurchaseByFilterFilter
|
||||
{
|
||||
google.protobuf.Int64Value user_id = 1;
|
||||
google.protobuf.Int64Value package_id = 2;
|
||||
google.protobuf.Int32Value purchase_method = 3;
|
||||
google.protobuf.Timestamp purchased_from = 4;
|
||||
google.protobuf.Timestamp purchased_to = 5;
|
||||
google.protobuf.Int64Value min_amount = 6;
|
||||
google.protobuf.Int64Value max_amount = 7;
|
||||
}
|
||||
|
||||
message GetAllUserPackagePurchaseByFilterResponse
|
||||
{
|
||||
messages.MetaData meta_data = 1;
|
||||
repeated UserPackagePurchaseModel models = 2;
|
||||
}
|
||||
|
||||
message UserPackagePurchaseModel
|
||||
{
|
||||
int64 id = 1;
|
||||
int64 user_id = 2;
|
||||
string user_name = 3;
|
||||
string user_mobile = 4;
|
||||
int64 package_id = 5;
|
||||
string package_name = 6;
|
||||
int32 purchase_method = 7;
|
||||
google.protobuf.Timestamp purchased_at = 8;
|
||||
int64 amount = 9;
|
||||
google.protobuf.Int64Value order_id = 10;
|
||||
google.protobuf.Int64Value transaction_id = 11;
|
||||
google.protobuf.Timestamp created_at = 12;
|
||||
}
|
||||
|
||||
message GetUserPackagePurchaseSummaryRequest
|
||||
{
|
||||
GetAllUserPackagePurchaseByFilterFilter filter = 1;
|
||||
}
|
||||
|
||||
message GetUserPackagePurchaseSummaryResponse
|
||||
{
|
||||
int64 total_count = 1;
|
||||
int64 total_amount = 2;
|
||||
}
|
||||
@@ -110,6 +110,21 @@ service UserWalletContract
|
||||
body: "*"
|
||||
};
|
||||
};
|
||||
|
||||
// ============= Credit (Main) Wallet Methods =============
|
||||
|
||||
rpc InitiateCreditCharge(InitiateCreditChargeRequest) returns (InitiateCreditChargeResponse){
|
||||
option (google.api.http) = {
|
||||
post: "/Customer/InitiateCreditCharge"
|
||||
body: "*"
|
||||
};
|
||||
};
|
||||
rpc VerifyCreditCharge(VerifyWalletChargeRequest) returns (VerifyWalletChargeResponse){
|
||||
option (google.api.http) = {
|
||||
post: "/Customer/VerifyCreditCharge"
|
||||
body: "*"
|
||||
};
|
||||
};
|
||||
}
|
||||
message CreateNewUserWalletRequest
|
||||
{
|
||||
@@ -283,6 +298,20 @@ message InitiateDiscountChargeResponse
|
||||
string error_message = 3;
|
||||
}
|
||||
|
||||
// ============= Credit (Main) Wallet Messages =============
|
||||
|
||||
message InitiateCreditChargeRequest
|
||||
{
|
||||
int64 amount = 1; // مبلغ واریزی (تومان)
|
||||
}
|
||||
|
||||
message InitiateCreditChargeResponse
|
||||
{
|
||||
bool is_success = 1;
|
||||
string gateway_url = 2;
|
||||
string error_message = 3;
|
||||
}
|
||||
|
||||
// ============= Wallet Verify Messages =============
|
||||
|
||||
message VerifyWalletChargeRequest
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
using Mapster;
|
||||
using AppHistory = CMSMicroservice.Application.ClubMembershipCycleHistoryCQ.Queries.GetAllClubMembershipCycleHistoryByFilter;
|
||||
using ProtoHistory = CMSMicroservice.Protobuf.Protos.ClubMembershipCycleHistory;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Common.Mappings;
|
||||
|
||||
public class ClubMembershipCycleHistoryProfile : IRegister
|
||||
{
|
||||
public void Register(TypeAdapterConfig config)
|
||||
{
|
||||
config.NewConfig<ProtoHistory.GetAllClubMembershipCycleHistoryByFilterRequest, AppHistory.GetAllClubMembershipCycleHistoryByFilterQuery>()
|
||||
.Map(dest => dest.PaginationState, src => src.PaginationState)
|
||||
.Map(dest => dest.SortBy, src => src.SortBy)
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<ProtoHistory.GetAllClubMembershipCycleHistoryByFilterFilter, AppHistory.GetAllClubMembershipCycleHistoryByFilterFilter>()
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.ClubMembershipCycleId, src => src.ClubMembershipCycleId)
|
||||
.Map(dest => dest.CycleNumber, src => src.CycleNumber)
|
||||
.Map(dest => dest.Action, src => src.Action == null ? null : (ClubMembershipCycleAction?)src.Action)
|
||||
.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);
|
||||
|
||||
config.NewConfig<AppHistory.GetAllClubMembershipCycleHistoryByFilterResponseDto, ProtoHistory.GetAllClubMembershipCycleHistoryByFilterResponse>()
|
||||
.Map(dest => dest.MetaData, src => src.MetaData)
|
||||
.Map(dest => dest.Models, src => src.Models);
|
||||
|
||||
config.NewConfig<AppHistory.GetAllClubMembershipCycleHistoryByFilterResponseModel, ProtoHistory.ClubMembershipCycleHistoryModel>()
|
||||
.Map(dest => dest.Id, src => src.Id)
|
||||
.Map(dest => dest.ClubMembershipCycleId, src => src.ClubMembershipCycleId)
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.UserName, src => src.UserName)
|
||||
.Map(dest => dest.CycleNumber, src => src.CycleNumber)
|
||||
.Map(dest => dest.OldIsCurrentCycle, src => src.OldIsCurrentCycle)
|
||||
.Map(dest => dest.NewIsCurrentCycle, src => src.NewIsCurrentCycle)
|
||||
.Map(dest => dest.OldMagicStartedAt, src => src.OldMagicStartedAt)
|
||||
.Map(dest => dest.NewMagicStartedAt, src => src.NewMagicStartedAt)
|
||||
.Map(dest => dest.OldMagicCompletedAt, src => src.OldMagicCompletedAt)
|
||||
.Map(dest => dest.NewMagicCompletedAt, src => src.NewMagicCompletedAt)
|
||||
.Map(dest => dest.Action, src => (int)src.Action)
|
||||
.Map(dest => dest.PerformedBy, src => src.PerformedBy ?? string.Empty)
|
||||
.Map(dest => dest.Reason, src => src.Reason ?? string.Empty)
|
||||
.Map(dest => dest.CreatedAt, src => Timestamp.FromDateTimeOffset(src.Created));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
using Mapster;
|
||||
using AppCycle = CMSMicroservice.Application.ClubMembershipCycleCQ.Queries.GetAllClubMembershipCycleByFilter;
|
||||
using AppCycleSummary = CMSMicroservice.Application.ClubMembershipCycleCQ.Queries.GetClubMembershipCycleSummary;
|
||||
using ProtoCycle = CMSMicroservice.Protobuf.Protos.ClubMembershipCycle;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Common.Mappings;
|
||||
|
||||
public class ClubMembershipCycleProfile : IRegister
|
||||
{
|
||||
public void Register(TypeAdapterConfig config)
|
||||
{
|
||||
config.NewConfig<ProtoCycle.GetAllClubMembershipCycleByFilterRequest, AppCycle.GetAllClubMembershipCycleByFilterQuery>()
|
||||
.Map(dest => dest.PaginationState, src => src.PaginationState)
|
||||
.Map(dest => dest.SortBy, src => src.SortBy)
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<ProtoCycle.GetAllClubMembershipCycleByFilterFilter, AppCycle.GetAllClubMembershipCycleByFilterFilter>()
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.IsCurrentCycle, src => src.IsCurrentCycle)
|
||||
.Map(dest => dest.PackageId, src => src.PackageId)
|
||||
.Map(dest => dest.CycleNumber, src => src.CycleNumber)
|
||||
.Map(dest => dest.PurchaseMethod, src => src.PurchaseMethod == null ? null : (PackagePurchaseMethod?)src.PurchaseMethod)
|
||||
.Map(dest => dest.MagicState, src => src.MagicState)
|
||||
.Map(dest => dest.PackagePurchasedFrom, src => src.PackagePurchasedFrom != null ? src.PackagePurchasedFrom.ToDateTime() : (DateTime?)null)
|
||||
.Map(dest => dest.PackagePurchasedTo, src => src.PackagePurchasedTo != null ? src.PackagePurchasedTo.ToDateTime() : (DateTime?)null);
|
||||
|
||||
config.NewConfig<AppCycle.GetAllClubMembershipCycleByFilterResponseDto, ProtoCycle.GetAllClubMembershipCycleByFilterResponse>()
|
||||
.Map(dest => dest.MetaData, src => src.MetaData)
|
||||
.Map(dest => dest.Models, src => src.Models);
|
||||
|
||||
config.NewConfig<AppCycle.GetAllClubMembershipCycleByFilterResponseModel, ProtoCycle.ClubMembershipCycleModel>()
|
||||
.Map(dest => dest.Id, src => src.Id)
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.UserName, src => src.UserName)
|
||||
.Map(dest => dest.ClubMembershipId, src => src.ClubMembershipId)
|
||||
.Map(dest => dest.CycleNumber, src => src.CycleNumber)
|
||||
.Map(dest => dest.PackageId, src => src.PackageId)
|
||||
.Map(dest => dest.PackageName, src => src.PackageName)
|
||||
.Map(dest => dest.PackageAmount, src => src.PackageAmount)
|
||||
.Map(dest => dest.PurchaseMethod, src => (int)src.PurchaseMethod)
|
||||
.Map(dest => dest.PackagePurchasedAt, src => Timestamp.FromDateTime(DateTime.SpecifyKind(src.PackagePurchasedAt, DateTimeKind.Utc)))
|
||||
.Map(dest => dest.MagicStartedAt, src => src.MagicStartedAt)
|
||||
.Map(dest => dest.MagicCompletedAt, src => src.MagicCompletedAt)
|
||||
.Map(dest => dest.IsCurrentCycle, src => src.IsCurrentCycle)
|
||||
.Map(dest => dest.CreatedAt, src => Timestamp.FromDateTimeOffset(src.Created));
|
||||
|
||||
config.NewConfig<ProtoCycle.GetClubMembershipCycleSummaryRequest, AppCycleSummary.GetClubMembershipCycleSummaryQuery>()
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<AppCycleSummary.GetClubMembershipCycleSummaryResponseDto, ProtoCycle.GetClubMembershipCycleSummaryResponse>()
|
||||
.Map(dest => dest.TotalCount, src => src.TotalCount)
|
||||
.Map(dest => dest.CurrentCycleCount, src => src.CurrentCycleCount)
|
||||
.Map(dest => dest.MagicActiveCount, src => src.MagicActiveCount);
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using CMSMicroservice.Application.ClubMembershipCQ.Queries.GetAllClubMemberships;
|
||||
using CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembership;
|
||||
using CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubStatistics;
|
||||
using CMSMicroservice.Protobuf.Protos.ClubMembership;
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
using AppHistory = CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembershipHistory;
|
||||
using ProtoClub = CMSMicroservice.Protobuf.Protos.ClubMembership;
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using Mapster;
|
||||
using System.Linq;
|
||||
@@ -17,15 +19,15 @@ public class ClubMembershipProfile : IRegister
|
||||
// =====================
|
||||
|
||||
// GetClubMembershipRequest -> GetClubMembershipQuery
|
||||
config.NewConfig<GetClubMembershipRequest, GetClubMembershipQuery>()
|
||||
config.NewConfig<ProtoClub.GetClubMembershipRequest, GetClubMembershipQuery>()
|
||||
.MapWith(src => new GetClubMembershipQuery
|
||||
{
|
||||
UserId = src.UserId
|
||||
});
|
||||
|
||||
// ClubMembershipDto -> GetClubMembershipResponse
|
||||
config.NewConfig<ClubMembershipDto, GetClubMembershipResponse>()
|
||||
.MapWith(src => new GetClubMembershipResponse
|
||||
config.NewConfig<ClubMembershipDto, ProtoClub.GetClubMembershipResponse>()
|
||||
.MapWith(src => new ProtoClub.GetClubMembershipResponse
|
||||
{
|
||||
Id = src.Id,
|
||||
UserId = src.UserId,
|
||||
@@ -48,7 +50,7 @@ public class ClubMembershipProfile : IRegister
|
||||
// =====================
|
||||
|
||||
// GetAllClubMembershipsRequest -> GetAllClubMembershipsQuery
|
||||
config.NewConfig<GetAllClubMembershipsRequest, GetAllClubMembershipsQuery>()
|
||||
config.NewConfig<ProtoClub.GetAllClubMembershipsRequest, GetAllClubMembershipsQuery>()
|
||||
.MapWith(src => new GetAllClubMembershipsQuery
|
||||
{
|
||||
PaginationState = new Application.Common.Models.PaginationState
|
||||
@@ -64,8 +66,8 @@ public class ClubMembershipProfile : IRegister
|
||||
});
|
||||
|
||||
// GetAllClubMembershipsResponseDto -> GetAllClubMembershipsResponse
|
||||
config.NewConfig<GetAllClubMembershipsResponseDto, GetAllClubMembershipsResponse>()
|
||||
.MapWith(src => new GetAllClubMembershipsResponse
|
||||
config.NewConfig<GetAllClubMembershipsResponseDto, ProtoClub.GetAllClubMembershipsResponse>()
|
||||
.MapWith(src => new ProtoClub.GetAllClubMembershipsResponse
|
||||
{
|
||||
MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
|
||||
{
|
||||
@@ -82,12 +84,12 @@ public class ClubMembershipProfile : IRegister
|
||||
// =====================
|
||||
|
||||
// GetClubStatisticsRequest -> GetClubStatisticsQuery
|
||||
config.NewConfig<GetClubStatisticsRequest, GetClubStatisticsQuery>()
|
||||
config.NewConfig<ProtoClub.GetClubStatisticsRequest, GetClubStatisticsQuery>()
|
||||
.MapWith(src => new GetClubStatisticsQuery());
|
||||
|
||||
// GetClubStatisticsResponseDto -> GetClubStatisticsResponse
|
||||
config.NewConfig<GetClubStatisticsResponseDto, GetClubStatisticsResponse>()
|
||||
.MapWith(src => new GetClubStatisticsResponse
|
||||
config.NewConfig<GetClubStatisticsResponseDto, ProtoClub.GetClubStatisticsResponse>()
|
||||
.MapWith(src => new ProtoClub.GetClubStatisticsResponse
|
||||
{
|
||||
TotalMembers = src.TotalMembers,
|
||||
ActiveMembers = src.ActiveMembers,
|
||||
@@ -97,14 +99,14 @@ public class ClubMembershipProfile : IRegister
|
||||
TotalRevenue = src.TotalRevenue,
|
||||
AverageMembershipDurationDays = src.AverageMembershipDurationDays,
|
||||
ExpiringSoonCount = src.ExpiringSoonCount,
|
||||
PackageDistribution = { src.PackageDistribution.Select(p => new PackageLevelDistribution
|
||||
PackageDistribution = { src.PackageDistribution.Select(p => new ProtoClub.PackageLevelDistribution
|
||||
{
|
||||
PackageId = p.PackageId,
|
||||
PackageName = p.PackageName ?? string.Empty,
|
||||
MemberCount = p.MemberCount,
|
||||
Percentage = p.Percentage
|
||||
}) },
|
||||
MonthlyTrend = { src.MonthlyTrend.Select(t => new MonthlyMembershipTrend
|
||||
MonthlyTrend = { src.MonthlyTrend.Select(t => new ProtoClub.MonthlyMembershipTrend
|
||||
{
|
||||
Month = t.Month ?? string.Empty,
|
||||
Activations = t.Activations,
|
||||
@@ -112,24 +114,55 @@ public class ClubMembershipProfile : IRegister
|
||||
NetChange = t.NetChange
|
||||
}) }
|
||||
});
|
||||
|
||||
// GetClubMembershipHistory
|
||||
config.NewConfig<ProtoClub.GetClubMembershipHistoryRequest, AppHistory.GetClubMembershipHistoryQuery>()
|
||||
.Map(dest => dest.PaginationState, src => src.PaginationState)
|
||||
.Map(dest => dest.SortBy, src => src.SortBy)
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<ProtoClub.GetClubMembershipHistoryFilter, AppHistory.GetClubMembershipHistoryFilter>()
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.ClubMembershipId, src => src.ClubMembershipId)
|
||||
.Map(dest => dest.Action, src => src.Action == null ? null : (ClubMembershipAction?)src.Action)
|
||||
.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);
|
||||
|
||||
config.NewConfig<AppHistory.GetClubMembershipHistoryResponseDto, ProtoClub.GetClubMembershipHistoryResponse>()
|
||||
.Map(dest => dest.MetaData, src => src.MetaData)
|
||||
.Map(dest => dest.Models, src => src.Models);
|
||||
|
||||
config.NewConfig<AppHistory.GetClubMembershipHistoryResponseModel, ProtoClub.ClubMembershipHistoryModel>()
|
||||
.Map(dest => dest.Id, src => src.Id)
|
||||
.Map(dest => dest.ClubMembershipId, src => src.ClubMembershipId)
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.UserName, src => src.UserName ?? string.Empty)
|
||||
.Map(dest => dest.OldIsActive, src => src.OldIsActive)
|
||||
.Map(dest => dest.NewIsActive, src => src.NewIsActive)
|
||||
.Map(dest => dest.OldInitialContribution, src => src.OldInitialContribution)
|
||||
.Map(dest => dest.NewInitialContribution, src => src.NewInitialContribution)
|
||||
.Map(dest => dest.Action, src => (int)src.Action)
|
||||
.Map(dest => dest.PerformedBy, src => src.PerformedBy ?? string.Empty)
|
||||
.Map(dest => dest.Reason, src => src.Reason ?? string.Empty)
|
||||
.Map(dest => dest.CreatedAt, src => Timestamp.FromDateTimeOffset(src.Created));
|
||||
}
|
||||
|
||||
private static ClubMembershipModel MapToModel(GetAllClubMembershipsResponseModel src)
|
||||
private static ProtoClub.ClubMembershipModel MapToModel(GetAllClubMembershipsResponseModel src)
|
||||
{
|
||||
return new ClubMembershipModel
|
||||
return new ProtoClub.ClubMembershipModel
|
||||
{
|
||||
Id = src.Id,
|
||||
UserId = src.UserId,
|
||||
UserName = src.UserName ?? string.Empty,
|
||||
PackageId = 0, // Not available in current entity
|
||||
PackageName = string.Empty, // Not available in current entity
|
||||
ActivationCode = string.Empty, // Not available in current entity
|
||||
PackageId = src.PackageId,
|
||||
PackageName = src.PackageName ?? string.Empty,
|
||||
ActivationCode = string.Empty,
|
||||
ActivatedAt = src.ActivatedAt.HasValue
|
||||
? Timestamp.FromDateTime(DateTime.SpecifyKind(src.ActivatedAt.Value, DateTimeKind.Utc))
|
||||
: null,
|
||||
ExpiresAt = null, // Not available in current entity
|
||||
ExpiresAt = null,
|
||||
IsActive = src.IsActive,
|
||||
IsExpired = false, // Calculate based on ExpiresAt if available
|
||||
IsExpired = false,
|
||||
Created = Timestamp.FromDateTime(src.Created.UtcDateTime)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
using Mapster;
|
||||
using AppPt = CMSMicroservice.Application.PaymentTransactionCQ.Queries.GetAllPaymentTransactionByFilter;
|
||||
using AppPtSummary = CMSMicroservice.Application.PaymentTransactionCQ.Queries.GetPaymentTransactionSummary;
|
||||
using ProtoPt = CMSMicroservice.Protobuf.Protos.PaymentTransaction;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Common.Mappings;
|
||||
|
||||
public class PaymentTransactionProfile : IRegister
|
||||
{
|
||||
public void Register(TypeAdapterConfig config)
|
||||
{
|
||||
config.NewConfig<ProtoPt.GetAllPaymentTransactionByFilterRequest, AppPt.GetAllPaymentTransactionByFilterQuery>()
|
||||
.Map(dest => dest.PaginationState, src => src.PaginationState)
|
||||
.Map(dest => dest.SortBy, src => src.SortBy)
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<ProtoPt.GetAllPaymentTransactionByFilterFilter, AppPt.GetAllPaymentTransactionByFilterFilter>()
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.Mobile, src => src.Mobile)
|
||||
.Map(dest => dest.GatewayProvider, src => src.GatewayProvider)
|
||||
.Map(dest => dest.PaymentStatus, src => src.PaymentStatus)
|
||||
.Map(dest => dest.Authority, src => src.Authority)
|
||||
.Map(dest => dest.RefId, src => src.RefId)
|
||||
.Map(dest => dest.OrderId, src => src.OrderId)
|
||||
.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);
|
||||
|
||||
config.NewConfig<AppPt.GetAllPaymentTransactionByFilterResponseDto, ProtoPt.GetAllPaymentTransactionByFilterResponse>()
|
||||
.Map(dest => dest.MetaData, src => src.MetaData)
|
||||
.Map(dest => dest.Models, src => src.Models);
|
||||
|
||||
config.NewConfig<AppPt.GetAllPaymentTransactionByFilterResponseModel, ProtoPt.PaymentTransactionModel>()
|
||||
.Map(dest => dest.Id, src => src.Id)
|
||||
.Map(dest => dest.UserId, src => src.UserId ?? 0)
|
||||
.Map(dest => dest.Mobile, src => src.Mobile ?? string.Empty)
|
||||
.Map(dest => dest.GatewayProvider, src => src.GatewayProvider)
|
||||
.Map(dest => dest.Amount, src => src.Amount)
|
||||
.Map(dest => dest.Authority, src => src.Authority ?? string.Empty)
|
||||
.Map(dest => dest.PaymentStatus, src => src.PaymentStatus)
|
||||
.Map(dest => dest.VerificationStatusCode, src => src.VerificationStatusCode)
|
||||
.Map(dest => dest.VerificationStatusMessage, src => src.VerificationStatusMessage ?? string.Empty)
|
||||
.Map(dest => dest.RefId, src => src.RefId ?? string.Empty)
|
||||
.Map(dest => dest.CardPan, src => src.CardPan ?? string.Empty)
|
||||
.Map(dest => dest.OrderId, src => src.OrderId ?? string.Empty)
|
||||
.Map(dest => dest.TransactionId, src => src.TransactionId)
|
||||
.Map(dest => dest.Description, src => src.Description ?? string.Empty)
|
||||
.Map(dest => dest.CreatedAt, src => Timestamp.FromDateTimeOffset(src.Created));
|
||||
|
||||
config.NewConfig<ProtoPt.GetPaymentTransactionSummaryRequest, AppPtSummary.GetPaymentTransactionSummaryQuery>()
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<AppPtSummary.GetPaymentTransactionSummaryResponseDto, ProtoPt.GetPaymentTransactionSummaryResponse>()
|
||||
.Map(dest => dest.TotalCount, src => src.TotalCount)
|
||||
.Map(dest => dest.TotalAmount, src => src.TotalAmount)
|
||||
.Map(dest => dest.SuccessfulCount, src => src.SuccessfulCount)
|
||||
.Map(dest => dest.PendingCount, src => src.PendingCount);
|
||||
}
|
||||
}
|
||||
@@ -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<Protobuf.Protos.Transactions.GetAllTransactionsByFilterRequest, Application.TransactionsCQ.Queries.GetAllTransactionsByFilter.GetAllTransactionsByFilterQuery>()
|
||||
.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<ProtoTx.GetAllTransactionsByFilterRequest, AppTx.GetAllTransactionsByFilterQuery>()
|
||||
.Map(dest => dest.PaginationState, src => src.PaginationState)
|
||||
.Map(dest => dest.SortBy, src => src.SortBy)
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<ProtoTx.GetAllTransactionsByFilterFilter, AppTx.GetAllTransactionsByFilterFilter>()
|
||||
.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<AppTx.GetAllTransactionsByFilterResponseDto, ProtoTx.GetAllTransactionsByFilterResponse>()
|
||||
.Map(dest => dest.MetaData, src => src.MetaData)
|
||||
.Map(dest => dest.Models, src => src.Models);
|
||||
|
||||
config.NewConfig<AppTx.GetAllTransactionsByFilterResponseModel, ProtoTx.GetAllTransactionsByFilterResponseModel>()
|
||||
.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<ProtoTx.GetTransactionSummaryRequest, AppTxSummary.GetTransactionSummaryQuery>()
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<AppTxSummary.GetTransactionSummaryResponseDto, ProtoTx.GetTransactionSummaryResponse>()
|
||||
.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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
using Google.Protobuf.WellKnownTypes;
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
using Mapster;
|
||||
using AppUp = CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetAllUserPackagePurchaseByFilter;
|
||||
using AppUpSummary = CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetUserPackagePurchaseSummary;
|
||||
using ProtoUp = CMSMicroservice.Protobuf.Protos.UserPackagePurchase;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Common.Mappings;
|
||||
|
||||
public class UserPackagePurchaseProfile : IRegister
|
||||
{
|
||||
public void Register(TypeAdapterConfig config)
|
||||
{
|
||||
config.NewConfig<ProtoUp.GetAllUserPackagePurchaseByFilterRequest, AppUp.GetAllUserPackagePurchaseByFilterQuery>()
|
||||
.Map(dest => dest.PaginationState, src => src.PaginationState)
|
||||
.Map(dest => dest.SortBy, src => src.SortBy)
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<ProtoUp.GetAllUserPackagePurchaseByFilterFilter, AppUp.GetAllUserPackagePurchaseByFilterFilter>()
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.PackageId, src => src.PackageId)
|
||||
.Map(dest => dest.PurchaseMethod, src => src.PurchaseMethod == null ? null : (PackagePurchaseMethod?)src.PurchaseMethod)
|
||||
.Map(dest => dest.PurchasedFrom, src => src.PurchasedFrom != null ? src.PurchasedFrom.ToDateTime() : (DateTime?)null)
|
||||
.Map(dest => dest.PurchasedTo, src => src.PurchasedTo != null ? src.PurchasedTo.ToDateTime() : (DateTime?)null)
|
||||
.Map(dest => dest.MinAmount, src => src.MinAmount)
|
||||
.Map(dest => dest.MaxAmount, src => src.MaxAmount);
|
||||
|
||||
config.NewConfig<AppUp.GetAllUserPackagePurchaseByFilterResponseDto, ProtoUp.GetAllUserPackagePurchaseByFilterResponse>()
|
||||
.Map(dest => dest.MetaData, src => src.MetaData)
|
||||
.Map(dest => dest.Models, src => src.Models);
|
||||
|
||||
config.NewConfig<AppUp.GetAllUserPackagePurchaseByFilterResponseModel, ProtoUp.UserPackagePurchaseModel>()
|
||||
.Map(dest => dest.Id, src => src.Id)
|
||||
.Map(dest => dest.UserId, src => src.UserId)
|
||||
.Map(dest => dest.UserName, src => src.UserName)
|
||||
.Map(dest => dest.UserMobile, src => src.UserMobile)
|
||||
.Map(dest => dest.PackageId, src => src.PackageId)
|
||||
.Map(dest => dest.PackageName, src => src.PackageName)
|
||||
.Map(dest => dest.PurchaseMethod, src => (int)src.PurchaseMethod)
|
||||
.Map(dest => dest.PurchasedAt, src => Timestamp.FromDateTime(DateTime.SpecifyKind(src.PurchasedAt, DateTimeKind.Utc)))
|
||||
.Map(dest => dest.Amount, src => src.Amount)
|
||||
.Map(dest => dest.OrderId, src => src.OrderId)
|
||||
.Map(dest => dest.TransactionId, src => src.TransactionId)
|
||||
.Map(dest => dest.CreatedAt, src => Timestamp.FromDateTimeOffset(src.Created));
|
||||
|
||||
config.NewConfig<ProtoUp.GetUserPackagePurchaseSummaryRequest, AppUpSummary.GetUserPackagePurchaseSummaryQuery>()
|
||||
.Map(dest => dest.Filter, src => src.Filter);
|
||||
|
||||
config.NewConfig<AppUpSummary.GetUserPackagePurchaseSummaryResponseDto, ProtoUp.GetUserPackagePurchaseSummaryResponse>()
|
||||
.Map(dest => dest.TotalCount, src => src.TotalCount)
|
||||
.Map(dest => dest.TotalAmount, src => src.TotalAmount);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using CMSMicroservice.Protobuf.Protos.ClubMembershipCycleHistory;
|
||||
using CMSMicroservice.WebApi.Common.Services;
|
||||
using CMSMicroservice.Application.ClubMembershipCycleHistoryCQ.Queries.GetAllClubMembershipCycleHistoryByFilter;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Services;
|
||||
|
||||
public class ClubMembershipCycleHistoryService : ClubMembershipCycleHistoryContract.ClubMembershipCycleHistoryContractBase
|
||||
{
|
||||
private readonly IDispatchRequestToCQRS _dispatch;
|
||||
|
||||
public ClubMembershipCycleHistoryService(IDispatchRequestToCQRS dispatch) => _dispatch = dispatch;
|
||||
|
||||
public override Task<GetAllClubMembershipCycleHistoryByFilterResponse> GetAllClubMembershipCycleHistoryByFilter(
|
||||
GetAllClubMembershipCycleHistoryByFilterRequest request, ServerCallContext context) =>
|
||||
_dispatch.Handle<GetAllClubMembershipCycleHistoryByFilterRequest, GetAllClubMembershipCycleHistoryByFilterQuery, GetAllClubMembershipCycleHistoryByFilterResponse>(request, context);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using CMSMicroservice.Protobuf.Protos.ClubMembershipCycle;
|
||||
using CMSMicroservice.WebApi.Common.Services;
|
||||
using CMSMicroservice.Application.ClubMembershipCycleCQ.Queries.GetAllClubMembershipCycleByFilter;
|
||||
using CMSMicroservice.Application.ClubMembershipCycleCQ.Queries.GetClubMembershipCycleSummary;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Services;
|
||||
|
||||
public class ClubMembershipCycleService : ClubMembershipCycleContract.ClubMembershipCycleContractBase
|
||||
{
|
||||
private readonly IDispatchRequestToCQRS _dispatch;
|
||||
|
||||
public ClubMembershipCycleService(IDispatchRequestToCQRS dispatch) => _dispatch = dispatch;
|
||||
|
||||
public override Task<GetAllClubMembershipCycleByFilterResponse> GetAllClubMembershipCycleByFilter(
|
||||
GetAllClubMembershipCycleByFilterRequest request, ServerCallContext context) =>
|
||||
_dispatch.Handle<GetAllClubMembershipCycleByFilterRequest, GetAllClubMembershipCycleByFilterQuery, GetAllClubMembershipCycleByFilterResponse>(request, context);
|
||||
|
||||
public override Task<GetClubMembershipCycleSummaryResponse> GetClubMembershipCycleSummary(
|
||||
GetClubMembershipCycleSummaryRequest request, ServerCallContext context) =>
|
||||
_dispatch.Handle<GetClubMembershipCycleSummaryRequest, GetClubMembershipCycleSummaryQuery, GetClubMembershipCycleSummaryResponse>(request, context);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using CMSMicroservice.Protobuf.Protos.PaymentTransaction;
|
||||
using CMSMicroservice.WebApi.Common.Services;
|
||||
using CMSMicroservice.Application.PaymentTransactionCQ.Queries.GetAllPaymentTransactionByFilter;
|
||||
using CMSMicroservice.Application.PaymentTransactionCQ.Queries.GetPaymentTransactionSummary;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Services;
|
||||
|
||||
public class PaymentTransactionService : PaymentTransactionContract.PaymentTransactionContractBase
|
||||
{
|
||||
private readonly IDispatchRequestToCQRS _dispatch;
|
||||
|
||||
public PaymentTransactionService(IDispatchRequestToCQRS dispatch) => _dispatch = dispatch;
|
||||
|
||||
public override Task<GetAllPaymentTransactionByFilterResponse> GetAllPaymentTransactionByFilter(
|
||||
GetAllPaymentTransactionByFilterRequest request, ServerCallContext context) =>
|
||||
_dispatch.Handle<GetAllPaymentTransactionByFilterRequest, GetAllPaymentTransactionByFilterQuery, GetAllPaymentTransactionByFilterResponse>(request, context);
|
||||
|
||||
public override Task<GetPaymentTransactionSummaryResponse> GetPaymentTransactionSummary(
|
||||
GetPaymentTransactionSummaryRequest request, ServerCallContext context) =>
|
||||
_dispatch.Handle<GetPaymentTransactionSummaryRequest, GetPaymentTransactionSummaryQuery, GetPaymentTransactionSummaryResponse>(request, context);
|
||||
}
|
||||
@@ -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<GetAllTransactionsByFilterRequest, GetAllTransactionsByFilterQuery, GetAllTransactionsByFilterResponse>(request, context);
|
||||
}
|
||||
|
||||
public override Task<GetTransactionSummaryResponse> GetTransactionSummary(
|
||||
GetTransactionSummaryRequest request, ServerCallContext context) =>
|
||||
_dispatchRequestToCQRS.Handle<GetTransactionSummaryRequest, GetTransactionSummaryQuery, GetTransactionSummaryResponse>(request, context);
|
||||
|
||||
public override async Task<VerifyTransactionResponse> VerifyTransaction(VerifyTransactionRequest request, ServerCallContext context)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using CMSMicroservice.Protobuf.Protos.UserPackagePurchase;
|
||||
using CMSMicroservice.WebApi.Common.Services;
|
||||
using CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetAllUserPackagePurchaseByFilter;
|
||||
using CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetUserPackagePurchaseSummary;
|
||||
|
||||
namespace CMSMicroservice.WebApi.Services;
|
||||
|
||||
public class UserPackagePurchaseService : UserPackagePurchaseContract.UserPackagePurchaseContractBase
|
||||
{
|
||||
private readonly IDispatchRequestToCQRS _dispatch;
|
||||
|
||||
public UserPackagePurchaseService(IDispatchRequestToCQRS dispatch) => _dispatch = dispatch;
|
||||
|
||||
public override Task<GetAllUserPackagePurchaseByFilterResponse> GetAllUserPackagePurchaseByFilter(
|
||||
GetAllUserPackagePurchaseByFilterRequest request, ServerCallContext context) =>
|
||||
_dispatch.Handle<GetAllUserPackagePurchaseByFilterRequest, GetAllUserPackagePurchaseByFilterQuery, GetAllUserPackagePurchaseByFilterResponse>(request, context);
|
||||
|
||||
public override Task<GetUserPackagePurchaseSummaryResponse> GetUserPackagePurchaseSummary(
|
||||
GetUserPackagePurchaseSummaryRequest request, ServerCallContext context) =>
|
||||
_dispatch.Handle<GetUserPackagePurchaseSummaryRequest, GetUserPackagePurchaseSummaryQuery, GetUserPackagePurchaseSummaryResponse>(request, context);
|
||||
}
|
||||
@@ -5,8 +5,10 @@ using CMSMicroservice.Application.UserWalletCQ.Commands.UpdateUserWallet;
|
||||
using CMSMicroservice.Application.UserWalletCQ.Commands.DeleteUserWallet;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.ChargeMagicWallet;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.ChargeDiscountWallet;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.ChargeCreditWallet;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyMagicWalletCharge;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyDiscountWalletCharge;
|
||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyCreditWalletCharge;
|
||||
using CMSMicroservice.Application.UserWalletCQ.Queries.GetUserWallet;
|
||||
using CMSMicroservice.Application.UserWalletCQ.Queries.GetAllUserWalletByFilter;
|
||||
using CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletHistory;
|
||||
@@ -242,6 +244,38 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
|
||||
}
|
||||
}
|
||||
|
||||
// ============= Credit (Main) Wallet Methods =============
|
||||
|
||||
public override async Task<InitiateCreditChargeResponse> InitiateCreditCharge(
|
||||
InitiateCreditChargeRequest request, ServerCallContext context)
|
||||
{
|
||||
var userId = GetCurrentUserId();
|
||||
|
||||
try
|
||||
{
|
||||
var result = await _sender.Send(new ChargeCreditWalletCommand
|
||||
{
|
||||
UserId = userId,
|
||||
Amount = request.Amount
|
||||
}, context.CancellationToken);
|
||||
|
||||
return new InitiateCreditChargeResponse
|
||||
{
|
||||
IsSuccess = result.IsSuccess,
|
||||
GatewayUrl = result.GatewayUrl ?? "",
|
||||
ErrorMessage = result.ErrorMessage ?? ""
|
||||
};
|
||||
}
|
||||
catch (PaymentInProgressException ex)
|
||||
{
|
||||
return new InitiateCreditChargeResponse
|
||||
{
|
||||
IsSuccess = false,
|
||||
ErrorMessage = ex.Message
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// ============= Wallet Verify Methods =============
|
||||
|
||||
public override async Task<VerifyWalletChargeResponse> VerifyMagicCharge(
|
||||
@@ -330,6 +364,57 @@ public class UserWalletService : UserWalletContract.UserWalletContractBase
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<VerifyWalletChargeResponse> VerifyCreditCharge(
|
||||
VerifyWalletChargeRequest request, ServerCallContext context)
|
||||
{
|
||||
_logger.LogInformation("VerifyCreditCharge called: Authority={Authority}, Status={Status}",
|
||||
request.Authority, request.Status);
|
||||
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(request.Authority))
|
||||
return new VerifyWalletChargeResponse { Success = false, Message = "کد Authority نامعتبر است" };
|
||||
|
||||
var paymentTx = await _context.PaymentTransactions
|
||||
.FirstOrDefaultAsync(pt => pt.Authority == request.Authority, context.CancellationToken);
|
||||
|
||||
if (paymentTx == null || !paymentTx.UserId.HasValue)
|
||||
{
|
||||
_logger.LogError("VerifyCreditCharge: PaymentTransaction not found for Authority={Authority}", request.Authority);
|
||||
return new VerifyWalletChargeResponse { Success = false, Message = "تراکنش یافت نشد" };
|
||||
}
|
||||
|
||||
if (!string.Equals(request.Status, "OK", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
_logger.LogWarning("VerifyCreditCharge: Payment cancelled by user. Authority={Authority}", request.Authority);
|
||||
return new VerifyWalletChargeResponse { Success = false, Message = "پرداخت توسط کاربر لغو شد" };
|
||||
}
|
||||
|
||||
var result = await _sender.Send(new VerifyCreditWalletChargeCommand
|
||||
{
|
||||
UserId = paymentTx.UserId.Value,
|
||||
Amount = paymentTx.Amount,
|
||||
Authority = request.Authority
|
||||
}, context.CancellationToken);
|
||||
|
||||
_logger.LogInformation("VerifyCreditCharge result: {Result}, Authority={Authority}, UserId={UserId}",
|
||||
result, request.Authority, paymentTx.UserId.Value);
|
||||
|
||||
return new VerifyWalletChargeResponse
|
||||
{
|
||||
Success = result,
|
||||
Message = result
|
||||
? "شارژ کیف پول اصلی با موفقیت انجام شد"
|
||||
: "شارژ کیف پول اصلی ناموفق بود"
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "VerifyCreditCharge error: Authority={Authority}", request.Authority);
|
||||
return new VerifyWalletChargeResponse { Success = false, Message = ex.Message };
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task<GetMagicWalletStatusResponse> GetMagicWalletStatus(
|
||||
Google.Protobuf.WellKnownTypes.Empty request, ServerCallContext context)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user