Compare commits
32 Commits
d82b7c28a8
...
production
| Author | SHA1 | Date | |
|---|---|---|---|
| c814cd9118 | |||
| 2d23dbc798 | |||
| 8ec0910cdf | |||
| e882f09955 | |||
| 436e5d7aca | |||
| 6a04a6a270 | |||
| 427d2cce1d | |||
| fb9e3d0109 | |||
| 6c90e4caf0 | |||
| 40da1bd8df | |||
| 053c5a7c4f | |||
| 3810146651 | |||
| 82944e11d0 | |||
| ce98efdd68 | |||
| d232399f43 | |||
| bb20ad2c4e | |||
| 246d893b62 | |||
| 99aab3beff | |||
| 728f28f525 | |||
| 89af07c122 | |||
| 58aeddf004 | |||
| 6c3fbe43b1 | |||
| 7570c39e65 | |||
| 46ac1d817e | |||
| db20d95b43 | |||
| f8794bbb63 | |||
| 19be5dc9dc | |||
| 6395f63ab5 | |||
| 758640cce3 | |||
| 5c1e3cf601 | |||
| 37820ea257 | |||
| 5f8e30905d |
@@ -1,3 +1,4 @@
|
|||||||
# CMS Microservice
|
# CMS Microservice
|
||||||
|
|
||||||
Documentation moved to [totalDoc/INDEX.md](../totalDoc/INDEX.md).
|
Documentation moved to [totalDoc/INDEX.md](../totalDoc/INDEX.md).
|
||||||
|
|
||||||
@@ -24,6 +24,8 @@ stringData:
|
|||||||
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
"MerchantId": "4225d555-5fa9-4df0-9b61-1ce152cbbba8",
|
||||||
"UseSandbox": true
|
"UseSandbox": true
|
||||||
},
|
},
|
||||||
|
"CmsBaseUrl": "https://cms.se.kbs1.ir",
|
||||||
|
"FrontOfficeBaseUrl": "https://frontoffice.se.kbs1.ir",
|
||||||
"FMS": {
|
"FMS": {
|
||||||
"Address": "https://dl.afrino.co"
|
"Address": "https://dl.afrino.co"
|
||||||
},
|
},
|
||||||
|
|||||||
+7
-2
@@ -1,4 +1,5 @@
|
|||||||
using CMSMicroservice.Application.Common.Exceptions;
|
using CMSMicroservice.Application.Common.Exceptions;
|
||||||
|
using CMSMicroservice.Application.Common.Helpers;
|
||||||
using CMSMicroservice.Application.Common.Interfaces;
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
using CMSMicroservice.Application.Common.Models;
|
using CMSMicroservice.Application.Common.Models;
|
||||||
using CMSMicroservice.Domain.Common;
|
using CMSMicroservice.Domain.Common;
|
||||||
@@ -162,10 +163,10 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
|||||||
request.UserId
|
request.UserId
|
||||||
);
|
);
|
||||||
|
|
||||||
// در فعالسازی اجباری، اگر PackagePurchaseMethod تنظیم نشده، مقدار DirectPurchase بگذار
|
// در فعالسازی اجباری ادمین، اگر روش خرید تنظیم نشده، دستی در نظر بگیر
|
||||||
if (user.PackagePurchaseMethod == PackagePurchaseMethod.None)
|
if (user.PackagePurchaseMethod == PackagePurchaseMethod.None)
|
||||||
{
|
{
|
||||||
user.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
|
user.PackagePurchaseMethod = PackagePurchaseMethod.Manual;
|
||||||
_context.Users.Update(user);
|
_context.Users.Update(user);
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
@@ -272,6 +273,7 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
|||||||
foreach (var prevCycle in previousCycles)
|
foreach (var prevCycle in previousCycles)
|
||||||
{
|
{
|
||||||
prevCycle.IsCurrentCycle = false;
|
prevCycle.IsCurrentCycle = false;
|
||||||
|
ClubMembershipCycleHistoryWriter.WriteCycleClosed(_context, prevCycle, reason: "شروع دوره جدید");
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxCycleNumber = await _context.ClubMembershipCycles
|
var maxCycleNumber = await _context.ClubMembershipCycles
|
||||||
@@ -293,6 +295,9 @@ public class ActivateClubMembershipCommandHandler : IRequestHandler<ActivateClub
|
|||||||
_context.ClubMembershipCycles.Add(newCycle);
|
_context.ClubMembershipCycles.Add(newCycle);
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
ClubMembershipCycleHistoryWriter.WriteCycleStarted(_context, newCycle, reason: "فعالسازی عضویت باشگاه");
|
||||||
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"Created ClubMembershipCycle #{CycleNumber} for UserId {UserId}, MembershipId {MembershipId}",
|
"Created ClubMembershipCycle #{CycleNumber} for UserId {UserId}, MembershipId {MembershipId}",
|
||||||
newCycle.CycleNumber,
|
newCycle.CycleNumber,
|
||||||
|
|||||||
+4
-1
@@ -13,6 +13,7 @@ public class GetAllClubMembershipsQueryHandler : IRequestHandler<GetAllClubMembe
|
|||||||
{
|
{
|
||||||
var query = _context.ClubMemberships
|
var query = _context.ClubMemberships
|
||||||
.Include(x => x.User)
|
.Include(x => x.User)
|
||||||
|
.Include(x => x.LastPackage)
|
||||||
.ApplyOrder(sortBy: request.SortBy)
|
.ApplyOrder(sortBy: request.SortBy)
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.AsQueryable();
|
.AsQueryable();
|
||||||
@@ -35,8 +36,10 @@ public class GetAllClubMembershipsQueryHandler : IRequestHandler<GetAllClubMembe
|
|||||||
Id = x.Id,
|
Id = x.Id,
|
||||||
UserId = x.UserId,
|
UserId = x.UserId,
|
||||||
UserName = x.User != null ? $"{x.User.FirstName} {x.User.LastName}" : string.Empty,
|
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,
|
IsActive = x.IsActive,
|
||||||
ActivatedAt = x.ActivatedAt,
|
ActivatedAt = x.LastActivationDate ?? x.ActivatedAt,
|
||||||
InitialContribution = x.InitialContribution,
|
InitialContribution = x.InitialContribution,
|
||||||
TotalEarned = x.TotalEarned,
|
TotalEarned = x.TotalEarned,
|
||||||
Created = x.Created,
|
Created = x.Created,
|
||||||
|
|||||||
+2
@@ -11,6 +11,8 @@ public class GetAllClubMembershipsResponseModel
|
|||||||
public long Id { get; set; }
|
public long Id { get; set; }
|
||||||
public long UserId { get; set; }
|
public long UserId { get; set; }
|
||||||
public string UserName { get; set; } = string.Empty;
|
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 bool IsActive { get; set; }
|
||||||
public DateTime? ActivatedAt { get; set; }
|
public DateTime? ActivatedAt { get; set; }
|
||||||
public long InitialContribution { get; set; }
|
public long InitialContribution { get; set; }
|
||||||
|
|||||||
+10
-20
@@ -1,27 +1,17 @@
|
|||||||
namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembershipHistory;
|
namespace CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembershipHistory;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Query برای دریافت تاریخچه تغییرات عضویت باشگاه
|
|
||||||
/// </summary>
|
|
||||||
public record GetClubMembershipHistoryQuery : IRequest<GetClubMembershipHistoryResponseDto>
|
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; }
|
public PaginationState? PaginationState { get; init; }
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// مرتبسازی بر اساس
|
|
||||||
/// </summary>
|
|
||||||
public string? SortBy { get; init; }
|
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)
|
public async Task<GetClubMembershipHistoryResponseDto> Handle(GetClubMembershipHistoryQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var query = _context.ClubMembershipHistories
|
var query = _context.ClubMembershipHistories
|
||||||
|
.Include(x => x.ClubMembership)
|
||||||
|
.ThenInclude(m => m!.User)
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.AsQueryable();
|
.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.ApplyOrder(sortBy: request.SortBy ?? "-Created");
|
||||||
{
|
|
||||||
query = query.Where(x => x.UserId == request.UserId.Value);
|
|
||||||
}
|
|
||||||
|
|
||||||
query = query.ApplyOrder(sortBy: request.SortBy ?? "Created"); // پیشفرض: جدیدترین اول
|
|
||||||
|
|
||||||
var meta = await query.GetMetaData(request.PaginationState, cancellationToken);
|
var meta = await query.GetMetaData(request.PaginationState, cancellationToken);
|
||||||
|
|
||||||
@@ -36,6 +46,9 @@ public class GetClubMembershipHistoryQueryHandler : IRequestHandler<GetClubMembe
|
|||||||
Id = x.Id,
|
Id = x.Id,
|
||||||
ClubMembershipId = x.ClubMembershipId,
|
ClubMembershipId = x.ClubMembershipId,
|
||||||
UserId = x.UserId,
|
UserId = x.UserId,
|
||||||
|
UserName = x.ClubMembership != null && x.ClubMembership.User != null
|
||||||
|
? $"{x.ClubMembership.User.FirstName} {x.ClubMembership.User.LastName}"
|
||||||
|
: string.Empty,
|
||||||
OldIsActive = x.OldIsActive,
|
OldIsActive = x.OldIsActive,
|
||||||
NewIsActive = x.NewIsActive,
|
NewIsActive = x.NewIsActive,
|
||||||
OldInitialContribution = x.OldInitialContribution,
|
OldInitialContribution = x.OldInitialContribution,
|
||||||
|
|||||||
+1
-26
@@ -4,31 +4,6 @@ public class GetClubMembershipHistoryQueryValidator : AbstractValidator<GetClubM
|
|||||||
{
|
{
|
||||||
public GetClubMembershipHistoryQueryValidator()
|
public GetClubMembershipHistoryQueryValidator()
|
||||||
{
|
{
|
||||||
RuleFor(x => x.MembershipId)
|
// Admin report: filters are all optional
|
||||||
.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 باید مقداردهی شود");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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 Id { get; set; }
|
||||||
public long ClubMembershipId { get; set; }
|
public long ClubMembershipId { get; set; }
|
||||||
public long UserId { get; set; }
|
public long UserId { get; set; }
|
||||||
|
public string UserName { get; set; } = string.Empty;
|
||||||
public bool OldIsActive { get; set; }
|
public bool OldIsActive { get; set; }
|
||||||
public bool NewIsActive { get; set; }
|
public bool NewIsActive { get; set; }
|
||||||
public long? OldInitialContribution { 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)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
+3
-40
@@ -1,5 +1,4 @@
|
|||||||
using CMSMicroservice.Application.Common.Interfaces;
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
using CMSMicroservice.Domain.Entities;
|
|
||||||
using CMSMicroservice.Domain.Entities.Commission;
|
using CMSMicroservice.Domain.Entities.Commission;
|
||||||
using CMSMicroservice.Domain.Entities.History;
|
using CMSMicroservice.Domain.Entities.History;
|
||||||
using CMSMicroservice.Domain.Enums;
|
using CMSMicroservice.Domain.Enums;
|
||||||
@@ -25,7 +24,6 @@ public class BulkCreditPayoutsCommandHandler : IRequestHandler<BulkCreditPayouts
|
|||||||
|
|
||||||
public async Task<BulkCreditPayoutsResult> Handle(BulkCreditPayoutsCommand request, CancellationToken cancellationToken)
|
public async Task<BulkCreditPayoutsResult> Handle(BulkCreditPayoutsCommand request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
// بارگذاری همه پرداختهای Pending این هفته
|
|
||||||
var pendingPayouts = await _context.UserCommissionPayouts
|
var pendingPayouts = await _context.UserCommissionPayouts
|
||||||
.Where(p => p.WeekDefinitionId == request.WeekDefinitionId
|
.Where(p => p.WeekDefinitionId == request.WeekDefinitionId
|
||||||
&& p.Status == CommissionPayoutStatus.Pending
|
&& p.Status == CommissionPayoutStatus.Pending
|
||||||
@@ -37,72 +35,37 @@ public class BulkCreditPayoutsCommandHandler : IRequestHandler<BulkCreditPayouts
|
|||||||
return new BulkCreditPayoutsResult { CreditedCount = 0, TotalCredited = 0 };
|
return new BulkCreditPayoutsResult { CreditedCount = 0, TotalCredited = 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
// بارگذاری کیف پول همه کاربران مربوطه (یک query)
|
|
||||||
var userIds = pendingPayouts.Select(p => p.UserId).Distinct().ToList();
|
|
||||||
var wallets = await _context.UserWallets
|
|
||||||
.Where(w => userIds.Contains(w.UserId) && !w.IsDeleted)
|
|
||||||
.ToDictionaryAsync(w => w.UserId, cancellationToken);
|
|
||||||
|
|
||||||
var performedBy = _currentUser.GetPerformedBy() ?? "System";
|
var performedBy = _currentUser.GetPerformedBy() ?? "System";
|
||||||
var now = DateTime.UtcNow;
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
var walletHistories = new List<UserWalletHistory>();
|
|
||||||
var payoutHistories = new List<CommissionPayoutHistory>();
|
var payoutHistories = new List<CommissionPayoutHistory>();
|
||||||
var creditedCount = 0;
|
var creditedCount = 0;
|
||||||
long totalCredited = 0;
|
long totalCredited = 0;
|
||||||
|
|
||||||
foreach (var payout in pendingPayouts)
|
foreach (var payout in pendingPayouts)
|
||||||
{
|
{
|
||||||
if (!wallets.TryGetValue(payout.UserId, out var wallet))
|
|
||||||
{
|
|
||||||
_logger.LogWarning(
|
|
||||||
"Wallet not found for UserId={UserId}, PayoutId={PayoutId} — skipping",
|
|
||||||
payout.UserId, payout.Id);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var oldBalance = wallet.Balance;
|
|
||||||
|
|
||||||
// واریز مبلغ به کیف پول
|
|
||||||
wallet.Balance += payout.TotalAmount;
|
|
||||||
|
|
||||||
walletHistories.Add(new UserWalletHistory
|
|
||||||
{
|
|
||||||
WalletId = wallet.Id,
|
|
||||||
CurrentBalance = wallet.Balance,
|
|
||||||
CurrentNetworkBalance = wallet.NetworkBalance,
|
|
||||||
CurrentDiscountBalance = wallet.DiscountBalance,
|
|
||||||
ChangeValue = payout.TotalAmount,
|
|
||||||
ChangeNerworkValue = 0,
|
|
||||||
ChangeDiscountValue = 0,
|
|
||||||
IsIncrease = true,
|
|
||||||
RefrenceId = payout.Id
|
|
||||||
});
|
|
||||||
|
|
||||||
// بهروزرسانی وضعیت پرداخت
|
|
||||||
payout.Status = CommissionPayoutStatus.Paid;
|
payout.Status = CommissionPayoutStatus.Paid;
|
||||||
payout.PaidAt = now;
|
payout.PaidAt = now;
|
||||||
payout.LastModified = now;
|
payout.LastModified = now;
|
||||||
|
|
||||||
payoutHistories.Add(new CommissionPayoutHistory
|
payoutHistories.Add(new CommissionPayoutHistory
|
||||||
{
|
{
|
||||||
UserCommissionPayoutId = payout.Id,
|
UserCommissionPayoutId = payout.Id,
|
||||||
UserId = payout.UserId,
|
UserId = payout.UserId,
|
||||||
WeekDefinitionId = payout.WeekDefinitionId,
|
WeekDefinitionId = payout.WeekDefinitionId,
|
||||||
AmountBefore = 0,
|
AmountBefore = payout.TotalAmount,
|
||||||
AmountAfter = payout.TotalAmount,
|
AmountAfter = payout.TotalAmount,
|
||||||
OldStatus = CommissionPayoutStatus.Pending,
|
OldStatus = CommissionPayoutStatus.Pending,
|
||||||
NewStatus = CommissionPayoutStatus.Paid,
|
NewStatus = CommissionPayoutStatus.Paid,
|
||||||
Action = CommissionPayoutAction.Paid,
|
Action = CommissionPayoutAction.Paid,
|
||||||
PerformedBy = performedBy,
|
PerformedBy = performedBy,
|
||||||
Reason = $"واریز دستهجمعی کمیسیون هفته {payout.WeekDefinitionId} توسط {performedBy}"
|
Reason = $"تایید پرداخت دستهجمعی کمیسیون هفته {payout.WeekDefinitionId} توسط {performedBy}"
|
||||||
});
|
});
|
||||||
|
|
||||||
creditedCount++;
|
creditedCount++;
|
||||||
totalCredited += payout.TotalAmount;
|
totalCredited += payout.TotalAmount;
|
||||||
}
|
}
|
||||||
|
|
||||||
await _context.UserWalletHistories.AddRangeAsync(walletHistories, cancellationToken);
|
|
||||||
await _context.CommissionPayoutHistories.AddRangeAsync(payoutHistories, cancellationToken);
|
await _context.CommissionPayoutHistories.AddRangeAsync(payoutHistories, cancellationToken);
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
|||||||
+6
-1
@@ -1,3 +1,5 @@
|
|||||||
|
using CMSMicroservice.Application.Common;
|
||||||
|
|
||||||
namespace CMSMicroservice.Application.CommissionCQ.Commands.RequestWithdrawal;
|
namespace CMSMicroservice.Application.CommissionCQ.Commands.RequestWithdrawal;
|
||||||
|
|
||||||
public class RequestWithdrawalCommandHandler : IRequestHandler<RequestWithdrawalCommand, Unit>
|
public class RequestWithdrawalCommandHandler : IRequestHandler<RequestWithdrawalCommand, Unit>
|
||||||
@@ -37,7 +39,10 @@ public class RequestWithdrawalCommandHandler : IRequestHandler<RequestWithdrawal
|
|||||||
|
|
||||||
if (request.Method == WithdrawalMethod.Cash)
|
if (request.Method == WithdrawalMethod.Cash)
|
||||||
{
|
{
|
||||||
payout.IbanNumber = request.IbanNumber;
|
var normalizedIban = IbanNormalizer.TryNormalize(request.IbanNumber);
|
||||||
|
if (normalizedIban is null)
|
||||||
|
throw new InvalidOperationException("فرمت شماره شبا معتبر نیست. باید IR و ۲۴ رقم باشد.");
|
||||||
|
payout.IbanNumber = normalizedIban;
|
||||||
}
|
}
|
||||||
|
|
||||||
_context.UserCommissionPayouts.Update(payout);
|
_context.UserCommissionPayouts.Update(payout);
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Linq.Expressions;
|
||||||
using System.Linq.Dynamic.Core;
|
using System.Linq.Dynamic.Core;
|
||||||
using CMSMicroservice.Domain.Common;
|
using CMSMicroservice.Domain.Common;
|
||||||
|
|
||||||
@@ -8,16 +9,46 @@ public static class SortByExtensions
|
|||||||
public static IQueryable<TSource> ApplyOrder<TSource>(this IQueryable<TSource> source,
|
public static IQueryable<TSource> ApplyOrder<TSource>(this IQueryable<TSource> source,
|
||||||
string? sortBy) where TSource : BaseAuditableEntity
|
string? sortBy) where TSource : BaseAuditableEntity
|
||||||
{
|
{
|
||||||
// default sort approach
|
|
||||||
if (sortBy is null or "")
|
if (sortBy is null or "")
|
||||||
{
|
{
|
||||||
source = source.OrderByDescending(p => p.Created);
|
return source.OrderByDescending(p => p.Created);
|
||||||
return source;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// sort using dynamic linq
|
return source.OrderBy(NormalizeSortBy(sortBy));
|
||||||
source = source.OrderBy(sortBy);
|
}
|
||||||
|
|
||||||
return source;
|
/// <summary>
|
||||||
|
/// موجودیدارها اول، سپس سورت درخواستی کاربر (یا Created desc اگر SortBy خالی باشد).
|
||||||
|
/// </summary>
|
||||||
|
public static IQueryable<TSource> ApplyOrderWithInStockPriority<TSource>(
|
||||||
|
this IQueryable<TSource> source,
|
||||||
|
string? sortBy,
|
||||||
|
Expression<Func<TSource, bool>> isInStock) where TSource : BaseAuditableEntity
|
||||||
|
{
|
||||||
|
var ordered = source.OrderByDescending(isInStock);
|
||||||
|
if (string.IsNullOrWhiteSpace(sortBy))
|
||||||
|
return ordered.ThenByDescending(p => p.Created);
|
||||||
|
|
||||||
|
return ordered.ThenBy(NormalizeSortBy(sortBy));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <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 ?? "دوره جدید جایگزین شد"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Application.Common;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// نرمالسازی و اعتبارسنجی شماره شبا ایران (IR + 24 رقم).
|
||||||
|
/// </summary>
|
||||||
|
public static class IbanNormalizer
|
||||||
|
{
|
||||||
|
private static readonly Regex IranianIbanRegex = new(@"^IR\d{24}$", RegexOptions.Compiled);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// فاصله و خط تیره را حذف میکند، به حروف بزرگ تبدیل میکند و یک پیشوند IR میگذارد.
|
||||||
|
/// در صورت نامعتبر بودن، null برمیگرداند.
|
||||||
|
/// </summary>
|
||||||
|
public static string? TryNormalize(string? iban)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(iban))
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var normalized = iban.Trim().ToUpperInvariant()
|
||||||
|
.Replace(" ", "", StringComparison.Ordinal)
|
||||||
|
.Replace("-", "", StringComparison.Ordinal);
|
||||||
|
|
||||||
|
if (normalized.StartsWith("IR", StringComparison.Ordinal))
|
||||||
|
normalized = normalized[2..];
|
||||||
|
|
||||||
|
normalized = "IR" + normalized;
|
||||||
|
|
||||||
|
return IranianIbanRegex.IsMatch(normalized) ? normalized : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool IsValid(string? iban) => TryNormalize(iban) is not null;
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
namespace CMSMicroservice.Application.Common;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// نام نمایشی کاربر برای گزارشها؛ اگر نام خالی باشد موبایل یا شناسه.
|
||||||
|
/// </summary>
|
||||||
|
public static class UserDisplayName
|
||||||
|
{
|
||||||
|
public static string From(string? firstName, string? lastName, string? mobile, long userId)
|
||||||
|
{
|
||||||
|
var name = string.Join(" ",
|
||||||
|
new[] { firstName, lastName }.Where(s => !string.IsNullOrWhiteSpace(s)));
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(name))
|
||||||
|
return name;
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(mobile))
|
||||||
|
return mobile.Trim();
|
||||||
|
|
||||||
|
return userId > 0 ? $"کاربر {userId}" : "—";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string From(Domain.Entities.User? user)
|
||||||
|
{
|
||||||
|
if (user is null)
|
||||||
|
return string.Empty;
|
||||||
|
|
||||||
|
return From(user.FirstName, user.LastName, user.Mobile, user.Id);
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -35,6 +35,11 @@ public class UpdateOrderStatusCommandHandler : IRequestHandler<UpdateOrderStatus
|
|||||||
order.TrackingCode = request.TrackingCode;
|
order.TrackingCode = request.TrackingCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrEmpty(request.AdminNotes))
|
||||||
|
{
|
||||||
|
order.DeliveryDescription = request.AdminNotes;
|
||||||
|
}
|
||||||
|
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
return new UpdateOrderStatusResponseDto
|
return new UpdateOrderStatusResponseDto
|
||||||
|
|||||||
+42
-18
@@ -1,3 +1,4 @@
|
|||||||
|
using CMSMicroservice.Application.Common;
|
||||||
using CMSMicroservice.Application.Common.Interfaces;
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
using CMSMicroservice.Application.Common.Models;
|
using CMSMicroservice.Application.Common.Models;
|
||||||
using MediatR;
|
using MediatR;
|
||||||
@@ -80,35 +81,58 @@ public class GetAllDiscountOrdersQueryHandler : IRequestHandler<GetAllDiscountOr
|
|||||||
// Apply pagination
|
// Apply pagination
|
||||||
var pagination = request.PaginationQuery ?? new PaginationState { PageNumber = 1, PageSize = 20 };
|
var pagination = request.PaginationQuery ?? new PaginationState { PageNumber = 1, PageSize = 20 };
|
||||||
|
|
||||||
var orders = await query
|
var rows = await query
|
||||||
.OrderByDescending(o => o.Created)
|
.OrderByDescending(o => o.Created)
|
||||||
.Skip((pagination.PageNumber - 1) * pagination.PageSize)
|
.Skip((pagination.PageNumber - 1) * pagination.PageSize)
|
||||||
.Take(pagination.PageSize)
|
.Take(pagination.PageSize)
|
||||||
.Select(o => new AdminOrderDto
|
.Select(o => new
|
||||||
{
|
{
|
||||||
Id = o.Id,
|
o.Id,
|
||||||
UserId = o.UserId,
|
o.UserId,
|
||||||
UserFullName = (o.User.FirstName ?? "") + " " + (o.User.LastName ?? ""),
|
FirstName = o.User.FirstName,
|
||||||
UserMobile = o.User.Mobile,
|
LastName = o.User.LastName,
|
||||||
TotalAmount = o.TotalAmount,
|
Mobile = o.User.Mobile,
|
||||||
DiscountBalanceUsed = o.DiscountBalanceUsed,
|
o.TotalAmount,
|
||||||
GatewayAmountPaid = o.GatewayAmountPaid,
|
o.DiscountBalanceUsed,
|
||||||
VatAmount = o.VatAmount,
|
o.GatewayAmountPaid,
|
||||||
PaymentStatus = o.PaymentStatus,
|
o.VatAmount,
|
||||||
PaymentDate = o.PaymentDate,
|
o.PaymentStatus,
|
||||||
DeliveryStatus = o.DeliveryStatus,
|
o.PaymentDate,
|
||||||
DeliveryDate = null, // TODO: Add DeliveryDate to DiscountOrder if needed
|
o.DeliveryStatus,
|
||||||
ShippingAddress = o.UserAddress.Address,
|
ShippingAddress = o.UserAddress.Address,
|
||||||
ReceiverName = o.UserAddress.Title,
|
ReceiverName = o.UserAddress.Title,
|
||||||
ReceiverMobile = o.User.Mobile,
|
o.TrackingCode,
|
||||||
TrackingCode = o.TrackingCode,
|
|
||||||
AdminNote = o.DeliveryDescription,
|
AdminNote = o.DeliveryDescription,
|
||||||
Created = o.Created,
|
o.Created,
|
||||||
LastModified = o.LastModified,
|
o.LastModified,
|
||||||
ItemsCount = o.OrderDetails.Count
|
ItemsCount = o.OrderDetails.Count
|
||||||
})
|
})
|
||||||
.ToListAsync(cancellationToken);
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
var orders = rows.Select(o => new AdminOrderDto
|
||||||
|
{
|
||||||
|
Id = o.Id,
|
||||||
|
UserId = o.UserId,
|
||||||
|
UserFullName = UserDisplayName.From(o.FirstName, o.LastName, o.Mobile, o.UserId),
|
||||||
|
UserMobile = o.Mobile,
|
||||||
|
TotalAmount = o.TotalAmount,
|
||||||
|
DiscountBalanceUsed = o.DiscountBalanceUsed,
|
||||||
|
GatewayAmountPaid = o.GatewayAmountPaid,
|
||||||
|
VatAmount = o.VatAmount,
|
||||||
|
PaymentStatus = o.PaymentStatus,
|
||||||
|
PaymentDate = o.PaymentDate,
|
||||||
|
DeliveryStatus = o.DeliveryStatus,
|
||||||
|
DeliveryDate = null,
|
||||||
|
ShippingAddress = o.ShippingAddress,
|
||||||
|
ReceiverName = o.ReceiverName,
|
||||||
|
ReceiverMobile = o.Mobile,
|
||||||
|
TrackingCode = o.TrackingCode,
|
||||||
|
AdminNote = o.AdminNote,
|
||||||
|
Created = o.Created,
|
||||||
|
LastModified = o.LastModified,
|
||||||
|
ItemsCount = o.ItemsCount
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
return new GetAllDiscountOrdersResponseDto
|
return new GetAllDiscountOrdersResponseDto
|
||||||
{
|
{
|
||||||
MetaData = new MetaData
|
MetaData = new MetaData
|
||||||
|
|||||||
+4
@@ -8,6 +8,10 @@ public class GetDiscountProductsQuery : IRequest<GetDiscountProductsResponseDto>
|
|||||||
public PaginationState? PaginationQuery { get; set; }
|
public PaginationState? PaginationQuery { get; set; }
|
||||||
public long? CategoryId { get; set; }
|
public long? CategoryId { get; set; }
|
||||||
public string? SearchTerm { get; set; }
|
public string? SearchTerm { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// true = فقط موجود (RemainingCount > 0)، false = فقط ناموجود
|
||||||
|
/// </summary>
|
||||||
|
public bool? InStock { get; set; }
|
||||||
public bool? IsActive { get; set; }
|
public bool? IsActive { get; set; }
|
||||||
public int? MinPrice { get; set; }
|
public int? MinPrice { get; set; }
|
||||||
public int? MaxPrice { get; set; }
|
public int? MaxPrice { get; set; }
|
||||||
|
|||||||
+7
-4
@@ -42,6 +42,11 @@ public class GetDiscountProductsQueryHandler : IRequestHandler<GetDiscountProduc
|
|||||||
query = query.Where(p => p.IsActive == request.IsActive.Value);
|
query = query.Where(p => p.IsActive == request.IsActive.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (request.InStock == true)
|
||||||
|
query = query.Where(p => p.RemainingCount > 0);
|
||||||
|
else if (request.InStock == false)
|
||||||
|
query = query.Where(p => p.RemainingCount <= 0);
|
||||||
|
|
||||||
if (request.MinPrice.HasValue)
|
if (request.MinPrice.HasValue)
|
||||||
{
|
{
|
||||||
query = query.Where(p => p.Price >= request.MinPrice.Value);
|
query = query.Where(p => p.Price >= request.MinPrice.Value);
|
||||||
@@ -52,10 +57,8 @@ public class GetDiscountProductsQueryHandler : IRequestHandler<GetDiscountProduc
|
|||||||
query = query.Where(p => p.Price <= request.MaxPrice.Value);
|
query = query.Where(p => p.Price <= request.MaxPrice.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(request.SortBy))
|
// موجودیدارها اول، سپس سورت درخواستی
|
||||||
query = query.ApplyOrder(request.SortBy);
|
query = query.ApplyOrderWithInStockPriority(request.SortBy, p => p.RemainingCount > 0);
|
||||||
else
|
|
||||||
query = query.OrderByDescending(p => p.Created);
|
|
||||||
|
|
||||||
var totalCount = await query.CountAsync(cancellationToken);
|
var totalCount = await query.CountAsync(cancellationToken);
|
||||||
|
|
||||||
|
|||||||
+2
@@ -32,6 +32,8 @@ public class UserAddressDto
|
|||||||
public string Title { get; set; }
|
public string Title { get; set; }
|
||||||
public string Address { get; set; }
|
public string Address { get; set; }
|
||||||
public string PostalCode { get; set; }
|
public string PostalCode { get; set; }
|
||||||
|
/// <summary>شماره تماس سفارشدهنده (موبایل کاربر) برای برچسب پست</summary>
|
||||||
|
public string? Phone { get; set; }
|
||||||
}
|
}
|
||||||
|
|
||||||
public class OrderItemDto
|
public class OrderItemDto
|
||||||
|
|||||||
+3
-1
@@ -25,6 +25,7 @@ public class GetOrderByIdQueryHandler : IRequestHandler<GetOrderByIdQuery, Order
|
|||||||
|
|
||||||
var order = await query
|
var order = await query
|
||||||
.Include(o => o.UserAddress)
|
.Include(o => o.UserAddress)
|
||||||
|
.Include(o => o.User)
|
||||||
.Include(o => o.OrderDetails)
|
.Include(o => o.OrderDetails)
|
||||||
.ThenInclude(od => od.Product)
|
.ThenInclude(od => od.Product)
|
||||||
.FirstOrDefaultAsync(cancellationToken);
|
.FirstOrDefaultAsync(cancellationToken);
|
||||||
@@ -50,7 +51,8 @@ public class GetOrderByIdQueryHandler : IRequestHandler<GetOrderByIdQuery, Order
|
|||||||
{
|
{
|
||||||
Title = order.UserAddress.Title,
|
Title = order.UserAddress.Title,
|
||||||
Address = order.UserAddress.Address,
|
Address = order.UserAddress.Address,
|
||||||
PostalCode = order.UserAddress.PostalCode
|
PostalCode = order.UserAddress.PostalCode,
|
||||||
|
Phone = order.User?.Mobile
|
||||||
},
|
},
|
||||||
Items = order.OrderDetails.Select(od => new OrderItemDto
|
Items = order.OrderDetails.Select(od => new OrderItemDto
|
||||||
{
|
{
|
||||||
|
|||||||
+12
-2
@@ -150,8 +150,18 @@ public class CreateManualPaymentCommandHandler : IRequestHandler<CreateManualPay
|
|||||||
|
|
||||||
await _context.UserWalletHistories.AddAsync(walletLog, cancellationToken);
|
await _context.UserWalletHistories.AddAsync(walletLog, cancellationToken);
|
||||||
|
|
||||||
// 9. تنظیم روش خرید پکیج
|
// 9. تنظیم روش خرید پکیج + ثبت ledger خرید دستی
|
||||||
user.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
|
user.PackagePurchaseMethod = PackagePurchaseMethod.Manual;
|
||||||
|
|
||||||
|
_context.UserPackagePurchases.Add(new UserPackagePurchase
|
||||||
|
{
|
||||||
|
UserId = request.UserId,
|
||||||
|
PackageId = package.Id,
|
||||||
|
PurchaseMethod = PackagePurchaseMethod.Manual,
|
||||||
|
PurchasedAt = DateTime.Now,
|
||||||
|
Amount = balanceAmount,
|
||||||
|
TransactionId = transaction.Id
|
||||||
|
});
|
||||||
|
|
||||||
// 10. ذخیره همه تغییرات
|
// 10. ذخیره همه تغییرات
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|||||||
+1
-1
@@ -118,7 +118,7 @@ public class ProcessManualMembershipPaymentCommandHandler : IRequestHandler<Proc
|
|||||||
};
|
};
|
||||||
await _context.UserWalletHistories.AddAsync(balanceLog, cancellationToken);
|
await _context.UserWalletHistories.AddAsync(balanceLog, cancellationToken);
|
||||||
|
|
||||||
user.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
|
user.PackagePurchaseMethod = PackagePurchaseMethod.Manual;
|
||||||
// 10. بهروزرسانی ManualPayment با TransactionId
|
// 10. بهروزرسانی ManualPayment با TransactionId
|
||||||
manualPayment.TransactionId = transaction.Id;
|
manualPayment.TransactionId = transaction.Id;
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|||||||
+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
@@ -21,6 +21,10 @@ public class GetCustomerProductsByFilterQuery : IRequest<GetCustomerProductsByFi
|
|||||||
public int? SaleCount { get; set; }
|
public int? SaleCount { get; set; }
|
||||||
public int? ViewCount { get; set; }
|
public int? ViewCount { get; set; }
|
||||||
public int? RemainingCount { get; set; }
|
public int? RemainingCount { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// true = فقط موجود (RemainingCount > 0)، false = فقط ناموجود
|
||||||
|
/// </summary>
|
||||||
|
public bool? InStock { get; set; }
|
||||||
public bool? IsActive { get; set; }
|
public bool? IsActive { get; set; }
|
||||||
public List<long>? CategoryIds { get; set; }
|
public List<long>? CategoryIds { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-5
@@ -56,17 +56,19 @@ public class GetCustomerProductsByFilterQueryHandler : IRequestHandler<GetCustom
|
|||||||
if (request.RemainingCount.HasValue)
|
if (request.RemainingCount.HasValue)
|
||||||
query = query.Where(x => x.RemainingCount == request.RemainingCount.Value);
|
query = query.Where(x => x.RemainingCount == request.RemainingCount.Value);
|
||||||
|
|
||||||
|
if (request.InStock == true)
|
||||||
|
query = query.Where(x => x.RemainingCount > 0);
|
||||||
|
else if (request.InStock == false)
|
||||||
|
query = query.Where(x => x.RemainingCount <= 0);
|
||||||
|
|
||||||
if (request.CategoryIds != null && request.CategoryIds.Any())
|
if (request.CategoryIds != null && request.CategoryIds.Any())
|
||||||
query = query.Where(x => x.ProductCategories.Any(pc => request.CategoryIds.Contains(pc.CategoryId)));
|
query = query.Where(x => x.ProductCategories.Any(pc => request.CategoryIds.Contains(pc.CategoryId)));
|
||||||
|
|
||||||
if (request.IsActive.HasValue)
|
if (request.IsActive.HasValue)
|
||||||
query = query.Where(x => x.IsDeleted != request.IsActive.Value);
|
query = query.Where(x => x.IsDeleted != request.IsActive.Value);
|
||||||
|
|
||||||
// Apply sorting
|
// موجودیدارها اول، سپس سورت درخواستی
|
||||||
if (!string.IsNullOrEmpty(request.SortBy))
|
query = query.ApplyOrderWithInStockPriority(request.SortBy, x => x.RemainingCount > 0);
|
||||||
query = query.ApplyOrder(request.SortBy);
|
|
||||||
else
|
|
||||||
query = query.OrderByDescending(x => x.Created);
|
|
||||||
|
|
||||||
// Pagination
|
// Pagination
|
||||||
var totalCount = await query.CountAsync(cancellationToken);
|
var totalCount = await query.CountAsync(cancellationToken);
|
||||||
|
|||||||
+4
@@ -26,4 +26,8 @@ public record GetAllTransactionsByFilterQuery : IRequest<GetAllTransactionsByFil
|
|||||||
public string? RefId { get; set; }
|
public string? RefId { get; set; }
|
||||||
//
|
//
|
||||||
public TransactionType? Type { 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;
|
namespace CMSMicroservice.Application.TransactionsCQ.Queries.GetAllTransactionsByFilter;
|
||||||
|
|
||||||
public class GetAllTransactionsByFilterQueryHandler : IRequestHandler<GetAllTransactionsByFilterQuery, GetAllTransactionsByFilterResponseDto>
|
public class GetAllTransactionsByFilterQueryHandler : IRequestHandler<GetAllTransactionsByFilterQuery, GetAllTransactionsByFilterResponseDto>
|
||||||
{
|
{
|
||||||
private readonly IApplicationDbContext _context;
|
private readonly IApplicationDbContext _context;
|
||||||
@@ -11,26 +12,27 @@ public class GetAllTransactionsByFilterQueryHandler : IRequestHandler<GetAllTran
|
|||||||
public async Task<GetAllTransactionsByFilterResponseDto> Handle(GetAllTransactionsByFilterQuery request, CancellationToken cancellationToken)
|
public async Task<GetAllTransactionsByFilterResponseDto> Handle(GetAllTransactionsByFilterQuery request, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var query = _context.Transactions
|
var query = _context.Transactions
|
||||||
.ApplyOrder(sortBy: request.SortBy)
|
|
||||||
.AsNoTracking()
|
.AsNoTracking()
|
||||||
.AsQueryable();
|
.ApplyTransactionFilter(request.Filter)
|
||||||
if (request.Filter is not null)
|
.ApplyOrder(sortBy: request.SortBy ?? "-Created");
|
||||||
{
|
|
||||||
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)
|
|
||||||
;
|
|
||||||
}
|
|
||||||
return new GetAllTransactionsByFilterResponseDto
|
return new GetAllTransactionsByFilterResponseDto
|
||||||
{
|
{
|
||||||
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
|
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
|
||||||
Models = await query.PaginatedListAsync(paginationState: request.PaginationState)
|
Models = await query
|
||||||
.ProjectToType<GetAllTransactionsByFilterResponseModel>().ToListAsync(cancellationToken)
|
.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 string? RefId { get; set; }
|
||||||
//
|
//
|
||||||
public TransactionType Type { 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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
+30
-5
@@ -17,7 +17,7 @@ public class GetAllUserByFilterQueryHandler : IRequestHandler<GetAllUserByFilter
|
|||||||
if (request.Filter is not null)
|
if (request.Filter is not null)
|
||||||
{
|
{
|
||||||
query = query
|
query = query
|
||||||
.Where(x => request.Filter.SearchText == null ||
|
.Where(x => request.Filter.SearchText == null ||
|
||||||
x.FirstName.Contains(request.Filter.SearchText) ||
|
x.FirstName.Contains(request.Filter.SearchText) ||
|
||||||
x.LastName.Contains(request.Filter.SearchText) ||
|
x.LastName.Contains(request.Filter.SearchText) ||
|
||||||
x.Mobile.Contains(request.Filter.SearchText) ||
|
x.Mobile.Contains(request.Filter.SearchText) ||
|
||||||
@@ -34,14 +34,39 @@ public class GetAllUserByFilterQueryHandler : IRequestHandler<GetAllUserByFilter
|
|||||||
.Where(x => request.Filter.SmsNotifications == null || x.SmsNotifications == request.Filter.SmsNotifications)
|
.Where(x => request.Filter.SmsNotifications == null || x.SmsNotifications == request.Filter.SmsNotifications)
|
||||||
.Where(x => request.Filter.EmailNotifications == null || x.EmailNotifications == request.Filter.EmailNotifications)
|
.Where(x => request.Filter.EmailNotifications == null || x.EmailNotifications == request.Filter.EmailNotifications)
|
||||||
.Where(x => request.Filter.PushNotifications == null || x.PushNotifications == request.Filter.PushNotifications)
|
.Where(x => request.Filter.PushNotifications == null || x.PushNotifications == request.Filter.PushNotifications)
|
||||||
.Where(x => request.Filter.BirthDate == null || x.BirthDate == request.Filter.BirthDate)
|
.Where(x => request.Filter.BirthDate == null || x.BirthDate == request.Filter.BirthDate);
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new GetAllUserByFilterResponseDto
|
return new GetAllUserByFilterResponseDto
|
||||||
{
|
{
|
||||||
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
|
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
|
||||||
Models = await query.PaginatedListAsync(paginationState: request.PaginationState)
|
Models = await query.PaginatedListAsync(paginationState: request.PaginationState)
|
||||||
.ProjectToType<GetAllUserByFilterResponseModel>().ToListAsync(cancellationToken)
|
.Select(x => new GetAllUserByFilterResponseModel
|
||||||
};
|
{
|
||||||
|
Id = x.Id,
|
||||||
|
FirstName = x.FirstName,
|
||||||
|
LastName = x.LastName,
|
||||||
|
Mobile = x.Mobile,
|
||||||
|
NationalCode = x.NationalCode,
|
||||||
|
AvatarPath = x.AvatarPath,
|
||||||
|
NetworkParentId = x.NetworkParentId,
|
||||||
|
ReferralCode = x.ReferralCode,
|
||||||
|
IsMobileVerified = x.IsMobileVerified,
|
||||||
|
MobileVerifiedAt = x.MobileVerifiedAt,
|
||||||
|
EmailNotifications = x.EmailNotifications,
|
||||||
|
SmsNotifications = x.SmsNotifications,
|
||||||
|
PushNotifications = x.PushNotifications,
|
||||||
|
BirthDate = x.BirthDate,
|
||||||
|
DefaultAddress = x.UserAddresses
|
||||||
|
.Where(a => a.IsDefault && !a.IsDeleted)
|
||||||
|
.Select(a => a.Address)
|
||||||
|
.FirstOrDefault() ?? string.Empty,
|
||||||
|
DefaultPostalCode = x.UserAddresses
|
||||||
|
.Where(a => a.IsDefault && !a.IsDeleted)
|
||||||
|
.Select(a => a.PostalCode)
|
||||||
|
.FirstOrDefault() ?? string.Empty
|
||||||
|
})
|
||||||
|
.ToListAsync(cancellationToken)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
@@ -36,4 +36,8 @@ public class GetAllUserByFilterResponseDto
|
|||||||
public bool PushNotifications { get; set; }
|
public bool PushNotifications { get; set; }
|
||||||
//تاریخ تولد
|
//تاریخ تولد
|
||||||
public DateTime? BirthDate { get; set; }
|
public DateTime? BirthDate { get; set; }
|
||||||
|
//آدرس پیشفرض
|
||||||
|
public string DefaultAddress { get; set; } = string.Empty;
|
||||||
|
//کدپستی پیشفرض
|
||||||
|
public string DefaultPostalCode { get; set; } = string.Empty;
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-1
@@ -1,3 +1,4 @@
|
|||||||
|
using CMSMicroservice.Application.Common;
|
||||||
using CMSMicroservice.Application.Common.Exceptions;
|
using CMSMicroservice.Application.Common.Exceptions;
|
||||||
using CMSMicroservice.Application.Common.Interfaces;
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
using CMSMicroservice.Domain.Entities;
|
using CMSMicroservice.Domain.Entities;
|
||||||
@@ -50,8 +51,10 @@ public class GetCustomerOrderQueryHandler : IRequestHandler<GetCustomerOrderQuer
|
|||||||
DeliveryStatus = order.DeliveryStatus,
|
DeliveryStatus = order.DeliveryStatus,
|
||||||
TrackingCode = order.TrackingCode ?? "",
|
TrackingCode = order.TrackingCode ?? "",
|
||||||
DeliveryDescription = order.DeliveryDescription ?? "",
|
DeliveryDescription = order.DeliveryDescription ?? "",
|
||||||
UserFullName = $"{order.User?.FirstName ?? ""} {order.User?.LastName ?? ""}".Trim(),
|
UserFullName = UserDisplayName.From(order.User),
|
||||||
UserNationalCode = order.User?.NationalCode ?? "",
|
UserNationalCode = order.User?.NationalCode ?? "",
|
||||||
|
PostalCode = order.UserAddress?.PostalCode ?? "",
|
||||||
|
UserMobile = order.User?.Mobile ?? "",
|
||||||
VatAmount = order.OrderVAT?.VATAmount ?? 0,
|
VatAmount = order.OrderVAT?.VATAmount ?? 0,
|
||||||
VatPercentage = order.OrderVAT != null ? (double)order.OrderVAT.VATRate * 100 : 0,
|
VatPercentage = order.OrderVAT != null ? (double)order.OrderVAT.VATRate * 100 : 0,
|
||||||
FactorDetails = order.FactorDetails?.Select(fd => new FactorDetailDto
|
FactorDetails = order.FactorDetails?.Select(fd => new FactorDetailDto
|
||||||
|
|||||||
+2
@@ -20,6 +20,8 @@ public class GetCustomerOrderResponseDto
|
|||||||
public string DeliveryDescription { get; set; }
|
public string DeliveryDescription { get; set; }
|
||||||
public string UserFullName { get; set; }
|
public string UserFullName { get; set; }
|
||||||
public string UserNationalCode { get; set; }
|
public string UserNationalCode { get; set; }
|
||||||
|
public string PostalCode { get; set; } = string.Empty;
|
||||||
|
public string UserMobile { get; set; } = string.Empty;
|
||||||
public long VatAmount { get; set; }
|
public long VatAmount { get; set; }
|
||||||
public double VatPercentage { get; set; }
|
public double VatPercentage { get; set; }
|
||||||
}
|
}
|
||||||
|
|||||||
+2
@@ -113,6 +113,7 @@ public class GetCustomerOrderHistoryQueryHandler : IRequestHandler<GetCustomerOr
|
|||||||
DeliveryStatus.Delivered => 4,
|
DeliveryStatus.Delivered => 4,
|
||||||
DeliveryStatus.Cancelled => 5,
|
DeliveryStatus.Cancelled => 5,
|
||||||
DeliveryStatus.Returned => 6,
|
DeliveryStatus.Returned => 6,
|
||||||
|
DeliveryStatus.ReadyForOfficePickup => 7,
|
||||||
_ => 0
|
_ => 0
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -127,6 +128,7 @@ public class GetCustomerOrderHistoryQueryHandler : IRequestHandler<GetCustomerOr
|
|||||||
DeliveryStatus.Delivered => "تحویل داده شد",
|
DeliveryStatus.Delivered => "تحویل داده شد",
|
||||||
DeliveryStatus.Cancelled => "لغو شده",
|
DeliveryStatus.Cancelled => "لغو شده",
|
||||||
DeliveryStatus.Returned => "مرجوع شده",
|
DeliveryStatus.Returned => "مرجوع شده",
|
||||||
|
DeliveryStatus.ReadyForOfficePickup => "آماده تحویل در دفتر",
|
||||||
_ => "نامشخص"
|
_ => "نامشخص"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
|
using CMSMicroservice.Application.Common;
|
||||||
using CMSMicroservice.Application.Common.Extensions;
|
using CMSMicroservice.Application.Common.Extensions;
|
||||||
using CMSMicroservice.Application.Common.Interfaces;
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
using CMSMicroservice.Application.Common.Models;
|
using CMSMicroservice.Application.Common.Models;
|
||||||
@@ -72,7 +73,7 @@ public class GetCustomerOrdersQueryHandler : IRequestHandler<GetCustomerOrdersQu
|
|||||||
DeliveryStatus = order.DeliveryStatus,
|
DeliveryStatus = order.DeliveryStatus,
|
||||||
TrackingCode = order.TrackingCode ?? "",
|
TrackingCode = order.TrackingCode ?? "",
|
||||||
DeliveryDescription = order.DeliveryDescription ?? "",
|
DeliveryDescription = order.DeliveryDescription ?? "",
|
||||||
UserFullName = $"{order.User?.FirstName ?? ""} {order.User?.LastName ?? ""}".Trim(),
|
UserFullName = UserDisplayName.From(order.User),
|
||||||
UserNationalCode = order.User?.NationalCode ?? "",
|
UserNationalCode = order.User?.NationalCode ?? "",
|
||||||
VatAmount = order.OrderVAT?.VATAmount ?? 0,
|
VatAmount = order.OrderVAT?.VATAmount ?? 0,
|
||||||
VatPercentage = order.OrderVAT != null ? (double)order.OrderVAT.VATRate * 100 : 0,
|
VatPercentage = order.OrderVAT != null ? (double)order.OrderVAT.VATRate * 100 : 0,
|
||||||
|
|||||||
+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;
|
||||||
|
}
|
||||||
|
}
|
||||||
+51
@@ -0,0 +1,51 @@
|
|||||||
|
using CMSMicroservice.Domain.Enums;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetCustomerPackagePurchaseRollup;
|
||||||
|
|
||||||
|
public record GetCustomerPackagePurchaseRollupQuery : IRequest<GetCustomerPackagePurchaseRollupResponseDto>
|
||||||
|
{
|
||||||
|
public PaginationState? PaginationState { get; init; }
|
||||||
|
public GetCustomerPackagePurchaseRollupFilter? Filter { get; init; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetCustomerPackagePurchaseRollupFilter
|
||||||
|
{
|
||||||
|
public long? UserId { get; set; }
|
||||||
|
public PackagePurchaseMethod? PurchaseMethod { get; set; }
|
||||||
|
public DateTime? PurchasedFrom { get; set; }
|
||||||
|
public DateTime? PurchasedTo { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetCustomerPackagePurchaseRollupResponseDto
|
||||||
|
{
|
||||||
|
public MetaData MetaData { get; set; } = new();
|
||||||
|
public List<CustomerPackagePurchaseRollupModel> Models { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CustomerPackagePurchaseRollupModel
|
||||||
|
{
|
||||||
|
public long UserId { get; set; }
|
||||||
|
public string UserName { get; set; } = string.Empty;
|
||||||
|
public string UserMobile { get; set; } = string.Empty;
|
||||||
|
|
||||||
|
public long FirstPackageId { get; set; }
|
||||||
|
public string FirstPackageName { get; set; } = string.Empty;
|
||||||
|
public long FirstAmount { get; set; }
|
||||||
|
public DateTime FirstPurchasedAt { get; set; }
|
||||||
|
|
||||||
|
public long LastPackageId { get; set; }
|
||||||
|
public string LastPackageName { get; set; } = string.Empty;
|
||||||
|
public long LastAmount { get; set; }
|
||||||
|
public DateTime LastPurchasedAt { get; set; }
|
||||||
|
public PackagePurchaseMethod LastPurchaseMethod { get; set; }
|
||||||
|
|
||||||
|
public int PurchaseCount { get; set; }
|
||||||
|
public long TotalAmount { get; set; }
|
||||||
|
|
||||||
|
public int DayaCount { get; set; }
|
||||||
|
public long DayaAmount { get; set; }
|
||||||
|
public int ManualCount { get; set; }
|
||||||
|
public long ManualAmount { get; set; }
|
||||||
|
public int GatewayCount { get; set; }
|
||||||
|
public long GatewayAmount { get; set; }
|
||||||
|
}
|
||||||
+136
@@ -0,0 +1,136 @@
|
|||||||
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
|
using CMSMicroservice.Application.Common.Models;
|
||||||
|
using CMSMicroservice.Domain.Enums;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetCustomerPackagePurchaseRollup;
|
||||||
|
|
||||||
|
public class GetCustomerPackagePurchaseRollupQueryHandler
|
||||||
|
: IRequestHandler<GetCustomerPackagePurchaseRollupQuery, GetCustomerPackagePurchaseRollupResponseDto>
|
||||||
|
{
|
||||||
|
private readonly IApplicationDbContext _context;
|
||||||
|
|
||||||
|
public GetCustomerPackagePurchaseRollupQueryHandler(IApplicationDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<GetCustomerPackagePurchaseRollupResponseDto> Handle(
|
||||||
|
GetCustomerPackagePurchaseRollupQuery request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var filter = request.Filter;
|
||||||
|
var pagination = request.PaginationState ?? new PaginationState { PageNumber = 1, PageSize = 20 };
|
||||||
|
if (pagination.PageNumber < 1) pagination.PageNumber = 1;
|
||||||
|
// PageSize == 0 → خروجی کامل (بدون صفحهبندی)، مثلاً Excel
|
||||||
|
var exportAll = pagination.PageSize == 0;
|
||||||
|
if (!exportAll && pagination.PageSize < 1) pagination.PageSize = 20;
|
||||||
|
|
||||||
|
// خرید معتبر: بدون تراکنش یا تراکنش موفق
|
||||||
|
var purchases = _context.UserPackagePurchases
|
||||||
|
.AsNoTracking()
|
||||||
|
.Include(x => x.User)
|
||||||
|
.Include(x => x.Package)
|
||||||
|
.Include(x => x.Transaction)
|
||||||
|
.Where(x => x.TransactionId == null
|
||||||
|
|| (x.Transaction != null && x.Transaction.PaymentStatus == PaymentStatus.Success));
|
||||||
|
|
||||||
|
if (filter?.UserId is > 0)
|
||||||
|
purchases = purchases.Where(x => x.UserId == filter.UserId.Value);
|
||||||
|
|
||||||
|
if (filter?.PurchaseMethod != null)
|
||||||
|
purchases = purchases.Where(x => x.PurchaseMethod == filter.PurchaseMethod.Value);
|
||||||
|
|
||||||
|
if (filter?.PurchasedFrom != null)
|
||||||
|
purchases = purchases.Where(x => x.PurchasedAt >= filter.PurchasedFrom.Value);
|
||||||
|
|
||||||
|
if (filter?.PurchasedTo != null)
|
||||||
|
purchases = purchases.Where(x => x.PurchasedAt <= filter.PurchasedTo.Value);
|
||||||
|
|
||||||
|
var rows = await purchases
|
||||||
|
.Select(x => new
|
||||||
|
{
|
||||||
|
x.UserId,
|
||||||
|
FirstName = x.User != null ? x.User.FirstName : null,
|
||||||
|
LastName = x.User != null ? x.User.LastName : null,
|
||||||
|
Mobile = x.User != null ? x.User.Mobile : null,
|
||||||
|
x.PackageId,
|
||||||
|
PackageName = x.Package != null ? x.Package.Title : null,
|
||||||
|
x.Amount,
|
||||||
|
x.PurchasedAt,
|
||||||
|
x.PurchaseMethod
|
||||||
|
})
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
var grouped = rows
|
||||||
|
.GroupBy(x => x.UserId)
|
||||||
|
.Select(g =>
|
||||||
|
{
|
||||||
|
var ordered = g.OrderBy(x => x.PurchasedAt).ThenBy(x => x.PackageId).ToList();
|
||||||
|
var first = ordered.First();
|
||||||
|
var last = ordered.Last();
|
||||||
|
var userName = string.Join(" ",
|
||||||
|
new[] { first.FirstName, first.LastName }.Where(s => !string.IsNullOrWhiteSpace(s))).Trim();
|
||||||
|
|
||||||
|
return new CustomerPackagePurchaseRollupModel
|
||||||
|
{
|
||||||
|
UserId = g.Key,
|
||||||
|
UserName = string.IsNullOrWhiteSpace(userName)
|
||||||
|
? (!string.IsNullOrWhiteSpace(first.Mobile) ? first.Mobile! : $"کاربر {g.Key}")
|
||||||
|
: userName,
|
||||||
|
UserMobile = first.Mobile ?? string.Empty,
|
||||||
|
|
||||||
|
FirstPackageId = first.PackageId,
|
||||||
|
FirstPackageName = first.PackageName ?? string.Empty,
|
||||||
|
FirstAmount = first.Amount,
|
||||||
|
FirstPurchasedAt = first.PurchasedAt,
|
||||||
|
|
||||||
|
LastPackageId = last.PackageId,
|
||||||
|
LastPackageName = last.PackageName ?? string.Empty,
|
||||||
|
LastAmount = last.Amount,
|
||||||
|
LastPurchasedAt = last.PurchasedAt,
|
||||||
|
LastPurchaseMethod = last.PurchaseMethod,
|
||||||
|
|
||||||
|
PurchaseCount = ordered.Count,
|
||||||
|
TotalAmount = ordered.Sum(x => x.Amount),
|
||||||
|
|
||||||
|
DayaCount = ordered.Count(x => x.PurchaseMethod == PackagePurchaseMethod.DayaLoan),
|
||||||
|
DayaAmount = ordered.Where(x => x.PurchaseMethod == PackagePurchaseMethod.DayaLoan).Sum(x => x.Amount),
|
||||||
|
ManualCount = ordered.Count(x => x.PurchaseMethod == PackagePurchaseMethod.Manual),
|
||||||
|
ManualAmount = ordered.Where(x => x.PurchaseMethod == PackagePurchaseMethod.Manual).Sum(x => x.Amount),
|
||||||
|
GatewayCount = ordered.Count(x => x.PurchaseMethod == PackagePurchaseMethod.DirectPurchase),
|
||||||
|
GatewayAmount = ordered.Where(x => x.PurchaseMethod == PackagePurchaseMethod.DirectPurchase).Sum(x => x.Amount)
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.OrderByDescending(x => x.LastPurchasedAt)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var totalCount = grouped.Count;
|
||||||
|
var pageNumber = exportAll ? 1 : pagination.PageNumber;
|
||||||
|
var pageSize = exportAll ? totalCount : pagination.PageSize;
|
||||||
|
var totalPage = exportAll || pageSize <= 0
|
||||||
|
? (totalCount > 0 ? 1 : 0)
|
||||||
|
: (int)Math.Ceiling(totalCount / (double)pageSize);
|
||||||
|
|
||||||
|
var pageModels = exportAll
|
||||||
|
? grouped
|
||||||
|
: grouped
|
||||||
|
.Skip((pageNumber - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
return new GetCustomerPackagePurchaseRollupResponseDto
|
||||||
|
{
|
||||||
|
MetaData = new MetaData
|
||||||
|
{
|
||||||
|
CurrentPage = pageNumber,
|
||||||
|
PageSize = pageSize,
|
||||||
|
TotalCount = totalCount,
|
||||||
|
TotalPage = totalPage,
|
||||||
|
HasPrevious = !exportAll && pageNumber > 1,
|
||||||
|
HasNext = !exportAll && pageNumber < totalPage
|
||||||
|
},
|
||||||
|
Models = pageModels
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
+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
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
@@ -20,6 +20,10 @@ public class GetAllUserWalletHistoryByFilterResponseDto
|
|||||||
public long CurrentNetworkBalance { get; set; }
|
public long CurrentNetworkBalance { get; set; }
|
||||||
//تغییر موجودی شبکه
|
//تغییر موجودی شبکه
|
||||||
public long ChangeNerworkValue { get; set; }
|
public long ChangeNerworkValue { get; set; }
|
||||||
|
//موجودی جاری اعتباری
|
||||||
|
public long CurrentDiscountBalance { get; set; }
|
||||||
|
//تغییر موجودی اعتباری
|
||||||
|
public long ChangeDiscountValue { get; set; }
|
||||||
//افزایشی؟
|
//افزایشی؟
|
||||||
public bool IsIncrease { get; set; }
|
public bool IsIncrease { get; set; }
|
||||||
//شناسه ارجاع
|
//شناسه ارجاع
|
||||||
|
|||||||
+4
@@ -13,6 +13,10 @@ public class GetUserWalletHistoryResponseDto
|
|||||||
public long CurrentNetworkBalance { get; set; }
|
public long CurrentNetworkBalance { get; set; }
|
||||||
//تغییر موجودی شبکه
|
//تغییر موجودی شبکه
|
||||||
public long ChangeNerworkValue { get; set; }
|
public long ChangeNerworkValue { get; set; }
|
||||||
|
//موجودی جاری اعتباری
|
||||||
|
public long CurrentDiscountBalance { get; set; }
|
||||||
|
//تغییر موجودی اعتباری
|
||||||
|
public long ChangeDiscountValue { get; set; }
|
||||||
//افزایشی؟
|
//افزایشی؟
|
||||||
public bool IsIncrease { get; set; }
|
public bool IsIncrease { get; set; }
|
||||||
//شناسه ارجاع
|
//شناسه ارجاع
|
||||||
|
|||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Application.WalletCQ.Commands.AdminManualCreditCharge;
|
||||||
|
|
||||||
|
public class AdminManualCreditChargeCommand : IRequest<AdminManualCreditChargeResult>
|
||||||
|
{
|
||||||
|
public long UserId { get; set; }
|
||||||
|
public long Amount { get; set; }
|
||||||
|
public string? Note { get; set; }
|
||||||
|
public string? PerformedByAdminId { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AdminManualCreditChargeResult
|
||||||
|
{
|
||||||
|
public bool Success { get; set; }
|
||||||
|
public string Message { get; set; } = string.Empty;
|
||||||
|
public long TransactionId { get; set; }
|
||||||
|
public long NewBalance { get; set; }
|
||||||
|
}
|
||||||
+105
@@ -0,0 +1,105 @@
|
|||||||
|
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.AdminManualCreditCharge;
|
||||||
|
|
||||||
|
public class AdminManualCreditChargeCommandHandler
|
||||||
|
: IRequestHandler<AdminManualCreditChargeCommand, AdminManualCreditChargeResult>
|
||||||
|
{
|
||||||
|
private readonly IApplicationDbContext _context;
|
||||||
|
private readonly ILogger<AdminManualCreditChargeCommandHandler> _logger;
|
||||||
|
private readonly IUserPaymentLock _paymentLock;
|
||||||
|
|
||||||
|
public AdminManualCreditChargeCommandHandler(
|
||||||
|
IApplicationDbContext context,
|
||||||
|
ILogger<AdminManualCreditChargeCommandHandler> logger,
|
||||||
|
IUserPaymentLock paymentLock)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
_logger = logger;
|
||||||
|
_paymentLock = paymentLock;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<AdminManualCreditChargeResult> Handle(
|
||||||
|
AdminManualCreditChargeCommand request,
|
||||||
|
CancellationToken cancellationToken) =>
|
||||||
|
_paymentLock.ExecuteAsync(
|
||||||
|
PaymentLockScopes.Initiate(request.UserId),
|
||||||
|
PaymentLockStrategy.FailFast,
|
||||||
|
ct => HandleCore(request, ct),
|
||||||
|
cancellationToken);
|
||||||
|
|
||||||
|
private async Task<AdminManualCreditChargeResult> HandleCore(
|
||||||
|
AdminManualCreditChargeCommand request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
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 == user.Id, cancellationToken)
|
||||||
|
?? throw new NotFoundException($"کیف پول کاربر با شناسه {request.UserId} یافت نشد");
|
||||||
|
|
||||||
|
var oldBalance = wallet.Balance;
|
||||||
|
wallet.Balance += request.Amount;
|
||||||
|
|
||||||
|
var refId = $"MANUAL-{Guid.NewGuid():N}";
|
||||||
|
var notePart = string.IsNullOrWhiteSpace(request.Note)
|
||||||
|
? string.Empty
|
||||||
|
: $" — {request.Note.Trim()}";
|
||||||
|
var adminPart = string.IsNullOrWhiteSpace(request.PerformedByAdminId)
|
||||||
|
? string.Empty
|
||||||
|
: $" (ادمین: {request.PerformedByAdminId})";
|
||||||
|
|
||||||
|
var transaction = new Transaction
|
||||||
|
{
|
||||||
|
Amount = request.Amount,
|
||||||
|
Description = $"شارژ دستی کیف پول اصلی - کاربر {user.Id}{notePart}{adminPart}",
|
||||||
|
PaymentStatus = PaymentStatus.Success,
|
||||||
|
PaymentDate = DateTime.Now,
|
||||||
|
RefId = refId,
|
||||||
|
Type = TransactionType.ManualCreditWalletCharge
|
||||||
|
};
|
||||||
|
|
||||||
|
_context.Transactions.Add(transaction);
|
||||||
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
_context.UserWalletHistories.Add(new 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);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Manual credit charge: UserId={UserId}, Amount={Amount}, OldBalance={Old}, NewBalance={New}, TxId={TxId}, Admin={Admin}",
|
||||||
|
user.Id,
|
||||||
|
request.Amount,
|
||||||
|
oldBalance,
|
||||||
|
wallet.Balance,
|
||||||
|
transaction.Id,
|
||||||
|
request.PerformedByAdminId);
|
||||||
|
|
||||||
|
return new AdminManualCreditChargeResult
|
||||||
|
{
|
||||||
|
Success = true,
|
||||||
|
Message = "شارژ دستی کیف پول اصلی با موفقیت انجام شد",
|
||||||
|
TransactionId = transaction.Id,
|
||||||
|
NewBalance = wallet.Balance
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
using CMSMicroservice.Domain.Common;
|
||||||
|
using FluentValidation;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Application.WalletCQ.Commands.AdminManualCreditCharge;
|
||||||
|
|
||||||
|
public class AdminManualCreditChargeCommandValidator : AbstractValidator<AdminManualCreditChargeCommand>
|
||||||
|
{
|
||||||
|
public AdminManualCreditChargeCommandValidator()
|
||||||
|
{
|
||||||
|
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 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; }
|
||||||
|
}
|
||||||
+130
@@ -0,0 +1,130 @@
|
|||||||
|
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
|
||||||
|
.Include(u => u.ClubMembership)
|
||||||
|
.FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken)
|
||||||
|
?? throw new NotFoundException(nameof(User), request.UserId);
|
||||||
|
|
||||||
|
if (user.ClubMembership?.IsActive != true)
|
||||||
|
{
|
||||||
|
throw new BadRequestException(
|
||||||
|
"برای شارژ کیف پول اصلی ابتدا باید پکیج را خریداری کرده و قرارداد باشگاه مشتریان را امضا کنید.");
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
+164
@@ -0,0 +1,164 @@
|
|||||||
|
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
|
||||||
|
.Include(u => u.ClubMembership)
|
||||||
|
.FirstOrDefaultAsync(u => u.Id == request.UserId, cancellationToken)
|
||||||
|
?? throw new NotFoundException(nameof(User), request.UserId);
|
||||||
|
|
||||||
|
if (user.ClubMembership?.IsActive != true)
|
||||||
|
{
|
||||||
|
throw new BadRequestException(
|
||||||
|
"برای شارژ کیف پول اصلی ابتدا باید پکیج را خریداری کرده و قرارداد باشگاه مشتریان را امضا کنید.");
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
using CMSMicroservice.Application.Common.Models;
|
||||||
|
using MediatR;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Application.WalletCQ.Queries.GetManualCreditCharges;
|
||||||
|
|
||||||
|
public class GetManualCreditChargesQuery : IRequest<GetManualCreditChargesResponseDto>
|
||||||
|
{
|
||||||
|
public PaginationState? PaginationState { get; set; }
|
||||||
|
public string? SortBy { get; set; }
|
||||||
|
public GetManualCreditChargesFilter? Filter { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetManualCreditChargesFilter
|
||||||
|
{
|
||||||
|
public long? UserId { get; set; }
|
||||||
|
public long? TransactionId { get; set; }
|
||||||
|
public string? RefId { get; set; }
|
||||||
|
public DateTime? CreatedFrom { get; set; }
|
||||||
|
public DateTime? CreatedTo { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class GetManualCreditChargesResponseDto
|
||||||
|
{
|
||||||
|
public MetaData MetaData { get; set; } = new();
|
||||||
|
public List<ManualCreditChargeModelDto> Models { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ManualCreditChargeModelDto
|
||||||
|
{
|
||||||
|
public long TransactionId { get; set; }
|
||||||
|
public long UserId { get; set; }
|
||||||
|
public string UserName { get; set; } = string.Empty;
|
||||||
|
public long Amount { get; set; }
|
||||||
|
public string Description { get; set; } = string.Empty;
|
||||||
|
public string? RefId { get; set; }
|
||||||
|
public long NewBalance { get; set; }
|
||||||
|
public DateTime Created { get; set; }
|
||||||
|
public DateTime? PaymentDate { get; set; }
|
||||||
|
}
|
||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
using CMSMicroservice.Application.Common.Extensions;
|
||||||
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
|
using CMSMicroservice.Domain.Enums;
|
||||||
|
using MediatR;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace CMSMicroservice.Application.WalletCQ.Queries.GetManualCreditCharges;
|
||||||
|
|
||||||
|
public class GetManualCreditChargesQueryHandler
|
||||||
|
: IRequestHandler<GetManualCreditChargesQuery, GetManualCreditChargesResponseDto>
|
||||||
|
{
|
||||||
|
private readonly IApplicationDbContext _context;
|
||||||
|
|
||||||
|
public GetManualCreditChargesQueryHandler(IApplicationDbContext context)
|
||||||
|
{
|
||||||
|
_context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task<GetManualCreditChargesResponseDto> Handle(
|
||||||
|
GetManualCreditChargesQuery request,
|
||||||
|
CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
var filter = request.Filter;
|
||||||
|
|
||||||
|
var query =
|
||||||
|
from t in _context.Transactions.AsNoTracking()
|
||||||
|
where t.Type == TransactionType.ManualCreditWalletCharge
|
||||||
|
join h in _context.UserWalletHistories.AsNoTracking() on t.Id equals h.RefrenceId
|
||||||
|
join w in _context.UserWallets.AsNoTracking() on h.WalletId equals w.Id
|
||||||
|
join u in _context.Users.AsNoTracking() on w.UserId equals u.Id
|
||||||
|
select new ManualCreditChargeModelDto
|
||||||
|
{
|
||||||
|
TransactionId = t.Id,
|
||||||
|
UserId = w.UserId,
|
||||||
|
UserName = ((u.FirstName ?? "") + " " + (u.LastName ?? "")).Trim(),
|
||||||
|
Amount = t.Amount,
|
||||||
|
Description = t.Description ?? string.Empty,
|
||||||
|
RefId = t.RefId,
|
||||||
|
NewBalance = h.CurrentBalance,
|
||||||
|
Created = t.Created,
|
||||||
|
PaymentDate = t.PaymentDate
|
||||||
|
};
|
||||||
|
|
||||||
|
if (filter?.UserId is long userId)
|
||||||
|
query = query.Where(x => x.UserId == userId);
|
||||||
|
|
||||||
|
if (filter?.TransactionId is long txId)
|
||||||
|
query = query.Where(x => x.TransactionId == txId);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(filter?.RefId))
|
||||||
|
query = query.Where(x => x.RefId != null && x.RefId.Contains(filter.RefId));
|
||||||
|
|
||||||
|
if (filter?.CreatedFrom is DateTime from)
|
||||||
|
query = query.Where(x => x.Created >= from);
|
||||||
|
|
||||||
|
if (filter?.CreatedTo is DateTime to)
|
||||||
|
query = query.Where(x => x.Created <= to);
|
||||||
|
|
||||||
|
query = query.OrderByDescending(x => x.Created);
|
||||||
|
|
||||||
|
return new GetManualCreditChargesResponseDto
|
||||||
|
{
|
||||||
|
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
|
||||||
|
Models = await query
|
||||||
|
.PaginatedListAsync(paginationState: request.PaginationState)
|
||||||
|
.ToListAsync(cancellationToken)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,5 +15,7 @@ public enum DeliveryStatus
|
|||||||
Returned = 4,
|
Returned = 4,
|
||||||
// لغو شده
|
// لغو شده
|
||||||
Cancelled = 5,
|
Cancelled = 5,
|
||||||
|
// آماده تحویل حضوری در دفتر
|
||||||
|
ReadyForOfficePickup = 6,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,5 +18,10 @@ public enum PackagePurchaseMethod
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// از طریق پرداخت مستقیم درگاه بانکی
|
/// از طریق پرداخت مستقیم درگاه بانکی
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DirectPurchase = 2
|
DirectPurchase = 2,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ثبت دستی توسط ادمین
|
||||||
|
/// </summary>
|
||||||
|
Manual = 3
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,4 +36,14 @@ public enum TransactionType
|
|||||||
/// بونوس داخلی کیفپول جادویی (مبلغ × 1.5)
|
/// بونوس داخلی کیفپول جادویی (مبلغ × 1.5)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MagicWalletBonus = 15,
|
MagicWalletBonus = 15,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شارژ کیف پول اصلی از درگاه
|
||||||
|
/// </summary>
|
||||||
|
CreditWalletCharge = 16,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// شارژ دستی کیف پول اصلی توسط ادمین
|
||||||
|
/// </summary>
|
||||||
|
ManualCreditWalletCharge = 17,
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using CMSMicroservice.Application.PackageCQ.Commands.VerifyUserPackagePurchasePa
|
|||||||
using CMSMicroservice.Application.Common.Interfaces;
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
using CMSMicroservice.Application.DiscountShopCQ.Commands.CompleteOrderPayment;
|
using CMSMicroservice.Application.DiscountShopCQ.Commands.CompleteOrderPayment;
|
||||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyDiscountWalletCharge;
|
using CMSMicroservice.Application.WalletCQ.Commands.VerifyDiscountWalletCharge;
|
||||||
|
using CMSMicroservice.Application.WalletCQ.Commands.VerifyCreditWalletCharge;
|
||||||
using CMSMicroservice.Application.WalletCQ.Commands.VerifyMagicWalletCharge;
|
using CMSMicroservice.Application.WalletCQ.Commands.VerifyMagicWalletCharge;
|
||||||
using CMSMicroservice.Domain.Entities;
|
using CMSMicroservice.Domain.Entities;
|
||||||
using CMSMicroservice.Domain.Entities.Payment;
|
using CMSMicroservice.Domain.Entities.Payment;
|
||||||
@@ -174,6 +175,19 @@ public class ZarinpalReconciliationJob
|
|||||||
}, ct);
|
}, ct);
|
||||||
break;
|
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":
|
case "discount-order":
|
||||||
await ReconcileDiscountOrderAsync(paymentTx, ct);
|
await ReconcileDiscountOrderAsync(paymentTx, ct);
|
||||||
break;
|
break;
|
||||||
@@ -194,6 +208,8 @@ public class ZarinpalReconciliationJob
|
|||||||
return "magic-wallet";
|
return "magic-wallet";
|
||||||
if (callbackUrl.Contains("type=discount-wallet", StringComparison.OrdinalIgnoreCase))
|
if (callbackUrl.Contains("type=discount-wallet", StringComparison.OrdinalIgnoreCase))
|
||||||
return "discount-wallet";
|
return "discount-wallet";
|
||||||
|
if (callbackUrl.Contains("type=credit-wallet", StringComparison.OrdinalIgnoreCase))
|
||||||
|
return "credit-wallet";
|
||||||
if (callbackUrl.Contains("type=discount-order", StringComparison.OrdinalIgnoreCase))
|
if (callbackUrl.Contains("type=discount-order", StringComparison.OrdinalIgnoreCase))
|
||||||
return "discount-order";
|
return "discount-order";
|
||||||
// Package callbacks have orderId= but no type= parameter
|
// Package callbacks have orderId= but no type= parameter
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using CMSMicroservice.Application.Common.Interfaces;
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
using CMSMicroservice.Domain.Entities;
|
using CMSMicroservice.Domain.Entities;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
@@ -13,10 +14,12 @@ namespace CMSMicroservice.Infrastructure.Services;
|
|||||||
public class GenerateJwtTokenService : IGenerateJwtToken
|
public class GenerateJwtTokenService : IGenerateJwtToken
|
||||||
{
|
{
|
||||||
private readonly IConfiguration _configuration;
|
private readonly IConfiguration _configuration;
|
||||||
|
private readonly IApplicationDbContext _context;
|
||||||
|
|
||||||
public GenerateJwtTokenService(IConfiguration configuration)
|
public GenerateJwtTokenService(IConfiguration configuration, IApplicationDbContext context)
|
||||||
{
|
{
|
||||||
_configuration = configuration;
|
_configuration = configuration;
|
||||||
|
_context = context;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string> GenerateJwtToken(User user, int? expiryDays = null)
|
public async Task<string> GenerateJwtToken(User user, int? expiryDays = null)
|
||||||
@@ -58,6 +61,10 @@ public class GenerateJwtTokenService : IGenerateJwtToken
|
|||||||
claims.Add(new Claim("HasPurchasedPackage",
|
claims.Add(new Claim("HasPurchasedPackage",
|
||||||
(user.PackagePurchaseMethod != PackagePurchaseMethod.None).ToString()));
|
(user.PackagePurchaseMethod != PackagePurchaseMethod.None).ToString()));
|
||||||
|
|
||||||
|
var hasAddress = await _context.UserAddresses
|
||||||
|
.AnyAsync(a => a.UserId == user.Id && !a.IsDeleted);
|
||||||
|
claims.Add(new Claim("HasAddress", hasAddress.ToString()));
|
||||||
|
|
||||||
if (user.UserRoles != null && user.UserRoles.Any())
|
if (user.UserRoles != null && user.UserRoles.Any())
|
||||||
{
|
{
|
||||||
foreach (var userRole in user.UserRoles)
|
foreach (var userRole in user.UserRoles)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<TargetFramework>net9.0</TargetFramework>
|
<TargetFramework>net9.0</TargetFramework>
|
||||||
<ImplicitUsings>enable</ImplicitUsings>
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
<Version>0.0.199</Version>
|
<Version>0.0.209</Version>
|
||||||
<DebugType>None</DebugType>
|
<DebugType>None</DebugType>
|
||||||
<DebugSymbols>False</DebugSymbols>
|
<DebugSymbols>False</DebugSymbols>
|
||||||
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>False</GeneratePackageOnBuild>
|
||||||
@@ -74,6 +74,11 @@
|
|||||||
<Protobuf Include="Protos\sitepagesettings.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
<Protobuf Include="Protos\sitepagesettings.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
||||||
<!-- Image Resolver Service -->
|
<!-- Image Resolver Service -->
|
||||||
<Protobuf Include="Protos\imageresolver.proto" ProtoRoot="Protos\" GrpcServices="Both" />
|
<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>
|
</ItemGroup>
|
||||||
|
|
||||||
<Target Name="PushToFoursatNuget" AfterTargets="Pack" Condition="'$(CI)' != 'true'">
|
<Target Name="PushToFoursatNuget" AfterTargets="Pack" Condition="'$(CI)' != 'true'">
|
||||||
|
|||||||
@@ -164,11 +164,19 @@ message ClubMembershipModel
|
|||||||
|
|
||||||
// GetHistory Query
|
// GetHistory Query
|
||||||
message GetClubMembershipHistoryRequest
|
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 user_id = 1;
|
||||||
google.protobuf.Int64Value package_id = 2;
|
google.protobuf.Int64Value club_membership_id = 2;
|
||||||
int32 page_index = 3;
|
google.protobuf.Int32Value action = 3;
|
||||||
int32 page_size = 4;
|
google.protobuf.Timestamp created_from = 4;
|
||||||
|
google.protobuf.Timestamp created_to = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GetClubMembershipHistoryResponse
|
message GetClubMembershipHistoryResponse
|
||||||
@@ -182,16 +190,15 @@ message ClubMembershipHistoryModel
|
|||||||
int64 id = 1;
|
int64 id = 1;
|
||||||
int64 club_membership_id = 2;
|
int64 club_membership_id = 2;
|
||||||
int64 user_id = 3;
|
int64 user_id = 3;
|
||||||
google.protobuf.Int64Value old_package_id = 4;
|
string user_name = 4;
|
||||||
google.protobuf.Int64Value new_package_id = 5;
|
bool old_is_active = 5;
|
||||||
google.protobuf.Timestamp old_activated_at = 6;
|
bool new_is_active = 6;
|
||||||
google.protobuf.Timestamp new_activated_at = 7;
|
google.protobuf.Int64Value old_initial_contribution = 7;
|
||||||
google.protobuf.Timestamp old_expires_at = 8;
|
google.protobuf.Int64Value new_initial_contribution = 8;
|
||||||
google.protobuf.Timestamp new_expires_at = 9;
|
int32 action = 9; // ClubMembershipAction enum
|
||||||
int32 action = 10; // ClubMembershipAction enum
|
string performed_by = 10;
|
||||||
string performed_by = 11;
|
string reason = 11;
|
||||||
string reason = 12;
|
google.protobuf.Timestamp created_at = 12;
|
||||||
google.protobuf.Timestamp created = 13;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetClubStatistics Query
|
// 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;
|
||||||
|
}
|
||||||
@@ -118,6 +118,8 @@ enum DeliveryStatus
|
|||||||
DELIVERY_SHIPPED = 2;
|
DELIVERY_SHIPPED = 2;
|
||||||
DELIVERY_DELIVERED = 3;
|
DELIVERY_DELIVERED = 3;
|
||||||
DELIVERY_CANCELLED = 4;
|
DELIVERY_CANCELLED = 4;
|
||||||
|
DELIVERY_READY_FOR_OFFICE = 5;
|
||||||
|
DELIVERY_RETURNED = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get Order By Id
|
// Get Order By Id
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -229,6 +229,7 @@ message GetAllProductsByFilterFilter
|
|||||||
google.protobuf.Int32Value remaining_count = 13;
|
google.protobuf.Int32Value remaining_count = 13;
|
||||||
google.protobuf.Int64Value category_id = 14;
|
google.protobuf.Int64Value category_id = 14;
|
||||||
google.protobuf.BoolValue is_active = 15;
|
google.protobuf.BoolValue is_active = 15;
|
||||||
|
google.protobuf.BoolValue in_stock = 16;
|
||||||
}
|
}
|
||||||
message GetAllProductsByFilterResponse
|
message GetAllProductsByFilterResponse
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -102,6 +102,10 @@ enum DeliveryStatus
|
|||||||
DeliveryStatus_Delivered = 3;
|
DeliveryStatus_Delivered = 3;
|
||||||
// مرجوع شده
|
// مرجوع شده
|
||||||
DeliveryStatus_Returned = 4;
|
DeliveryStatus_Returned = 4;
|
||||||
|
// لغو شده
|
||||||
|
DeliveryStatus_Cancelled = 5;
|
||||||
|
// آماده تحویل حضوری در دفتر
|
||||||
|
DeliveryStatus_ReadyForOfficePickup = 6;
|
||||||
}
|
}
|
||||||
enum TransactionType
|
enum TransactionType
|
||||||
{
|
{
|
||||||
@@ -109,6 +113,14 @@ enum TransactionType
|
|||||||
DepositIpg = 1;
|
DepositIpg = 1;
|
||||||
DepositExternal1 = 2;
|
DepositExternal1 = 2;
|
||||||
Withdraw = 3;
|
Withdraw = 3;
|
||||||
|
NetworkCommission = 10;
|
||||||
|
ClubActivation = 11;
|
||||||
|
DiscountWalletCharge = 12;
|
||||||
|
DiscountShopPurchase = 13;
|
||||||
|
MagicWalletDeposit = 14;
|
||||||
|
MagicWalletBonus = 15;
|
||||||
|
CreditWalletCharge = 16;
|
||||||
|
ManualCreditWalletCharge = 17;
|
||||||
}
|
}
|
||||||
enum ContractType
|
enum ContractType
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -43,6 +43,11 @@ service TransactionsContract
|
|||||||
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
rpc GetTransactionSummary(GetTransactionSummaryRequest) returns (GetTransactionSummaryResponse){
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/GetTransactionSummary"
|
||||||
|
};
|
||||||
|
};
|
||||||
rpc VerifyTransaction(VerifyTransactionRequest) returns (VerifyTransactionResponse){
|
rpc VerifyTransaction(VerifyTransactionRequest) returns (VerifyTransactionResponse){
|
||||||
option (google.api.http) = {
|
option (google.api.http) = {
|
||||||
post: "/VerifyTransaction"
|
post: "/VerifyTransaction"
|
||||||
@@ -161,6 +166,10 @@ message GetAllTransactionsByFilterFilter
|
|||||||
{
|
{
|
||||||
messages.TransactionType type = 7;
|
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
|
message GetAllTransactionsByFilterResponse
|
||||||
{
|
{
|
||||||
@@ -182,6 +191,21 @@ message GetAllTransactionsByFilterResponseModel
|
|||||||
{
|
{
|
||||||
messages.TransactionType type = 7;
|
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
|
// VerifyTransaction Messages
|
||||||
|
|||||||
@@ -238,6 +238,8 @@ message GetAllUserByFilterResponseModel
|
|||||||
bool sms_notifications = 12;
|
bool sms_notifications = 12;
|
||||||
bool push_notifications = 13;
|
bool push_notifications = 13;
|
||||||
google.protobuf.Timestamp birth_date = 14;
|
google.protobuf.Timestamp birth_date = 14;
|
||||||
|
string default_address = 15;
|
||||||
|
string default_postal_code = 16;
|
||||||
}
|
}
|
||||||
message GetJwtTokenRequest
|
message GetJwtTokenRequest
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -220,6 +220,9 @@ message GetUserOrderResponse
|
|||||||
google.protobuf.StringValue user_national_code = 16;
|
google.protobuf.StringValue user_national_code = 16;
|
||||||
// اطلاعات مالیات بر ارزش افزوده
|
// اطلاعات مالیات بر ارزش افزوده
|
||||||
OrderVATInfo vat_info = 17;
|
OrderVATInfo vat_info = 17;
|
||||||
|
// اطلاعات پستی برای برچسب کارتن
|
||||||
|
google.protobuf.StringValue postal_code = 18;
|
||||||
|
google.protobuf.StringValue user_mobile = 19;
|
||||||
}
|
}
|
||||||
|
|
||||||
// اطلاعات مالیات بر ارزش افزوده
|
// اطلاعات مالیات بر ارزش افزوده
|
||||||
|
|||||||
@@ -0,0 +1,128 @@
|
|||||||
|
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"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
rpc GetCustomerPackagePurchaseRollup(GetCustomerPackagePurchaseRollupRequest) returns (GetCustomerPackagePurchaseRollupResponse){
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/UserPackagePurchase/GetCustomerRollup"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetCustomerPackagePurchaseRollupRequest
|
||||||
|
{
|
||||||
|
messages.PaginationState pagination_state = 1;
|
||||||
|
GetCustomerPackagePurchaseRollupFilter filter = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetCustomerPackagePurchaseRollupFilter
|
||||||
|
{
|
||||||
|
google.protobuf.Int64Value user_id = 1;
|
||||||
|
google.protobuf.Int32Value purchase_method = 2;
|
||||||
|
google.protobuf.Timestamp purchased_from = 3;
|
||||||
|
google.protobuf.Timestamp purchased_to = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetCustomerPackagePurchaseRollupResponse
|
||||||
|
{
|
||||||
|
messages.MetaData meta_data = 1;
|
||||||
|
repeated CustomerPackagePurchaseRollupModel models = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message CustomerPackagePurchaseRollupModel
|
||||||
|
{
|
||||||
|
int64 user_id = 1;
|
||||||
|
string user_name = 2;
|
||||||
|
string user_mobile = 3;
|
||||||
|
|
||||||
|
int64 first_package_id = 4;
|
||||||
|
string first_package_name = 5;
|
||||||
|
int64 first_amount = 6;
|
||||||
|
google.protobuf.Timestamp first_purchased_at = 7;
|
||||||
|
|
||||||
|
int64 last_package_id = 8;
|
||||||
|
string last_package_name = 9;
|
||||||
|
int64 last_amount = 10;
|
||||||
|
google.protobuf.Timestamp last_purchased_at = 11;
|
||||||
|
int32 last_purchase_method = 12;
|
||||||
|
|
||||||
|
int32 purchase_count = 13;
|
||||||
|
int64 total_amount = 14;
|
||||||
|
|
||||||
|
int32 daya_count = 15;
|
||||||
|
int64 daya_amount = 16;
|
||||||
|
int32 manual_count = 17;
|
||||||
|
int64 manual_amount = 18;
|
||||||
|
int32 gateway_count = 19;
|
||||||
|
int64 gateway_amount = 20;
|
||||||
|
}
|
||||||
@@ -110,6 +110,35 @@ service UserWalletContract
|
|||||||
body: "*"
|
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: "*"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// ============= Admin Manual Credit Charge =============
|
||||||
|
|
||||||
|
rpc AdminManualCreditCharge(AdminManualCreditChargeRequest) returns (AdminManualCreditChargeResponse){
|
||||||
|
option (google.api.http) = {
|
||||||
|
post: "/Admin/ManualCreditCharge"
|
||||||
|
body: "*"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
rpc GetManualCreditCharges(GetManualCreditChargesRequest) returns (GetManualCreditChargesResponse){
|
||||||
|
option (google.api.http) = {
|
||||||
|
get: "/Admin/GetManualCreditCharges"
|
||||||
|
};
|
||||||
|
};
|
||||||
}
|
}
|
||||||
message CreateNewUserWalletRequest
|
message CreateNewUserWalletRequest
|
||||||
{
|
{
|
||||||
@@ -283,6 +312,20 @@ message InitiateDiscountChargeResponse
|
|||||||
string error_message = 3;
|
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 =============
|
// ============= Wallet Verify Messages =============
|
||||||
|
|
||||||
message VerifyWalletChargeRequest
|
message VerifyWalletChargeRequest
|
||||||
@@ -295,4 +338,56 @@ message VerifyWalletChargeResponse
|
|||||||
{
|
{
|
||||||
bool success = 1;
|
bool success = 1;
|
||||||
string message = 2;
|
string message = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============= Admin Manual Credit Charge Messages =============
|
||||||
|
|
||||||
|
message AdminManualCreditChargeRequest
|
||||||
|
{
|
||||||
|
int64 user_id = 1;
|
||||||
|
int64 amount = 2; // تومان
|
||||||
|
google.protobuf.StringValue note = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message AdminManualCreditChargeResponse
|
||||||
|
{
|
||||||
|
bool success = 1;
|
||||||
|
string message = 2;
|
||||||
|
int64 transaction_id = 3;
|
||||||
|
int64 new_balance = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetManualCreditChargesRequest
|
||||||
|
{
|
||||||
|
messages.PaginationState pagination_state = 1;
|
||||||
|
google.protobuf.StringValue sort_by = 2;
|
||||||
|
GetManualCreditChargesFilter filter = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetManualCreditChargesFilter
|
||||||
|
{
|
||||||
|
google.protobuf.Int64Value user_id = 1;
|
||||||
|
google.protobuf.Int64Value transaction_id = 2;
|
||||||
|
google.protobuf.StringValue ref_id = 3;
|
||||||
|
google.protobuf.Timestamp created_from = 4;
|
||||||
|
google.protobuf.Timestamp created_to = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
message GetManualCreditChargesResponse
|
||||||
|
{
|
||||||
|
messages.MetaData meta_data = 1;
|
||||||
|
repeated ManualCreditChargeModel models = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
message ManualCreditChargeModel
|
||||||
|
{
|
||||||
|
int64 transaction_id = 1;
|
||||||
|
int64 user_id = 2;
|
||||||
|
string user_name = 3;
|
||||||
|
int64 amount = 4;
|
||||||
|
string description = 5;
|
||||||
|
string ref_id = 6;
|
||||||
|
int64 new_balance = 7;
|
||||||
|
google.protobuf.Timestamp created = 8;
|
||||||
|
google.protobuf.Timestamp payment_date = 9;
|
||||||
}
|
}
|
||||||
@@ -88,6 +88,8 @@ message GetUserWalletHistoryResponse
|
|||||||
bool is_increase = 7;
|
bool is_increase = 7;
|
||||||
google.protobuf.Int64Value refrence_id = 8;
|
google.protobuf.Int64Value refrence_id = 8;
|
||||||
google.protobuf.Timestamp created_at = 9;
|
google.protobuf.Timestamp created_at = 9;
|
||||||
|
int64 current_discount_balance = 10;
|
||||||
|
int64 change_discount_value = 11;
|
||||||
}
|
}
|
||||||
message GetAllUserWalletHistoryByFilterRequest
|
message GetAllUserWalletHistoryByFilterRequest
|
||||||
{
|
{
|
||||||
@@ -121,4 +123,6 @@ message GetAllUserWalletHistoryByFilterResponseModel
|
|||||||
bool is_increase = 7;
|
bool is_increase = 7;
|
||||||
google.protobuf.Int64Value refrence_id = 8;
|
google.protobuf.Int64Value refrence_id = 8;
|
||||||
google.protobuf.Timestamp created_at = 9;
|
google.protobuf.Timestamp created_at = 9;
|
||||||
|
int64 current_discount_balance = 10;
|
||||||
|
int64 change_discount_value = 11;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.GetAllClubMemberships;
|
||||||
using CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembership;
|
using CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubMembership;
|
||||||
using CMSMicroservice.Application.ClubMembershipCQ.Queries.GetClubStatistics;
|
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 Google.Protobuf.WellKnownTypes;
|
||||||
using Mapster;
|
using Mapster;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -17,15 +19,15 @@ public class ClubMembershipProfile : IRegister
|
|||||||
// =====================
|
// =====================
|
||||||
|
|
||||||
// GetClubMembershipRequest -> GetClubMembershipQuery
|
// GetClubMembershipRequest -> GetClubMembershipQuery
|
||||||
config.NewConfig<GetClubMembershipRequest, GetClubMembershipQuery>()
|
config.NewConfig<ProtoClub.GetClubMembershipRequest, GetClubMembershipQuery>()
|
||||||
.MapWith(src => new GetClubMembershipQuery
|
.MapWith(src => new GetClubMembershipQuery
|
||||||
{
|
{
|
||||||
UserId = src.UserId
|
UserId = src.UserId
|
||||||
});
|
});
|
||||||
|
|
||||||
// ClubMembershipDto -> GetClubMembershipResponse
|
// ClubMembershipDto -> GetClubMembershipResponse
|
||||||
config.NewConfig<ClubMembershipDto, GetClubMembershipResponse>()
|
config.NewConfig<ClubMembershipDto, ProtoClub.GetClubMembershipResponse>()
|
||||||
.MapWith(src => new GetClubMembershipResponse
|
.MapWith(src => new ProtoClub.GetClubMembershipResponse
|
||||||
{
|
{
|
||||||
Id = src.Id,
|
Id = src.Id,
|
||||||
UserId = src.UserId,
|
UserId = src.UserId,
|
||||||
@@ -48,7 +50,7 @@ public class ClubMembershipProfile : IRegister
|
|||||||
// =====================
|
// =====================
|
||||||
|
|
||||||
// GetAllClubMembershipsRequest -> GetAllClubMembershipsQuery
|
// GetAllClubMembershipsRequest -> GetAllClubMembershipsQuery
|
||||||
config.NewConfig<GetAllClubMembershipsRequest, GetAllClubMembershipsQuery>()
|
config.NewConfig<ProtoClub.GetAllClubMembershipsRequest, GetAllClubMembershipsQuery>()
|
||||||
.MapWith(src => new GetAllClubMembershipsQuery
|
.MapWith(src => new GetAllClubMembershipsQuery
|
||||||
{
|
{
|
||||||
PaginationState = new Application.Common.Models.PaginationState
|
PaginationState = new Application.Common.Models.PaginationState
|
||||||
@@ -64,8 +66,8 @@ public class ClubMembershipProfile : IRegister
|
|||||||
});
|
});
|
||||||
|
|
||||||
// GetAllClubMembershipsResponseDto -> GetAllClubMembershipsResponse
|
// GetAllClubMembershipsResponseDto -> GetAllClubMembershipsResponse
|
||||||
config.NewConfig<GetAllClubMembershipsResponseDto, GetAllClubMembershipsResponse>()
|
config.NewConfig<GetAllClubMembershipsResponseDto, ProtoClub.GetAllClubMembershipsResponse>()
|
||||||
.MapWith(src => new GetAllClubMembershipsResponse
|
.MapWith(src => new ProtoClub.GetAllClubMembershipsResponse
|
||||||
{
|
{
|
||||||
MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
|
MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
|
||||||
{
|
{
|
||||||
@@ -82,12 +84,12 @@ public class ClubMembershipProfile : IRegister
|
|||||||
// =====================
|
// =====================
|
||||||
|
|
||||||
// GetClubStatisticsRequest -> GetClubStatisticsQuery
|
// GetClubStatisticsRequest -> GetClubStatisticsQuery
|
||||||
config.NewConfig<GetClubStatisticsRequest, GetClubStatisticsQuery>()
|
config.NewConfig<ProtoClub.GetClubStatisticsRequest, GetClubStatisticsQuery>()
|
||||||
.MapWith(src => new GetClubStatisticsQuery());
|
.MapWith(src => new GetClubStatisticsQuery());
|
||||||
|
|
||||||
// GetClubStatisticsResponseDto -> GetClubStatisticsResponse
|
// GetClubStatisticsResponseDto -> GetClubStatisticsResponse
|
||||||
config.NewConfig<GetClubStatisticsResponseDto, GetClubStatisticsResponse>()
|
config.NewConfig<GetClubStatisticsResponseDto, ProtoClub.GetClubStatisticsResponse>()
|
||||||
.MapWith(src => new GetClubStatisticsResponse
|
.MapWith(src => new ProtoClub.GetClubStatisticsResponse
|
||||||
{
|
{
|
||||||
TotalMembers = src.TotalMembers,
|
TotalMembers = src.TotalMembers,
|
||||||
ActiveMembers = src.ActiveMembers,
|
ActiveMembers = src.ActiveMembers,
|
||||||
@@ -97,14 +99,14 @@ public class ClubMembershipProfile : IRegister
|
|||||||
TotalRevenue = src.TotalRevenue,
|
TotalRevenue = src.TotalRevenue,
|
||||||
AverageMembershipDurationDays = src.AverageMembershipDurationDays,
|
AverageMembershipDurationDays = src.AverageMembershipDurationDays,
|
||||||
ExpiringSoonCount = src.ExpiringSoonCount,
|
ExpiringSoonCount = src.ExpiringSoonCount,
|
||||||
PackageDistribution = { src.PackageDistribution.Select(p => new PackageLevelDistribution
|
PackageDistribution = { src.PackageDistribution.Select(p => new ProtoClub.PackageLevelDistribution
|
||||||
{
|
{
|
||||||
PackageId = p.PackageId,
|
PackageId = p.PackageId,
|
||||||
PackageName = p.PackageName ?? string.Empty,
|
PackageName = p.PackageName ?? string.Empty,
|
||||||
MemberCount = p.MemberCount,
|
MemberCount = p.MemberCount,
|
||||||
Percentage = p.Percentage
|
Percentage = p.Percentage
|
||||||
}) },
|
}) },
|
||||||
MonthlyTrend = { src.MonthlyTrend.Select(t => new MonthlyMembershipTrend
|
MonthlyTrend = { src.MonthlyTrend.Select(t => new ProtoClub.MonthlyMembershipTrend
|
||||||
{
|
{
|
||||||
Month = t.Month ?? string.Empty,
|
Month = t.Month ?? string.Empty,
|
||||||
Activations = t.Activations,
|
Activations = t.Activations,
|
||||||
@@ -112,24 +114,55 @@ public class ClubMembershipProfile : IRegister
|
|||||||
NetChange = t.NetChange
|
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,
|
Id = src.Id,
|
||||||
UserId = src.UserId,
|
UserId = src.UserId,
|
||||||
UserName = src.UserName ?? string.Empty,
|
UserName = src.UserName ?? string.Empty,
|
||||||
PackageId = 0, // Not available in current entity
|
PackageId = src.PackageId,
|
||||||
PackageName = string.Empty, // Not available in current entity
|
PackageName = src.PackageName ?? string.Empty,
|
||||||
ActivationCode = string.Empty, // Not available in current entity
|
ActivationCode = string.Empty,
|
||||||
ActivatedAt = src.ActivatedAt.HasValue
|
ActivatedAt = src.ActivatedAt.HasValue
|
||||||
? Timestamp.FromDateTime(DateTime.SpecifyKind(src.ActivatedAt.Value, DateTimeKind.Utc))
|
? Timestamp.FromDateTime(DateTime.SpecifyKind(src.ActivatedAt.Value, DateTimeKind.Utc))
|
||||||
: null,
|
: null,
|
||||||
ExpiresAt = null, // Not available in current entity
|
ExpiresAt = null,
|
||||||
IsActive = src.IsActive,
|
IsActive = src.IsActive,
|
||||||
IsExpired = false, // Calculate based on ExpiresAt if available
|
IsExpired = false,
|
||||||
Created = Timestamp.FromDateTime(src.Created.UtcDateTime)
|
Created = Timestamp.FromDateTime(src.Created.UtcDateTime)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ public class DiscountProductProfile : IRegister
|
|||||||
src => src.CategoryId != null ? src.CategoryId.Value : (long?)null)
|
src => src.CategoryId != null ? src.CategoryId.Value : (long?)null)
|
||||||
.Map(dest => dest.IsActive,
|
.Map(dest => dest.IsActive,
|
||||||
src => src.IsActive != null ? src.IsActive.Value : (bool?)null)
|
src => src.IsActive != null ? src.IsActive.Value : (bool?)null)
|
||||||
|
.Map(dest => dest.InStock,
|
||||||
|
src => src.InStock != null ? src.InStock.Value : (bool?)null)
|
||||||
.Map(dest => dest.MinPrice,
|
.Map(dest => dest.MinPrice,
|
||||||
src => src.MinPrice != null ? (int?)src.MinPrice.Value : null)
|
src => src.MinPrice != null ? (int?)src.MinPrice.Value : null)
|
||||||
.Map(dest => dest.MaxPrice,
|
.Map(dest => dest.MaxPrice,
|
||||||
|
|||||||
@@ -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;
|
namespace CMSMicroservice.WebApi.Common.Mappings;
|
||||||
|
|
||||||
public class TransactionsProfile : IRegister
|
public class TransactionsProfile : IRegister
|
||||||
{
|
{
|
||||||
void IRegister.Register(TypeAdapterConfig config)
|
public void Register(TypeAdapterConfig config)
|
||||||
{
|
{
|
||||||
config.NewConfig<Protobuf.Protos.Transactions.GetAllTransactionsByFilterRequest, Application.TransactionsCQ.Queries.GetAllTransactionsByFilter.GetAllTransactionsByFilterQuery>()
|
config.NewConfig<ProtoTx.GetAllTransactionsByFilterRequest, AppTx.GetAllTransactionsByFilterQuery>()
|
||||||
.IgnoreIf((src, dest) => !src.Filter.HasPaymentStatus, dest => dest.Filter.PaymentStatus)
|
.Map(dest => dest.PaginationState, src => src.PaginationState)
|
||||||
.IgnoreIf((src, dest) => !src.Filter.HasType, dest => dest.Filter.Type);
|
.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,90 @@
|
|||||||
|
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 AppRollup = CMSMicroservice.Application.UserPackagePurchaseCQ.Queries.GetCustomerPackagePurchaseRollup;
|
||||||
|
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);
|
||||||
|
|
||||||
|
config.NewConfig<ProtoUp.GetCustomerPackagePurchaseRollupRequest, AppRollup.GetCustomerPackagePurchaseRollupQuery>()
|
||||||
|
.Map(dest => dest.PaginationState, src => src.PaginationState)
|
||||||
|
.Map(dest => dest.Filter, src => src.Filter);
|
||||||
|
|
||||||
|
config.NewConfig<ProtoUp.GetCustomerPackagePurchaseRollupFilter, AppRollup.GetCustomerPackagePurchaseRollupFilter>()
|
||||||
|
.Map(dest => dest.UserId, src => src.UserId)
|
||||||
|
.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);
|
||||||
|
|
||||||
|
config.NewConfig<AppRollup.GetCustomerPackagePurchaseRollupResponseDto, ProtoUp.GetCustomerPackagePurchaseRollupResponse>()
|
||||||
|
.Map(dest => dest.MetaData, src => src.MetaData)
|
||||||
|
.Map(dest => dest.Models, src => src.Models);
|
||||||
|
|
||||||
|
config.NewConfig<AppRollup.CustomerPackagePurchaseRollupModel, ProtoUp.CustomerPackagePurchaseRollupModel>()
|
||||||
|
.Map(dest => dest.UserId, src => src.UserId)
|
||||||
|
.Map(dest => dest.UserName, src => src.UserName)
|
||||||
|
.Map(dest => dest.UserMobile, src => src.UserMobile)
|
||||||
|
.Map(dest => dest.FirstPackageId, src => src.FirstPackageId)
|
||||||
|
.Map(dest => dest.FirstPackageName, src => src.FirstPackageName)
|
||||||
|
.Map(dest => dest.FirstAmount, src => src.FirstAmount)
|
||||||
|
.Map(dest => dest.FirstPurchasedAt, src => Timestamp.FromDateTime(DateTime.SpecifyKind(src.FirstPurchasedAt, DateTimeKind.Utc)))
|
||||||
|
.Map(dest => dest.LastPackageId, src => src.LastPackageId)
|
||||||
|
.Map(dest => dest.LastPackageName, src => src.LastPackageName)
|
||||||
|
.Map(dest => dest.LastAmount, src => src.LastAmount)
|
||||||
|
.Map(dest => dest.LastPurchasedAt, src => Timestamp.FromDateTime(DateTime.SpecifyKind(src.LastPurchasedAt, DateTimeKind.Utc)))
|
||||||
|
.Map(dest => dest.LastPurchaseMethod, src => (int)src.LastPurchaseMethod)
|
||||||
|
.Map(dest => dest.PurchaseCount, src => src.PurchaseCount)
|
||||||
|
.Map(dest => dest.TotalAmount, src => src.TotalAmount)
|
||||||
|
.Map(dest => dest.DayaCount, src => src.DayaCount)
|
||||||
|
.Map(dest => dest.DayaAmount, src => src.DayaAmount)
|
||||||
|
.Map(dest => dest.ManualCount, src => src.ManualCount)
|
||||||
|
.Map(dest => dest.ManualAmount, src => src.ManualAmount)
|
||||||
|
.Map(dest => dest.GatewayCount, src => src.GatewayCount)
|
||||||
|
.Map(dest => dest.GatewayAmount, src => src.GatewayAmount);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,10 @@ public class UserProfile : IRegister
|
|||||||
{
|
{
|
||||||
void IRegister.Register(TypeAdapterConfig config)
|
void IRegister.Register(TypeAdapterConfig config)
|
||||||
{
|
{
|
||||||
//config.NewConfig<Source,Destination>()
|
config.NewConfig<Application.UserCQ.Queries.GetAllUserByFilter.GetAllUserByFilterResponseModel,
|
||||||
// .Map(dest => dest.FullName, src => $"{src.Firstname} {src.Lastname}");
|
CMSMicroservice.Protobuf.Protos.User.GetAllUserByFilterResponseModel>()
|
||||||
|
.Map(dest => dest.ParentId, src => src.NetworkParentId)
|
||||||
|
.Map(dest => dest.DefaultAddress, src => src.DefaultAddress ?? string.Empty)
|
||||||
|
.Map(dest => dest.DefaultPostalCode, src => src.DefaultPostalCode ?? string.Empty);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
@@ -99,7 +99,20 @@ public class DiscountOrderService : DiscountOrderContract.DiscountOrderContractB
|
|||||||
|
|
||||||
public override async Task<UpdateOrderStatusResponse> UpdateOrderStatus(UpdateOrderStatusRequest request, ServerCallContext context)
|
public override async Task<UpdateOrderStatusResponse> UpdateOrderStatus(UpdateOrderStatusRequest request, ServerCallContext context)
|
||||||
{
|
{
|
||||||
return await _dispatchRequestToCQRS.Handle<UpdateOrderStatusRequest, UpdateOrderStatusCommand, UpdateOrderStatusResponse>(request, context);
|
// Proto DeliveryStatus ≠ Domain DeliveryStatus — نگاشت صریح لازم است
|
||||||
|
var command = new UpdateOrderStatusCommand
|
||||||
|
{
|
||||||
|
OrderId = request.OrderId,
|
||||||
|
DeliveryStatus = MapProtoDeliveryToDomain(request.DeliveryStatus),
|
||||||
|
TrackingCode = request.TrackingCode,
|
||||||
|
AdminNotes = request.AdminNotes
|
||||||
|
};
|
||||||
|
var result = await _sender.Send(command, context.CancellationToken);
|
||||||
|
return new UpdateOrderStatusResponse
|
||||||
|
{
|
||||||
|
Success = result.Success,
|
||||||
|
Message = result.Message ?? string.Empty
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<GetOrderByIdResponse> GetOrderById(GetOrderByIdRequest request, ServerCallContext context)
|
public override async Task<GetOrderByIdResponse> GetOrderById(GetOrderByIdRequest request, ServerCallContext context)
|
||||||
@@ -141,6 +154,8 @@ public class DiscountOrderService : DiscountOrderContract.DiscountOrderContractB
|
|||||||
Address = result.Address.Address ?? "",
|
Address = result.Address.Address ?? "",
|
||||||
PostalCode = result.Address.PostalCode ?? ""
|
PostalCode = result.Address.PostalCode ?? ""
|
||||||
};
|
};
|
||||||
|
if (!string.IsNullOrWhiteSpace(result.Address.Phone))
|
||||||
|
response.Address.Phone = result.Address.Phone;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var item in result.Items)
|
foreach (var item in result.Items)
|
||||||
@@ -197,9 +212,98 @@ public class DiscountOrderService : DiscountOrderContract.DiscountOrderContractB
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<GetAllDiscountOrdersResponse> GetAllDiscountOrders(GetAllDiscountOrdersRequest request, ServerCallContext context)
|
public override async Task<GetAllDiscountOrdersResponse> GetAllDiscountOrders(
|
||||||
|
GetAllDiscountOrdersRequest request, ServerCallContext context)
|
||||||
{
|
{
|
||||||
return await _dispatchRequestToCQRS.Handle<GetAllDiscountOrdersRequest, GetAllDiscountOrdersQuery, GetAllDiscountOrdersResponse>(request, context);
|
// Proto PaymentStatus ≠ Domain PaymentStatus (مقادیر int متفاوت) — Adapt خام باعث باگ لیست/فیلتر میشود
|
||||||
|
if (request.PaymentStatus is 3) // PAYMENT_REFUNDED — در دامنه وجود ندارد
|
||||||
|
{
|
||||||
|
return new GetAllDiscountOrdersResponse
|
||||||
|
{
|
||||||
|
MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
|
||||||
|
{
|
||||||
|
TotalCount = 0,
|
||||||
|
PageSize = request.PageSize > 0 ? request.PageSize : 20,
|
||||||
|
CurrentPage = request.PageNumber > 0 ? request.PageNumber : 1,
|
||||||
|
TotalPage = 0
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = new GetAllDiscountOrdersQuery
|
||||||
|
{
|
||||||
|
PaginationQuery = new Application.Common.Models.PaginationState
|
||||||
|
{
|
||||||
|
PageNumber = request.PageNumber > 0 ? request.PageNumber : 1,
|
||||||
|
PageSize = request.PageSize > 0 ? request.PageSize : 20
|
||||||
|
},
|
||||||
|
UserId = request.UserId,
|
||||||
|
UserMobile = request.UserMobile,
|
||||||
|
TrackingCode = request.TrackingCode,
|
||||||
|
FromDate = request.FromDate?.ToDateTime(),
|
||||||
|
ToDate = request.ToDate?.ToDateTime(),
|
||||||
|
MinAmount = request.MinAmount,
|
||||||
|
MaxAmount = request.MaxAmount
|
||||||
|
};
|
||||||
|
|
||||||
|
if (request.PaymentStatus is int paymentStatus)
|
||||||
|
query.PaymentStatus = MapProtoPaymentFilterToDomain(paymentStatus);
|
||||||
|
|
||||||
|
if (request.DeliveryStatus is int deliveryStatus)
|
||||||
|
query.DeliveryStatus = MapProtoDeliveryFilterToDomain(deliveryStatus);
|
||||||
|
|
||||||
|
var result = await _sender.Send(query, context.CancellationToken);
|
||||||
|
|
||||||
|
var response = new GetAllDiscountOrdersResponse
|
||||||
|
{
|
||||||
|
MetaData = new CMSMicroservice.Protobuf.Protos.MetaData
|
||||||
|
{
|
||||||
|
TotalCount = result.MetaData.TotalCount,
|
||||||
|
PageSize = result.MetaData.PageSize,
|
||||||
|
CurrentPage = result.MetaData.CurrentPage,
|
||||||
|
TotalPage = result.MetaData.TotalPage,
|
||||||
|
HasPrevious = result.MetaData.HasPrevious,
|
||||||
|
HasNext = result.MetaData.HasNext
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
foreach (var o in result.Models)
|
||||||
|
{
|
||||||
|
var model = new CMSMicroservice.Protobuf.Protos.DiscountOrder.AdminOrderDto
|
||||||
|
{
|
||||||
|
Id = o.Id,
|
||||||
|
UserId = o.UserId,
|
||||||
|
UserFullName = o.UserFullName ?? string.Empty,
|
||||||
|
UserMobile = o.UserMobile ?? string.Empty,
|
||||||
|
TotalAmount = o.TotalAmount,
|
||||||
|
DiscountBalanceUsed = o.DiscountBalanceUsed,
|
||||||
|
GatewayAmountPaid = o.GatewayAmountPaid,
|
||||||
|
VatAmount = o.VatAmount,
|
||||||
|
PaymentStatus = MapPaymentStatus(o.PaymentStatus),
|
||||||
|
DeliveryStatus = MapDeliveryStatus(o.DeliveryStatus),
|
||||||
|
ItemsCount = o.ItemsCount,
|
||||||
|
Created = Timestamp.FromDateTime(DateTime.SpecifyKind(o.Created, DateTimeKind.Utc))
|
||||||
|
};
|
||||||
|
|
||||||
|
if (o.PaymentDate.HasValue)
|
||||||
|
model.PaymentDate = Timestamp.FromDateTime(DateTime.SpecifyKind(o.PaymentDate.Value, DateTimeKind.Utc));
|
||||||
|
if (o.LastModified.HasValue)
|
||||||
|
model.LastModified = Timestamp.FromDateTime(DateTime.SpecifyKind(o.LastModified.Value, DateTimeKind.Utc));
|
||||||
|
if (!string.IsNullOrWhiteSpace(o.ShippingAddress))
|
||||||
|
model.ShippingAddress = o.ShippingAddress;
|
||||||
|
if (!string.IsNullOrWhiteSpace(o.ReceiverName))
|
||||||
|
model.ReceiverName = o.ReceiverName;
|
||||||
|
if (!string.IsNullOrWhiteSpace(o.ReceiverMobile))
|
||||||
|
model.ReceiverMobile = o.ReceiverMobile;
|
||||||
|
if (!string.IsNullOrWhiteSpace(o.TrackingCode))
|
||||||
|
model.TrackingCode = o.TrackingCode;
|
||||||
|
if (!string.IsNullOrWhiteSpace(o.AdminNote))
|
||||||
|
model.AdminNote = o.AdminNote;
|
||||||
|
|
||||||
|
response.Models.Add(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override async Task<GetDiscountSalesReportResponse> GetDiscountSalesReport(GetDiscountSalesReportRequest request, ServerCallContext context)
|
public override async Task<GetDiscountSalesReportResponse> GetDiscountSalesReport(GetDiscountSalesReportRequest request, ServerCallContext context)
|
||||||
@@ -359,14 +463,50 @@ public class DiscountOrderService : DiscountOrderContract.DiscountOrderContractB
|
|||||||
_ => CMSMicroservice.Protobuf.Protos.DiscountOrder.PaymentStatus.PaymentPending
|
_ => CMSMicroservice.Protobuf.Protos.DiscountOrder.PaymentStatus.PaymentPending
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// فیلتر UI/proto → دامنه: PENDING=0, COMPLETED=1, FAILED=2
|
||||||
|
/// </summary>
|
||||||
|
private static DomainEnums.PaymentStatus MapProtoPaymentFilterToDomain(int protoPaymentStatus) => protoPaymentStatus switch
|
||||||
|
{
|
||||||
|
1 => DomainEnums.PaymentStatus.Success, // PAYMENT_COMPLETED
|
||||||
|
2 => DomainEnums.PaymentStatus.Reject, // PAYMENT_FAILED
|
||||||
|
_ => DomainEnums.PaymentStatus.Pending // PAYMENT_PENDING (0) و پیشفرض
|
||||||
|
};
|
||||||
|
|
||||||
private static DeliveryStatus MapDeliveryStatus(DomainEnums.DeliveryStatus status) => status switch
|
private static DeliveryStatus MapDeliveryStatus(DomainEnums.DeliveryStatus status) => status switch
|
||||||
{
|
{
|
||||||
DomainEnums.DeliveryStatus.None => DeliveryStatus.DeliveryPending,
|
DomainEnums.DeliveryStatus.None => DeliveryStatus.DeliveryPending,
|
||||||
DomainEnums.DeliveryStatus.Pending => DeliveryStatus.DeliveryProcessing,
|
DomainEnums.DeliveryStatus.Pending => DeliveryStatus.DeliveryProcessing,
|
||||||
DomainEnums.DeliveryStatus.InTransit => DeliveryStatus.DeliveryShipped,
|
DomainEnums.DeliveryStatus.InTransit => DeliveryStatus.DeliveryShipped,
|
||||||
DomainEnums.DeliveryStatus.Delivered => DeliveryStatus.DeliveryDelivered,
|
DomainEnums.DeliveryStatus.Delivered => DeliveryStatus.DeliveryDelivered,
|
||||||
DomainEnums.DeliveryStatus.Returned => DeliveryStatus.DeliveryCancelled,
|
|
||||||
DomainEnums.DeliveryStatus.Cancelled => DeliveryStatus.DeliveryCancelled,
|
DomainEnums.DeliveryStatus.Cancelled => DeliveryStatus.DeliveryCancelled,
|
||||||
|
DomainEnums.DeliveryStatus.ReadyForOfficePickup => DeliveryStatus.DeliveryReadyForOffice,
|
||||||
|
DomainEnums.DeliveryStatus.Returned => DeliveryStatus.DeliveryReturned,
|
||||||
_ => DeliveryStatus.DeliveryPending
|
_ => DeliveryStatus.DeliveryPending
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// فیلتر UI/proto → دامنه DeliveryStatus
|
||||||
|
/// </summary>
|
||||||
|
private static DomainEnums.DeliveryStatus MapProtoDeliveryFilterToDomain(int protoDeliveryStatus) => protoDeliveryStatus switch
|
||||||
|
{
|
||||||
|
1 => DomainEnums.DeliveryStatus.Pending, // DELIVERY_PROCESSING
|
||||||
|
2 => DomainEnums.DeliveryStatus.InTransit, // DELIVERY_SHIPPED
|
||||||
|
3 => DomainEnums.DeliveryStatus.Delivered, // DELIVERY_DELIVERED
|
||||||
|
4 => DomainEnums.DeliveryStatus.Cancelled, // DELIVERY_CANCELLED
|
||||||
|
5 => DomainEnums.DeliveryStatus.ReadyForOfficePickup, // DELIVERY_READY_FOR_OFFICE
|
||||||
|
6 => DomainEnums.DeliveryStatus.Returned, // DELIVERY_RETURNED
|
||||||
|
_ => DomainEnums.DeliveryStatus.None // DELIVERY_PENDING (0)
|
||||||
|
};
|
||||||
|
|
||||||
|
private static DomainEnums.DeliveryStatus MapProtoDeliveryToDomain(DeliveryStatus status) => status switch
|
||||||
|
{
|
||||||
|
DeliveryStatus.DeliveryProcessing => DomainEnums.DeliveryStatus.Pending,
|
||||||
|
DeliveryStatus.DeliveryShipped => DomainEnums.DeliveryStatus.InTransit,
|
||||||
|
DeliveryStatus.DeliveryDelivered => DomainEnums.DeliveryStatus.Delivered,
|
||||||
|
DeliveryStatus.DeliveryCancelled => DomainEnums.DeliveryStatus.Cancelled,
|
||||||
|
DeliveryStatus.DeliveryReadyForOffice => DomainEnums.DeliveryStatus.ReadyForOfficePickup,
|
||||||
|
DeliveryStatus.DeliveryReturned => DomainEnums.DeliveryStatus.Returned,
|
||||||
|
_ => DomainEnums.DeliveryStatus.None
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user