refactor: rename UserWalletChangeLog→UserWalletHistory, add History interceptor & migration
Build and Deploy to Kubernetes / build-and-deploy (push) Successful in 9m11s

- Rename UserWalletChangeLog to UserWalletHistory across 54+ files (entities, configs, DTOs, commands, queries, protos, services)
- Rename 34 files and 11 directories accordingly
- Rename proto file userwalletchangelog.proto → userwallethistory.proto
- Add IHasHistory<T> generic interface for history auto-tracking
- Implement IHasHistory<PackageHistory> on Package entity
- Add HistoryTrackingSaveChangesInterceptor (reflection-based, auto-fills Old* values from OriginalValues)
- Wire interceptor in DI and ApplicationDbContext
- Add EF migration Q27_HistoryTables_And_RenameWalletHistory:
  * RenameTable UserWalletChangeLogs → UserWalletHistories (preserves data)
  * Rename PK, FK constraints and indexes via sp_rename
  * CreateTable ClubMembershipCycleHistories + PackageHistories
This commit is contained in:
masoodafar-web
2026-02-27 06:22:15 +03:30
parent fdbb91d2e1
commit 10d2ca20d1
86 changed files with 6255 additions and 472 deletions
@@ -192,7 +192,7 @@ public class CalculateWeeklyCommissionPoolCommandHandler : IRequestHandler<Calcu
.ToDictionaryAsync(w => w.UserId, cancellationToken);
var newWallets = new List<UserWallet>();
var walletLogs = new List<UserWalletChangeLog>();
var walletLogs = new List<UserWalletHistory>();
foreach (var payout in payouts)
{
@@ -241,7 +241,7 @@ public class CalculateWeeklyCommissionPoolCommandHandler : IRequestHandler<Calcu
wallet.NetworkBalance += payout.TotalAmount;
// ایجاد لاگ تغییر کیف پول
var walletLog = new UserWalletChangeLog
var walletLog = new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -258,7 +258,7 @@ public class CalculateWeeklyCommissionPoolCommandHandler : IRequestHandler<Calcu
}
// ذخیره تغییرات کیف پول و لاگ‌ها
await _context.UserWalletChangeLogs.AddRangeAsync(walletLogs, cancellationToken);
await _context.UserWalletHistories.AddRangeAsync(walletLogs, cancellationToken);
await _context.SaveChangesAsync(cancellationToken);
}
@@ -271,7 +271,7 @@ public class CalculateWeeklyCommissionPoolCommandHandler : IRequestHandler<Calcu
CancellationToken cancellationToken)
{
// پیدا کردن لاگ‌های کیف پول مرتبط با پرداخت‌های قبلی
var oldWalletLogs = await _context.UserWalletChangeLogs
var oldWalletLogs = await _context.UserWalletHistories
.Where(l => l.RefrenceId.HasValue && oldPayoutIds.Contains(l.RefrenceId.Value))
.ToListAsync(cancellationToken);
@@ -300,7 +300,7 @@ public class CalculateWeeklyCommissionPoolCommandHandler : IRequestHandler<Calcu
}
// حذف لاگ‌های قبلی
_context.UserWalletChangeLogs.RemoveRange(oldWalletLogs);
_context.UserWalletHistories.RemoveRange(oldWalletLogs);
await _context.SaveChangesAsync(cancellationToken);
}
@@ -32,7 +32,7 @@ public interface IApplicationDbContext
DbSet<OrderVAT> OrderVATs { get; }
DbSet<UserPackagePurchase> UserPackagePurchases { get; }
DbSet<UserWallet> UserWallets { get; }
DbSet<UserWalletChangeLog> UserWalletChangeLogs { get; }
DbSet<UserWalletHistory> UserWalletHistories { get; }
DbSet<ManualPayment> ManualPayments { get; }
DbSet<PaymentTransaction> PaymentTransactions { get; }
DbSet<PublicMessage> PublicMessages { get; }
@@ -1,16 +0,0 @@
using CMSMicroservice.Application.UserWalletChangeLogCQ.Queries.GetAllUserWalletChangeLogByFilter;
using CMSMicroservice.Application.UserWalletChangeLogCQ.Queries.GetUserWalletChangeLog;
namespace CMSMicroservice.Application.Common.Mappings;
public class UserWalletChangeLogProfile : IRegister
{
void IRegister.Register(TypeAdapterConfig config)
{
config.NewConfig<UserWalletChangeLog,GetAllUserWalletChangeLogByFilterResponseModel>()
.Map(dest => dest.CreatedAt, src => src.Created);
config.NewConfig<UserWalletChangeLog, GetUserWalletChangeLogResponseDto>()
.Map(dest => dest.CreatedAt, src => src.Created);
}
}
@@ -0,0 +1,16 @@
using CMSMicroservice.Application.UserWalletHistoryCQ.Queries.GetAllUserWalletHistoryByFilter;
using CMSMicroservice.Application.UserWalletHistoryCQ.Queries.GetUserWalletHistory;
namespace CMSMicroservice.Application.Common.Mappings;
public class UserWalletHistoryProfile : IRegister
{
void IRegister.Register(TypeAdapterConfig config)
{
config.NewConfig<UserWalletHistory,GetAllUserWalletHistoryByFilterResponseModel>()
.Map(dest => dest.CreatedAt, src => src.Created);
config.NewConfig<UserWalletHistory, GetUserWalletHistoryResponseDto>()
.Map(dest => dest.CreatedAt, src => src.Created);
}
}
@@ -223,7 +223,7 @@ public class CheckAndProcessDayaLoansCommandHandler : IRequestHandler<CheckAndPr
// 3. شارژ کیف پول عادی
wallet.Balance += package.Price;
var mainLog = new UserWalletChangeLog
var mainLog = new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = 0,
@@ -233,13 +233,13 @@ public class CheckAndProcessDayaLoansCommandHandler : IRequestHandler<CheckAndPr
IsIncrease = true,
RefrenceId = transaction.Id
};
await _context.UserWalletChangeLogs.AddAsync(mainLog, cancellationToken);
await _context.UserWalletHistories.AddAsync(mainLog, cancellationToken);
// 4. شارژ کیف پول تخفیف
var discountAmount = (long)(package.Price * package.DiscountMultiplier);
wallet.DiscountBalance += discountAmount;
var discountLog = new UserWalletChangeLog
var discountLog = new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -251,7 +251,7 @@ public class CheckAndProcessDayaLoansCommandHandler : IRequestHandler<CheckAndPr
IsIncrease = true,
RefrenceId = transaction.Id
};
await _context.UserWalletChangeLogs.AddAsync(discountLog, cancellationToken);
await _context.UserWalletHistories.AddAsync(discountLog, cancellationToken);
// 5. به‌روزرسانی کاربر
user.HasReceivedDayaCredit = true;
@@ -67,7 +67,7 @@ public class CompleteOrderPaymentCommandHandler : IRequestHandler<CompleteOrderP
userWallet.DiscountBalance -= order.DiscountBalanceUsed;
// ثبت لاگ تغییرات کیف پول
_context.UserWalletChangeLogs.Add(new Domain.Entities.UserWalletChangeLog
_context.UserWalletHistories.Add(new Domain.Entities.UserWalletHistory
{
WalletId = userWallet.Id,
CurrentBalance = userWallet.Balance,
@@ -279,7 +279,7 @@ public class PlaceOrderCommandHandler : IRequestHandler<PlaceOrderCommand, Place
walletForDeduct.DiscountBalance -= actualDiscountBalanceUsed;
// ثبت لاگ تغییرات کیف پول
_context.UserWalletChangeLogs.Add(new Domain.Entities.UserWalletChangeLog
_context.UserWalletHistories.Add(new Domain.Entities.UserWalletHistory
{
WalletId = walletForDeduct.Id,
CurrentBalance = walletForDeduct.Balance,
@@ -108,7 +108,7 @@ public class ApproveManualPaymentCommandHandler : IRequestHandler<ApproveManualP
wallet.DiscountBalance += manualPayment.Amount;
// لاگ Balance
await _context.UserWalletChangeLogs.AddAsync(new UserWalletChangeLog
await _context.UserWalletHistories.AddAsync(new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -122,7 +122,7 @@ public class ApproveManualPaymentCommandHandler : IRequestHandler<ApproveManualP
}, cancellationToken);
// لاگ DiscountBalance
await _context.UserWalletChangeLogs.AddAsync(new UserWalletChangeLog
await _context.UserWalletHistories.AddAsync(new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -139,7 +139,7 @@ public class ApproveManualPaymentCommandHandler : IRequestHandler<ApproveManualP
case ManualPaymentType.DiscountWalletCharge:
wallet.DiscountBalance += manualPayment.Amount;
await _context.UserWalletChangeLogs.AddAsync(new UserWalletChangeLog
await _context.UserWalletHistories.AddAsync(new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -156,7 +156,7 @@ public class ApproveManualPaymentCommandHandler : IRequestHandler<ApproveManualP
case ManualPaymentType.NetworkWalletCharge:
wallet.NetworkBalance += manualPayment.Amount;
await _context.UserWalletChangeLogs.AddAsync(new UserWalletChangeLog
await _context.UserWalletHistories.AddAsync(new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -183,7 +183,7 @@ public class ApproveManualPaymentCommandHandler : IRequestHandler<ApproveManualP
wallet.DiscountBalance -= manualPayment.Amount;
}
await _context.UserWalletChangeLogs.AddAsync(new UserWalletChangeLog
await _context.UserWalletHistories.AddAsync(new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -201,7 +201,7 @@ public class ApproveManualPaymentCommandHandler : IRequestHandler<ApproveManualP
// Other یا سایر موارد - فقط Balance
wallet.Balance += manualPayment.Amount;
await _context.UserWalletChangeLogs.AddAsync(new UserWalletChangeLog
await _context.UserWalletHistories.AddAsync(new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -120,7 +120,7 @@ public class CreateManualPaymentCommandHandler : IRequestHandler<CreateManualPay
wallet.DiscountBalance += discountBalanceAmount;
// 8. ثبت لاگ کیف پول
var walletLog = new UserWalletChangeLog
var walletLog = new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = 0,
@@ -133,7 +133,7 @@ public class CreateManualPaymentCommandHandler : IRequestHandler<CreateManualPay
RefrenceId = transaction.Id
};
await _context.UserWalletChangeLogs.AddAsync(walletLog, cancellationToken);
await _context.UserWalletHistories.AddAsync(walletLog, cancellationToken);
// 9. تنظیم روش خرید پکیج
user.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
@@ -104,7 +104,7 @@ public class ProcessManualMembershipPaymentCommandHandler : IRequestHandler<Proc
wallet.DiscountBalance += request.Amount;
// 8. ثبت لاگ Balance
var balanceLog = new UserWalletChangeLog
var balanceLog = new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -116,7 +116,7 @@ public class ProcessManualMembershipPaymentCommandHandler : IRequestHandler<Proc
IsIncrease = true,
RefrenceId = transaction.Id
};
await _context.UserWalletChangeLogs.AddAsync(balanceLog, cancellationToken);
await _context.UserWalletHistories.AddAsync(balanceLog, cancellationToken);
user.PackagePurchaseMethod = PackagePurchaseMethod.DirectPurchase;
// 10. به‌روزرسانی ManualPayment با TransactionId
@@ -60,7 +60,7 @@ public class CancelOrderByAdminCommandHandler : IRequestHandler<CancelOrderByAdm
var wallet = order.User.UserWallets.FirstOrDefault();
if (wallet != null)
{
var walletLog = new UserWalletChangeLog
var walletLog = new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -74,7 +74,7 @@ public class CancelOrderByAdminCommandHandler : IRequestHandler<CancelOrderByAdm
wallet.Balance += order.Amount;
await _context.UserWalletChangeLogs.AddAsync(walletLog, cancellationToken);
await _context.UserWalletHistories.AddAsync(walletLog, cancellationToken);
_logger.LogInformation(
"Refund processed. OrderId: {OrderId}, Amount: {Amount}, UserId: {UserId}",
@@ -129,7 +129,7 @@ public class VerifyPackagePurchaseCommandHandler
await _context.SaveChangesAsync(cancellationToken);
// 6. ثبت لاگ تغییر Balance
var balanceLog = new UserWalletChangeLog
var balanceLog = new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -141,10 +141,10 @@ public class VerifyPackagePurchaseCommandHandler
IsIncrease = true,
RefrenceId = transaction.Id
};
await _context.UserWalletChangeLogs.AddAsync(balanceLog, cancellationToken);
await _context.UserWalletHistories.AddAsync(balanceLog, cancellationToken);
// 7. ثبت لاگ تغییر DiscountBalance
var discountLog = new UserWalletChangeLog
var discountLog = new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -156,7 +156,7 @@ public class VerifyPackagePurchaseCommandHandler
IsIncrease = true,
RefrenceId = transaction.Id
};
await _context.UserWalletChangeLogs.AddAsync(discountLog, cancellationToken);
await _context.UserWalletHistories.AddAsync(discountLog, cancellationToken);
// 8. ثبت UserPackagePurchase
if (order.PackageId.HasValue)
@@ -60,7 +60,7 @@ public class GetCustomerReferralsQueryHandler : IRequestHandler<GetCustomerRefer
// Calculate this month's commission from wallet changelog
var startOfMonth = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1);
var thisMonthCommission = await _context.UserWalletChangeLogs
var thisMonthCommission = await _context.UserWalletHistories
.AsNoTracking()
.Include(x => x.Wallet)
.Where(x => x.Wallet.UserId == userId && x.Created >= startOfMonth)
@@ -1,6 +1,6 @@
namespace CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletChangeLog;
namespace CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletHistory;
public class GetCustomerWalletChangeLogQuery : IRequest<List<GetCustomerWalletChangeLogResponseDto>>
public class GetCustomerWalletHistoryQuery : IRequest<List<GetCustomerWalletHistoryResponseDto>>
{
/// <summary>
/// فیلتر بر اساس شناسه ارجاع (اختیاری)
@@ -1,11 +1,11 @@
namespace CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletChangeLog;
namespace CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletHistory;
public class GetCustomerWalletChangeLogQueryHandler : IRequestHandler<GetCustomerWalletChangeLogQuery, List<GetCustomerWalletChangeLogResponseDto>>
public class GetCustomerWalletHistoryQueryHandler : IRequestHandler<GetCustomerWalletHistoryQuery, List<GetCustomerWalletHistoryResponseDto>>
{
private readonly IApplicationDbContext _context;
private readonly ICurrentUserService _currentUser;
public GetCustomerWalletChangeLogQueryHandler(
public GetCustomerWalletHistoryQueryHandler(
IApplicationDbContext context,
ICurrentUserService currentUser)
{
@@ -13,8 +13,8 @@ public class GetCustomerWalletChangeLogQueryHandler : IRequestHandler<GetCustome
_currentUser = currentUser;
}
public async Task<List<GetCustomerWalletChangeLogResponseDto>> Handle(
GetCustomerWalletChangeLogQuery request,
public async Task<List<GetCustomerWalletHistoryResponseDto>> Handle(
GetCustomerWalletHistoryQuery request,
CancellationToken cancellationToken)
{
// Get current user's ID from JWT
@@ -35,7 +35,7 @@ public class GetCustomerWalletChangeLogQueryHandler : IRequestHandler<GetCustome
}
// Build query for wallet change logs
var query = _context.UserWalletChangeLogs
var query = _context.UserWalletHistories
.AsNoTracking()
.Where(x => x.WalletId == userWallet.Id);
@@ -53,7 +53,7 @@ public class GetCustomerWalletChangeLogQueryHandler : IRequestHandler<GetCustome
// Order by newest first
var result = await query
.OrderByDescending(x => x.Created)
.ProjectToType<GetCustomerWalletChangeLogResponseDto>()
.ProjectToType<GetCustomerWalletHistoryResponseDto>()
.ToListAsync(cancellationToken);
return result;
@@ -1,6 +1,6 @@
namespace CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletChangeLog;
namespace CMSMicroservice.Application.UserWalletCQ.Queries.GetCustomerWalletHistory;
public class GetCustomerWalletChangeLogResponseDto
public class GetCustomerWalletHistoryResponseDto
{
/// <summary>
/// موجودی جاری
@@ -1,21 +0,0 @@
using CMSMicroservice.Domain.Events;
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Commands.CreateNewUserWalletChangeLog;
public class CreateNewUserWalletChangeLogCommandHandler : IRequestHandler<CreateNewUserWalletChangeLogCommand, CreateNewUserWalletChangeLogResponseDto>
{
private readonly IApplicationDbContext _context;
public CreateNewUserWalletChangeLogCommandHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<CreateNewUserWalletChangeLogResponseDto> Handle(CreateNewUserWalletChangeLogCommand request,
CancellationToken cancellationToken)
{
var entity = request.Adapt<UserWalletChangeLog>();
await _context.UserWalletChangeLogs.AddAsync(entity, cancellationToken);
entity.AddDomainEvent(new CreateNewUserWalletChangeLogEvent(entity));
await _context.SaveChangesAsync(cancellationToken);
return entity.Adapt<CreateNewUserWalletChangeLogResponseDto>();
}
}
@@ -1,7 +0,0 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Commands.CreateNewUserWalletChangeLog;
public class CreateNewUserWalletChangeLogResponseDto
{
//شناسه
public long Id { get; set; }
}
@@ -1,7 +0,0 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Commands.DeleteUserWalletChangeLog;
public record DeleteUserWalletChangeLogCommand : IRequest<Unit>
{
//شناسه
public long Id { get; init; }
}
@@ -1,22 +0,0 @@
using CMSMicroservice.Domain.Events;
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Commands.DeleteUserWalletChangeLog;
public class DeleteUserWalletChangeLogCommandHandler : IRequestHandler<DeleteUserWalletChangeLogCommand, Unit>
{
private readonly IApplicationDbContext _context;
public DeleteUserWalletChangeLogCommandHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<Unit> Handle(DeleteUserWalletChangeLogCommand request, CancellationToken cancellationToken)
{
var entity = await _context.UserWalletChangeLogs
.FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken) ?? throw new NotFoundException(nameof(UserWalletChangeLog), request.Id);
entity.IsDeleted = true;
_context.UserWalletChangeLogs.Update(entity);
entity.AddDomainEvent(new DeleteUserWalletChangeLogEvent(entity));
await _context.SaveChangesAsync(cancellationToken);
return Unit.Value;
}
}
@@ -1,16 +0,0 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Commands.DeleteUserWalletChangeLog;
public class DeleteUserWalletChangeLogCommandValidator : AbstractValidator<DeleteUserWalletChangeLogCommand>
{
public DeleteUserWalletChangeLogCommandValidator()
{
RuleFor(model => model.Id)
.NotNull();
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<DeleteUserWalletChangeLogCommand>.CreateWithOptions((DeleteUserWalletChangeLogCommand)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
@@ -1,22 +0,0 @@
using CMSMicroservice.Domain.Events;
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Commands.UpdateUserWalletChangeLog;
public class UpdateUserWalletChangeLogCommandHandler : IRequestHandler<UpdateUserWalletChangeLogCommand, Unit>
{
private readonly IApplicationDbContext _context;
public UpdateUserWalletChangeLogCommandHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<Unit> Handle(UpdateUserWalletChangeLogCommand request, CancellationToken cancellationToken)
{
var entity = await _context.UserWalletChangeLogs
.FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken) ?? throw new NotFoundException(nameof(UserWalletChangeLog), request.Id);
request.Adapt(entity);
_context.UserWalletChangeLogs.Update(entity);
entity.AddDomainEvent(new UpdateUserWalletChangeLogEvent(entity));
await _context.SaveChangesAsync(cancellationToken);
return Unit.Value;
}
}
@@ -1,22 +0,0 @@
using CMSMicroservice.Domain.Events;
using Microsoft.Extensions.Logging;
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.EventHandlers;
public class CreateNewUserWalletChangeLogEventHandler : INotificationHandler<CreateNewUserWalletChangeLogEvent>
{
private readonly ILogger<
CreateNewUserWalletChangeLogEventHandler> _logger;
public CreateNewUserWalletChangeLogEventHandler(ILogger<CreateNewUserWalletChangeLogEventHandler> logger)
{
_logger = logger;
}
public Task Handle(CreateNewUserWalletChangeLogEvent notification, CancellationToken cancellationToken)
{
_logger.LogInformation("Domain Event: {DomainEvent}", notification.GetType().Name);
return Task.CompletedTask;
}
}
@@ -1,22 +0,0 @@
using CMSMicroservice.Domain.Events;
using Microsoft.Extensions.Logging;
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.EventHandlers;
public class DeleteUserWalletChangeLogEventHandler : INotificationHandler<DeleteUserWalletChangeLogEvent>
{
private readonly ILogger<
DeleteUserWalletChangeLogEventHandler> _logger;
public DeleteUserWalletChangeLogEventHandler(ILogger<DeleteUserWalletChangeLogEventHandler> logger)
{
_logger = logger;
}
public Task Handle(DeleteUserWalletChangeLogEvent notification, CancellationToken cancellationToken)
{
_logger.LogInformation("Domain Event: {DomainEvent}", notification.GetType().Name);
return Task.CompletedTask;
}
}
@@ -1,22 +0,0 @@
using CMSMicroservice.Domain.Events;
using Microsoft.Extensions.Logging;
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.EventHandlers;
public class UpdateUserWalletChangeLogEventHandler : INotificationHandler<UpdateUserWalletChangeLogEvent>
{
private readonly ILogger<
UpdateUserWalletChangeLogEventHandler> _logger;
public UpdateUserWalletChangeLogEventHandler(ILogger<UpdateUserWalletChangeLogEventHandler> logger)
{
_logger = logger;
}
public Task Handle(UpdateUserWalletChangeLogEvent notification, CancellationToken cancellationToken)
{
_logger.LogInformation("Domain Event: {DomainEvent}", notification.GetType().Name);
return Task.CompletedTask;
}
}
@@ -1,14 +0,0 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Queries.GetAllUserWalletChangeLogByFilter;
public class GetAllUserWalletChangeLogByFilterQueryValidator : AbstractValidator<GetAllUserWalletChangeLogByFilterQuery>
{
public GetAllUserWalletChangeLogByFilterQueryValidator()
{
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<GetAllUserWalletChangeLogByFilterQuery>.CreateWithOptions((GetAllUserWalletChangeLogByFilterQuery)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
@@ -1,7 +0,0 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Queries.GetUserWalletChangeLog;
public record GetUserWalletChangeLogQuery : IRequest<GetUserWalletChangeLogResponseDto>
{
//شناسه
public long Id { get; init; }
}
@@ -1,22 +0,0 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Queries.GetUserWalletChangeLog;
public class GetUserWalletChangeLogQueryHandler : IRequestHandler<GetUserWalletChangeLogQuery, GetUserWalletChangeLogResponseDto>
{
private readonly IApplicationDbContext _context;
public GetUserWalletChangeLogQueryHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<GetUserWalletChangeLogResponseDto> Handle(GetUserWalletChangeLogQuery request,
CancellationToken cancellationToken)
{
var response = await _context.UserWalletChangeLogs
.AsNoTracking()
.Where(x => x.Id == request.Id)
.ProjectToType<GetUserWalletChangeLogResponseDto>()
.FirstOrDefaultAsync(cancellationToken);
return response ?? throw new NotFoundException(nameof(UserWalletChangeLog), request.Id);
}
}
@@ -1,5 +1,5 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Commands.CreateNewUserWalletChangeLog;
public record CreateNewUserWalletChangeLogCommand : IRequest<CreateNewUserWalletChangeLogResponseDto>
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Commands.CreateNewUserWalletHistory;
public record CreateNewUserWalletHistoryCommand : IRequest<CreateNewUserWalletHistoryResponseDto>
{
//شناسه کیف پول
public long WalletId { get; init; }
@@ -0,0 +1,21 @@
using CMSMicroservice.Domain.Events;
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Commands.CreateNewUserWalletHistory;
public class CreateNewUserWalletHistoryCommandHandler : IRequestHandler<CreateNewUserWalletHistoryCommand, CreateNewUserWalletHistoryResponseDto>
{
private readonly IApplicationDbContext _context;
public CreateNewUserWalletHistoryCommandHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<CreateNewUserWalletHistoryResponseDto> Handle(CreateNewUserWalletHistoryCommand request,
CancellationToken cancellationToken)
{
var entity = request.Adapt<UserWalletHistory>();
await _context.UserWalletHistories.AddAsync(entity, cancellationToken);
entity.AddDomainEvent(new CreateNewUserWalletHistoryEvent(entity));
await _context.SaveChangesAsync(cancellationToken);
return entity.Adapt<CreateNewUserWalletHistoryResponseDto>();
}
}
@@ -1,7 +1,7 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Commands.CreateNewUserWalletChangeLog;
public class CreateNewUserWalletChangeLogCommandValidator : AbstractValidator<CreateNewUserWalletChangeLogCommand>
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Commands.CreateNewUserWalletHistory;
public class CreateNewUserWalletHistoryCommandValidator : AbstractValidator<CreateNewUserWalletHistoryCommand>
{
public CreateNewUserWalletChangeLogCommandValidator()
public CreateNewUserWalletHistoryCommandValidator()
{
RuleFor(model => model.WalletId)
.NotNull();
@@ -18,7 +18,7 @@ public class CreateNewUserWalletChangeLogCommandValidator : AbstractValidator<Cr
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<CreateNewUserWalletChangeLogCommand>.CreateWithOptions((CreateNewUserWalletChangeLogCommand)model, x => x.IncludeProperties(propertyName)));
var result = await ValidateAsync(ValidationContext<CreateNewUserWalletHistoryCommand>.CreateWithOptions((CreateNewUserWalletHistoryCommand)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
@@ -0,0 +1,7 @@
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Commands.CreateNewUserWalletHistory;
public class CreateNewUserWalletHistoryResponseDto
{
//شناسه
public long Id { get; set; }
}
@@ -0,0 +1,7 @@
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Commands.DeleteUserWalletHistory;
public record DeleteUserWalletHistoryCommand : IRequest<Unit>
{
//شناسه
public long Id { get; init; }
}
@@ -0,0 +1,22 @@
using CMSMicroservice.Domain.Events;
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Commands.DeleteUserWalletHistory;
public class DeleteUserWalletHistoryCommandHandler : IRequestHandler<DeleteUserWalletHistoryCommand, Unit>
{
private readonly IApplicationDbContext _context;
public DeleteUserWalletHistoryCommandHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<Unit> Handle(DeleteUserWalletHistoryCommand request, CancellationToken cancellationToken)
{
var entity = await _context.UserWalletHistories
.FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken) ?? throw new NotFoundException(nameof(UserWalletHistory), request.Id);
entity.IsDeleted = true;
_context.UserWalletHistories.Update(entity);
entity.AddDomainEvent(new DeleteUserWalletHistoryEvent(entity));
await _context.SaveChangesAsync(cancellationToken);
return Unit.Value;
}
}
@@ -0,0 +1,16 @@
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Commands.DeleteUserWalletHistory;
public class DeleteUserWalletHistoryCommandValidator : AbstractValidator<DeleteUserWalletHistoryCommand>
{
public DeleteUserWalletHistoryCommandValidator()
{
RuleFor(model => model.Id)
.NotNull();
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<DeleteUserWalletHistoryCommand>.CreateWithOptions((DeleteUserWalletHistoryCommand)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
@@ -1,5 +1,5 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Commands.UpdateUserWalletChangeLog;
public record UpdateUserWalletChangeLogCommand : IRequest<Unit>
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Commands.UpdateUserWalletHistory;
public record UpdateUserWalletHistoryCommand : IRequest<Unit>
{
//شناسه
public long Id { get; init; }
@@ -0,0 +1,22 @@
using CMSMicroservice.Domain.Events;
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Commands.UpdateUserWalletHistory;
public class UpdateUserWalletHistoryCommandHandler : IRequestHandler<UpdateUserWalletHistoryCommand, Unit>
{
private readonly IApplicationDbContext _context;
public UpdateUserWalletHistoryCommandHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<Unit> Handle(UpdateUserWalletHistoryCommand request, CancellationToken cancellationToken)
{
var entity = await _context.UserWalletHistories
.FirstOrDefaultAsync(x => x.Id == request.Id, cancellationToken) ?? throw new NotFoundException(nameof(UserWalletHistory), request.Id);
request.Adapt(entity);
_context.UserWalletHistories.Update(entity);
entity.AddDomainEvent(new UpdateUserWalletHistoryEvent(entity));
await _context.SaveChangesAsync(cancellationToken);
return Unit.Value;
}
}
@@ -1,7 +1,7 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Commands.UpdateUserWalletChangeLog;
public class UpdateUserWalletChangeLogCommandValidator : AbstractValidator<UpdateUserWalletChangeLogCommand>
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Commands.UpdateUserWalletHistory;
public class UpdateUserWalletHistoryCommandValidator : AbstractValidator<UpdateUserWalletHistoryCommand>
{
public UpdateUserWalletChangeLogCommandValidator()
public UpdateUserWalletHistoryCommandValidator()
{
RuleFor(model => model.Id)
.NotNull();
@@ -20,7 +20,7 @@ public class UpdateUserWalletChangeLogCommandValidator : AbstractValidator<Updat
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<UpdateUserWalletChangeLogCommand>.CreateWithOptions((UpdateUserWalletChangeLogCommand)model, x => x.IncludeProperties(propertyName)));
var result = await ValidateAsync(ValidationContext<UpdateUserWalletHistoryCommand>.CreateWithOptions((UpdateUserWalletHistoryCommand)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
@@ -0,0 +1,22 @@
using CMSMicroservice.Domain.Events;
using Microsoft.Extensions.Logging;
namespace CMSMicroservice.Application.UserWalletHistoryCQ.EventHandlers;
public class CreateNewUserWalletHistoryEventHandler : INotificationHandler<CreateNewUserWalletHistoryEvent>
{
private readonly ILogger<
CreateNewUserWalletHistoryEventHandler> _logger;
public CreateNewUserWalletHistoryEventHandler(ILogger<CreateNewUserWalletHistoryEventHandler> logger)
{
_logger = logger;
}
public Task Handle(CreateNewUserWalletHistoryEvent notification, CancellationToken cancellationToken)
{
_logger.LogInformation("Domain Event: {DomainEvent}", notification.GetType().Name);
return Task.CompletedTask;
}
}
@@ -0,0 +1,22 @@
using CMSMicroservice.Domain.Events;
using Microsoft.Extensions.Logging;
namespace CMSMicroservice.Application.UserWalletHistoryCQ.EventHandlers;
public class DeleteUserWalletHistoryEventHandler : INotificationHandler<DeleteUserWalletHistoryEvent>
{
private readonly ILogger<
DeleteUserWalletHistoryEventHandler> _logger;
public DeleteUserWalletHistoryEventHandler(ILogger<DeleteUserWalletHistoryEventHandler> logger)
{
_logger = logger;
}
public Task Handle(DeleteUserWalletHistoryEvent notification, CancellationToken cancellationToken)
{
_logger.LogInformation("Domain Event: {DomainEvent}", notification.GetType().Name);
return Task.CompletedTask;
}
}
@@ -0,0 +1,22 @@
using CMSMicroservice.Domain.Events;
using Microsoft.Extensions.Logging;
namespace CMSMicroservice.Application.UserWalletHistoryCQ.EventHandlers;
public class UpdateUserWalletHistoryEventHandler : INotificationHandler<UpdateUserWalletHistoryEvent>
{
private readonly ILogger<
UpdateUserWalletHistoryEventHandler> _logger;
public UpdateUserWalletHistoryEventHandler(ILogger<UpdateUserWalletHistoryEventHandler> logger)
{
_logger = logger;
}
public Task Handle(UpdateUserWalletHistoryEvent notification, CancellationToken cancellationToken)
{
_logger.LogInformation("Domain Event: {DomainEvent}", notification.GetType().Name);
return Task.CompletedTask;
}
}
@@ -1,14 +1,14 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Queries.GetAllUserWalletChangeLogByFilter;
public record GetAllUserWalletChangeLogByFilterQuery : IRequest<GetAllUserWalletChangeLogByFilterResponseDto>
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Queries.GetAllUserWalletHistoryByFilter;
public record GetAllUserWalletHistoryByFilterQuery : IRequest<GetAllUserWalletHistoryByFilterResponseDto>
{
//موقعیت صفحه بندی
public PaginationState? PaginationState { get; init; }
//مرتب سازی بر اساس
public string? SortBy { get; init; }
//فیلتر
public GetAllUserWalletChangeLogByFilterFilter? Filter { get; init; }
public GetAllUserWalletHistoryByFilterFilter? Filter { get; init; }
}public class GetAllUserWalletChangeLogByFilterFilter
}public class GetAllUserWalletHistoryByFilterFilter
{
//شناسه
public long? Id { get; set; }
@@ -1,16 +1,16 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Queries.GetAllUserWalletChangeLogByFilter;
public class GetAllUserWalletChangeLogByFilterQueryHandler : IRequestHandler<GetAllUserWalletChangeLogByFilterQuery, GetAllUserWalletChangeLogByFilterResponseDto>
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Queries.GetAllUserWalletHistoryByFilter;
public class GetAllUserWalletHistoryByFilterQueryHandler : IRequestHandler<GetAllUserWalletHistoryByFilterQuery, GetAllUserWalletHistoryByFilterResponseDto>
{
private readonly IApplicationDbContext _context;
public GetAllUserWalletChangeLogByFilterQueryHandler(IApplicationDbContext context)
public GetAllUserWalletHistoryByFilterQueryHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<GetAllUserWalletChangeLogByFilterResponseDto> Handle(GetAllUserWalletChangeLogByFilterQuery request, CancellationToken cancellationToken)
public async Task<GetAllUserWalletHistoryByFilterResponseDto> Handle(GetAllUserWalletHistoryByFilterQuery request, CancellationToken cancellationToken)
{
var query = _context.UserWalletChangeLogs
var query = _context.UserWalletHistories
.Include(i=>i.Wallet)
.ApplyOrder(sortBy: request.SortBy)
.AsNoTracking()
@@ -27,11 +27,11 @@ public class GetAllUserWalletChangeLogByFilterQueryHandler : IRequestHandler<Get
.Where(x => request.Filter.UserId == null || x.Wallet.UserId == request.Filter.UserId)
;
}
return new GetAllUserWalletChangeLogByFilterResponseDto
return new GetAllUserWalletHistoryByFilterResponseDto
{
MetaData = await query.GetMetaData(request.PaginationState, cancellationToken),
Models = await query.PaginatedListAsync(paginationState: request.PaginationState)
.ProjectToType<GetAllUserWalletChangeLogByFilterResponseModel>().ToListAsync(cancellationToken)
.ProjectToType<GetAllUserWalletHistoryByFilterResponseModel>().ToListAsync(cancellationToken)
};
}
}
@@ -0,0 +1,14 @@
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Queries.GetAllUserWalletHistoryByFilter;
public class GetAllUserWalletHistoryByFilterQueryValidator : AbstractValidator<GetAllUserWalletHistoryByFilterQuery>
{
public GetAllUserWalletHistoryByFilterQueryValidator()
{
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<GetAllUserWalletHistoryByFilterQuery>.CreateWithOptions((GetAllUserWalletHistoryByFilterQuery)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
};
}
@@ -1,12 +1,12 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Queries.GetAllUserWalletChangeLogByFilter;
public class GetAllUserWalletChangeLogByFilterResponseDto
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Queries.GetAllUserWalletHistoryByFilter;
public class GetAllUserWalletHistoryByFilterResponseDto
{
//متادیتا
public MetaData MetaData { get; set; }
//مدل خروجی
public List<GetAllUserWalletChangeLogByFilterResponseModel>? Models { get; set; }
public List<GetAllUserWalletHistoryByFilterResponseModel>? Models { get; set; }
}public class GetAllUserWalletChangeLogByFilterResponseModel
}public class GetAllUserWalletHistoryByFilterResponseModel
{
//شناسه
public long Id { get; set; }
@@ -0,0 +1,7 @@
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Queries.GetUserWalletHistory;
public record GetUserWalletHistoryQuery : IRequest<GetUserWalletHistoryResponseDto>
{
//شناسه
public long Id { get; init; }
}
@@ -0,0 +1,22 @@
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Queries.GetUserWalletHistory;
public class GetUserWalletHistoryQueryHandler : IRequestHandler<GetUserWalletHistoryQuery, GetUserWalletHistoryResponseDto>
{
private readonly IApplicationDbContext _context;
public GetUserWalletHistoryQueryHandler(IApplicationDbContext context)
{
_context = context;
}
public async Task<GetUserWalletHistoryResponseDto> Handle(GetUserWalletHistoryQuery request,
CancellationToken cancellationToken)
{
var response = await _context.UserWalletHistories
.AsNoTracking()
.Where(x => x.Id == request.Id)
.ProjectToType<GetUserWalletHistoryResponseDto>()
.FirstOrDefaultAsync(cancellationToken);
return response ?? throw new NotFoundException(nameof(UserWalletHistory), request.Id);
}
}
@@ -1,14 +1,14 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Queries.GetUserWalletChangeLog;
public class GetUserWalletChangeLogQueryValidator : AbstractValidator<GetUserWalletChangeLogQuery>
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Queries.GetUserWalletHistory;
public class GetUserWalletHistoryQueryValidator : AbstractValidator<GetUserWalletHistoryQuery>
{
public GetUserWalletChangeLogQueryValidator()
public GetUserWalletHistoryQueryValidator()
{
RuleFor(model => model.Id)
.NotNull();
}
public Func<object, string, Task<IEnumerable<string>>> ValidateValue => async (model, propertyName) =>
{
var result = await ValidateAsync(ValidationContext<GetUserWalletChangeLogQuery>.CreateWithOptions((GetUserWalletChangeLogQuery)model, x => x.IncludeProperties(propertyName)));
var result = await ValidateAsync(ValidationContext<GetUserWalletHistoryQuery>.CreateWithOptions((GetUserWalletHistoryQuery)model, x => x.IncludeProperties(propertyName)));
if (result.IsValid)
return Array.Empty<string>();
return result.Errors.Select(e => e.ErrorMessage);
@@ -1,5 +1,5 @@
namespace CMSMicroservice.Application.UserWalletChangeLogCQ.Queries.GetUserWalletChangeLog;
public class GetUserWalletChangeLogResponseDto
namespace CMSMicroservice.Application.UserWalletHistoryCQ.Queries.GetUserWalletHistory;
public class GetUserWalletHistoryResponseDto
{
//شناسه
public long Id { get; set; }
@@ -115,7 +115,7 @@ public class VerifyDiscountWalletChargeCommandHandler
await _context.SaveChangesAsync(cancellationToken);
// ثبت لاگ تغییرات کیف پول (بعد از ایجاد Transaction برای داشتن TransactionId)
_context.UserWalletChangeLogs.Add(new Domain.Entities.UserWalletChangeLog
_context.UserWalletHistories.Add(new Domain.Entities.UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -167,8 +167,8 @@ public class VerifyMagicWalletChargeCommandHandler
wallet.MagicTotalDeposited += depositAmount;
wallet.MagicTotalCredited += creditAmount;
// 9. ثبت WalletChangeLog (اجباری)
var walletLog = new UserWalletChangeLog
// 9. ثبت WalletHistory (اجباری)
var walletLog = new UserWalletHistory
{
WalletId = wallet.Id,
CurrentBalance = wallet.Balance,
@@ -181,7 +181,7 @@ public class VerifyMagicWalletChargeCommandHandler
RefrenceId = depositTransaction.Id
};
_context.UserWalletChangeLogs.Add(walletLog);
_context.UserWalletHistories.Add(walletLog);
// 10. لینک PaymentTransaction به Transaction داخلی
paymentTx.TransactionId = depositTransaction.Id;