feat: enhance club membership activation with pool and features
This commit is contained in:
+177
-12
@@ -1,5 +1,9 @@
|
|||||||
using CMSMicroservice.Application.Common.Exceptions;
|
using CMSMicroservice.Application.Common.Exceptions;
|
||||||
|
using CMSMicroservice.Application.Common.Interfaces;
|
||||||
using CMSMicroservice.Domain.Entities;
|
using CMSMicroservice.Domain.Entities;
|
||||||
|
using CMSMicroservice.Domain.Entities.Club;
|
||||||
|
using CMSMicroservice.Domain.Entities.Commission;
|
||||||
|
using CMSMicroservice.Domain.Entities.History;
|
||||||
using CMSMicroservice.Domain.Enums;
|
using CMSMicroservice.Domain.Enums;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -12,6 +16,8 @@ namespace CMSMicroservice.Application.ClubMembershipCQ.Commands.AcceptClubMember
|
|||||||
/// 1. کد OTP را تایید میکند
|
/// 1. کد OTP را تایید میکند
|
||||||
/// 2. قرارداد را در جدول UserContract ثبت میکند
|
/// 2. قرارداد را در جدول UserContract ثبت میکند
|
||||||
/// 3. باشگاه مشتری را فعال میکند (IsActive = true)
|
/// 3. باشگاه مشتری را فعال میکند (IsActive = true)
|
||||||
|
/// 4. مبلغ را به Pool هفته جاری اضافه میکند
|
||||||
|
/// 5. ویژگیهای باشگاه را به کاربر اعطا میکند
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class AcceptClubMembershipContractCommandHandler
|
public class AcceptClubMembershipContractCommandHandler
|
||||||
: IRequestHandler<AcceptClubMembershipContractCommand, AcceptClubMembershipContractResponseDto>
|
: IRequestHandler<AcceptClubMembershipContractCommand, AcceptClubMembershipContractResponseDto>
|
||||||
@@ -19,6 +25,8 @@ public class AcceptClubMembershipContractCommandHandler
|
|||||||
private readonly IApplicationDbContext _context;
|
private readonly IApplicationDbContext _context;
|
||||||
private readonly IConfiguration _cfg;
|
private readonly IConfiguration _cfg;
|
||||||
private readonly IHashService _hashService;
|
private readonly IHashService _hashService;
|
||||||
|
private readonly ICurrentUserService _currentUser;
|
||||||
|
private readonly IWeekDefinitionRepository _weekRepository;
|
||||||
private readonly ILogger<AcceptClubMembershipContractCommandHandler> _logger;
|
private readonly ILogger<AcceptClubMembershipContractCommandHandler> _logger;
|
||||||
|
|
||||||
private const int MaxAttempts = 5;
|
private const int MaxAttempts = 5;
|
||||||
@@ -28,11 +36,15 @@ public class AcceptClubMembershipContractCommandHandler
|
|||||||
IApplicationDbContext context,
|
IApplicationDbContext context,
|
||||||
IConfiguration cfg,
|
IConfiguration cfg,
|
||||||
IHashService hashService,
|
IHashService hashService,
|
||||||
|
ICurrentUserService currentUser,
|
||||||
|
IWeekDefinitionRepository weekRepository,
|
||||||
ILogger<AcceptClubMembershipContractCommandHandler> logger)
|
ILogger<AcceptClubMembershipContractCommandHandler> logger)
|
||||||
{
|
{
|
||||||
_context = context;
|
_context = context;
|
||||||
_cfg = cfg;
|
_cfg = cfg;
|
||||||
_hashService = hashService;
|
_hashService = hashService;
|
||||||
|
_currentUser = currentUser;
|
||||||
|
_weekRepository = weekRepository;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,33 +126,173 @@ public class AcceptClubMembershipContractCommandHandler
|
|||||||
};
|
};
|
||||||
await _context.UserContracts.AddAsync(userContract, cancellationToken);
|
await _context.UserContracts.AddAsync(userContract, cancellationToken);
|
||||||
|
|
||||||
// 6. فعالسازی باشگاه مشتریان
|
// 6. دریافت مقادیر از تنظیمات سیستم
|
||||||
if (user.ClubMembership == null)
|
var giftValueConfig = await _context.SystemConfigurations
|
||||||
|
.FirstOrDefaultAsync(
|
||||||
|
c => c.Key == "Club.MembershipGiftValue" && c.IsActive,
|
||||||
|
cancellationToken
|
||||||
|
);
|
||||||
|
|
||||||
|
var activationFeeConfig = await _context.SystemConfigurations
|
||||||
|
.FirstOrDefaultAsync(
|
||||||
|
c => c.Key == "Club.ActivationFee" && c.IsActive,
|
||||||
|
cancellationToken
|
||||||
|
);
|
||||||
|
|
||||||
|
long giftValue = 28_000_000; // مقدار پیشفرض
|
||||||
|
if (giftValueConfig != null && long.TryParse(giftValueConfig.Value, out var configValue))
|
||||||
{
|
{
|
||||||
user.ClubMembership = new Domain.Entities.Club.ClubMembership
|
giftValue = configValue;
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Using Club.MembershipGiftValue from configuration: {GiftValue}",
|
||||||
|
giftValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
long activationFeeValue = 25_200_000; // مقدار پیشفرض
|
||||||
|
if (activationFeeConfig != null && long.TryParse(activationFeeConfig.Value, out var activationFeeConfigValue))
|
||||||
|
{
|
||||||
|
activationFeeValue = activationFeeConfigValue;
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Using Club.ActivationFee from configuration: {activationFeeValue}",
|
||||||
|
activationFeeValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 7. فعالسازی باشگاه مشتریان
|
||||||
|
ClubMembership clubMembership;
|
||||||
|
bool isNewMembership = user.ClubMembership == null;
|
||||||
|
var activationDate = DateTime.Now;
|
||||||
|
|
||||||
|
if (isNewMembership)
|
||||||
|
{
|
||||||
|
clubMembership = new ClubMembership
|
||||||
{
|
{
|
||||||
UserId = user.Id,
|
UserId = user.Id,
|
||||||
IsActive = true,
|
IsActive = true,
|
||||||
ActivatedAt = DateTime.Now,
|
ActivatedAt = activationDate,
|
||||||
InitialContribution = 56_000_000,
|
InitialContribution = activationFeeValue,
|
||||||
GiftValue = 25_200_000,
|
GiftValue = giftValue,
|
||||||
|
TotalEarned = 0,
|
||||||
PurchaseMethod = user.PackagePurchaseMethod
|
PurchaseMethod = user.PackagePurchaseMethod
|
||||||
};
|
};
|
||||||
await _context.ClubMemberships.AddAsync(user.ClubMembership, cancellationToken);
|
await _context.ClubMemberships.AddAsync(clubMembership, cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Created new club membership for UserId {UserId} via {Method}, GiftValue: {GiftValue}",
|
||||||
|
user.Id,
|
||||||
|
user.PackagePurchaseMethod,
|
||||||
|
giftValue
|
||||||
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
user.ClubMembership.IsActive = true;
|
clubMembership = user.ClubMembership!;
|
||||||
user.ClubMembership.ActivatedAt = DateTime.Now;
|
clubMembership.IsActive = true;
|
||||||
_context.ClubMemberships.Update(user.ClubMembership);
|
clubMembership.ActivatedAt = activationDate;
|
||||||
|
clubMembership.PurchaseMethod = user.PackagePurchaseMethod;
|
||||||
|
_context.ClubMemberships.Update(clubMembership);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Reactivated club membership for UserId {UserId}",
|
||||||
|
user.Id
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await _context.SaveChangesAsync(cancellationToken);
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
// 8. ثبت تاریخچه
|
||||||
|
var history = new ClubMembershipHistory
|
||||||
|
{
|
||||||
|
ClubMembershipId = clubMembership.Id,
|
||||||
|
UserId = clubMembership.UserId,
|
||||||
|
OldIsActive = !isNewMembership && !user.ClubMembership!.IsActive,
|
||||||
|
NewIsActive = true,
|
||||||
|
Action = ClubMembershipAction.Activated,
|
||||||
|
Reason = isNewMembership
|
||||||
|
? $"Initial activation via contract signing - {user.PackagePurchaseMethod}"
|
||||||
|
: $"Reactivated via contract signing - {user.PackagePurchaseMethod}",
|
||||||
|
PerformedBy = _currentUser.GetPerformedBy()
|
||||||
|
};
|
||||||
|
|
||||||
|
_context.ClubMembershipHistories.Add(history);
|
||||||
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
// 9. اضافه کردن مبلغ به Pool هفته جاری
|
||||||
|
var currentWeekDefinitionId = GetCurrentWeekDefinitionId();
|
||||||
|
var weeklyPool = await _context.WeeklyCommissionPools
|
||||||
|
.FirstOrDefaultAsync(p => p.WeekDefinitionId == currentWeekDefinitionId, cancellationToken);
|
||||||
|
|
||||||
|
if (weeklyPool == null)
|
||||||
|
{
|
||||||
|
weeklyPool = new WeeklyCommissionPool
|
||||||
|
{
|
||||||
|
WeekDefinitionId = currentWeekDefinitionId,
|
||||||
|
TotalPoolAmount = activationFeeValue,
|
||||||
|
TotalBalances = 0,
|
||||||
|
ValuePerBalance = 0,
|
||||||
|
IsCalculated = false,
|
||||||
|
CalculatedAt = null
|
||||||
|
};
|
||||||
|
|
||||||
|
await _context.WeeklyCommissionPools.AddAsync(weeklyPool, cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Created new WeeklyCommissionPool for WeekDefinitionId={WeekDefinitionId} with initial amount: {Amount}",
|
||||||
|
currentWeekDefinitionId,
|
||||||
|
activationFeeValue
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
weeklyPool.TotalPoolAmount += activationFeeValue;
|
||||||
|
_context.WeeklyCommissionPools.Update(weeklyPool);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Added {Amount} to existing WeeklyCommissionPool for WeekDefinitionId={WeekDefinitionId}. New total: {NewTotal}",
|
||||||
|
activationFeeValue,
|
||||||
|
currentWeekDefinitionId,
|
||||||
|
weeklyPool.TotalPoolAmount
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
// 10. اعطای ویژگیهای باشگاه برای کاربر (فقط برای عضویت جدید)
|
||||||
|
if (isNewMembership)
|
||||||
|
{
|
||||||
|
var clubFeatures = await _context.ClubFeatures
|
||||||
|
.Where(f => !f.IsDeleted && new long[] { 1, 2, 3, 4 }.Contains(f.Id))
|
||||||
|
.ToListAsync(cancellationToken);
|
||||||
|
|
||||||
|
if (clubFeatures.Any())
|
||||||
|
{
|
||||||
|
var userClubFeatures = clubFeatures.Select(feature => new UserClubFeature
|
||||||
|
{
|
||||||
|
UserId = user.Id,
|
||||||
|
ClubMembershipId = clubMembership.Id,
|
||||||
|
ClubFeatureId = feature.Id,
|
||||||
|
GrantedAt = activationDate,
|
||||||
|
IsActive = true,
|
||||||
|
Notes = "اعطا شده هنگام امضای قرارداد"
|
||||||
|
}).ToList();
|
||||||
|
|
||||||
|
_context.UserClubFeatures.AddRange(userClubFeatures);
|
||||||
|
await _context.SaveChangesAsync(cancellationToken);
|
||||||
|
|
||||||
|
_logger.LogInformation(
|
||||||
|
"Granted {Count} club features to UserId {UserId}",
|
||||||
|
clubFeatures.Count,
|
||||||
|
user.Id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_logger.LogInformation(
|
_logger.LogInformation(
|
||||||
"Club membership contract accepted and activated for UserId: {UserId}, ContractId: {ContractId}",
|
"Club membership contract accepted and activated for UserId: {UserId}, ContractId: {ContractId}, MembershipId: {MembershipId}",
|
||||||
request.UserId,
|
request.UserId,
|
||||||
userContract.Id
|
userContract.Id,
|
||||||
|
clubMembership.Id
|
||||||
);
|
);
|
||||||
|
|
||||||
return new AcceptClubMembershipContractResponseDto
|
return new AcceptClubMembershipContractResponseDto
|
||||||
@@ -151,6 +303,19 @@ public class AcceptClubMembershipContractCommandHandler
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// دریافت شناسه تعریف هفته جاری
|
||||||
|
/// </summary>
|
||||||
|
private long GetCurrentWeekDefinitionId()
|
||||||
|
{
|
||||||
|
var week = _weekRepository.GetCurrentWeek();
|
||||||
|
if (week == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("هفته جاری در سیستم تعریف نشده است");
|
||||||
|
}
|
||||||
|
return week.Id;
|
||||||
|
}
|
||||||
|
|
||||||
private async Task<(bool Success, string Message)> VerifyOtpAsync(
|
private async Task<(bool Success, string Message)> VerifyOtpAsync(
|
||||||
string mobile,
|
string mobile,
|
||||||
string code,
|
string code,
|
||||||
|
|||||||
Reference in New Issue
Block a user