feat: Implement Approve and Reject Withdrawal commands with handlers
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
namespace CMSMicroservice.Application.CommissionCQ.Commands.ApproveWithdrawal;
|
||||
|
||||
public class ApproveWithdrawalCommand : IRequest<Unit>
|
||||
{
|
||||
public long PayoutId { get; set; }
|
||||
public string? Notes { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
using CMSMicroservice.Application.Common.Exceptions;
|
||||
|
||||
namespace CMSMicroservice.Application.CommissionCQ.Commands.ApproveWithdrawal;
|
||||
|
||||
public class ApproveWithdrawalCommandHandler : IRequestHandler<ApproveWithdrawalCommand, Unit>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public ApproveWithdrawalCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<Unit> Handle(ApproveWithdrawalCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var payout = await _context.UserCommissionPayouts
|
||||
.FirstOrDefaultAsync(x => x.Id == request.PayoutId, cancellationToken);
|
||||
|
||||
if (payout == null)
|
||||
{
|
||||
throw new NotFoundException($"Payout با شناسه {request.PayoutId} یافت نشد");
|
||||
}
|
||||
|
||||
if (payout.Status != CommissionPayoutStatus.WithdrawRequested)
|
||||
{
|
||||
throw new BadRequestException($"فقط درخواستهای در وضعیت WithdrawRequested قابل تایید هستند");
|
||||
}
|
||||
|
||||
// Update status to Withdrawn (approved)
|
||||
payout.Status = CommissionPayoutStatus.Withdrawn;
|
||||
payout.WithdrawnAt = DateTime.UtcNow;
|
||||
payout.LastModified = DateTime.UtcNow;
|
||||
|
||||
// TODO: Add PayoutHistory record
|
||||
// var history = new CommissionPayoutHistory
|
||||
// {
|
||||
// PayoutId = payout.Id,
|
||||
// UserId = payout.UserId,
|
||||
// WeekNumber = payout.WeekNumber,
|
||||
// AmountBefore = payout.TotalAmount,
|
||||
// AmountAfter = payout.TotalAmount,
|
||||
// OldStatus = (int)CommissionPayoutStatus.Pending,
|
||||
// NewStatus = (int)CommissionPayoutStatus.Approved,
|
||||
// Action = (int)CommissionPayoutAction.Approved,
|
||||
// PerformedBy = "Admin", // TODO: Get from authenticated user
|
||||
// Reason = request.Notes,
|
||||
// Created = DateTime.UtcNow
|
||||
// };
|
||||
// _context.CommissionPayoutHistories.Add(history);
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
return Unit.Value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace CMSMicroservice.Application.CommissionCQ.Commands.RejectWithdrawal;
|
||||
|
||||
public class RejectWithdrawalCommand : IRequest<Unit>
|
||||
{
|
||||
public long PayoutId { get; set; }
|
||||
public string Reason { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
using CMSMicroservice.Domain.Enums;
|
||||
using CMSMicroservice.Application.Common.Exceptions;
|
||||
|
||||
namespace CMSMicroservice.Application.CommissionCQ.Commands.RejectWithdrawal;
|
||||
|
||||
public class RejectWithdrawalCommandHandler : IRequestHandler<RejectWithdrawalCommand, Unit>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
|
||||
public RejectWithdrawalCommandHandler(IApplicationDbContext context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public async Task<Unit> Handle(RejectWithdrawalCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
var payout = await _context.UserCommissionPayouts
|
||||
.FirstOrDefaultAsync(x => x.Id == request.PayoutId, cancellationToken);
|
||||
|
||||
if (payout == null)
|
||||
{
|
||||
throw new NotFoundException($"Payout با شناسه {request.PayoutId} یافت نشد");
|
||||
}
|
||||
|
||||
if (payout.Status != CommissionPayoutStatus.WithdrawRequested)
|
||||
{
|
||||
throw new BadRequestException($"فقط درخواستهای در وضعیت WithdrawRequested قابل رد هستند");
|
||||
}
|
||||
|
||||
// Update status to Cancelled (rejected)
|
||||
payout.Status = CommissionPayoutStatus.Cancelled;
|
||||
payout.LastModified = DateTime.UtcNow;
|
||||
|
||||
// TODO: Add PayoutHistory record with rejection reason
|
||||
// var history = new CommissionPayoutHistory
|
||||
// {
|
||||
// PayoutId = payout.Id,
|
||||
// UserId = payout.UserId,
|
||||
// WeekNumber = payout.WeekNumber,
|
||||
// AmountBefore = payout.TotalAmount,
|
||||
// AmountAfter = payout.TotalAmount,
|
||||
// OldStatus = (int)CommissionPayoutStatus.Pending,
|
||||
// NewStatus = (int)CommissionPayoutStatus.Rejected,
|
||||
// Action = (int)CommissionPayoutAction.Rejected,
|
||||
// PerformedBy = "Admin", // TODO: Get from authenticated user
|
||||
// Reason = request.Reason,
|
||||
// Created = DateTime.UtcNow
|
||||
// };
|
||||
// _context.CommissionPayoutHistories.Add(history);
|
||||
|
||||
await _context.SaveChangesAsync(cancellationToken);
|
||||
return Unit.Value;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
namespace CMSMicroservice.Application.CommissionCQ.Commands.TriggerWeeklyCalculation;
|
||||
|
||||
public record TriggerWeeklyCalculationCommand : IRequest<TriggerWeeklyCalculationResponseDto>
|
||||
{
|
||||
/// <summary>
|
||||
/// شماره هفته (فرمت: "YYYY-Www")
|
||||
/// </summary>
|
||||
public string WeekNumber { get; init; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// اگر true باشد، محاسبات قبلی را حذف و دوباره محاسبه میکند
|
||||
/// </summary>
|
||||
public bool ForceRecalculate { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Skip balance calculation
|
||||
/// </summary>
|
||||
public bool SkipBalances { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Skip pool calculation
|
||||
/// </summary>
|
||||
public bool SkipPool { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Skip payout processing
|
||||
/// </summary>
|
||||
public bool SkipPayouts { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
using CMSMicroservice.Application.Common.Interfaces;
|
||||
using CMSMicroservice.Application.CommissionCQ.Commands.CalculateWeeklyBalances;
|
||||
using CMSMicroservice.Application.CommissionCQ.Commands.CalculateWeeklyCommissionPool;
|
||||
using CMSMicroservice.Application.CommissionCQ.Commands.ProcessUserPayouts;
|
||||
|
||||
namespace CMSMicroservice.Application.CommissionCQ.Commands.TriggerWeeklyCalculation;
|
||||
|
||||
public class TriggerWeeklyCalculationCommandHandler : IRequestHandler<TriggerWeeklyCalculationCommand, TriggerWeeklyCalculationResponseDto>
|
||||
{
|
||||
private readonly IApplicationDbContext _context;
|
||||
private readonly IMediator _mediator;
|
||||
|
||||
public TriggerWeeklyCalculationCommandHandler(
|
||||
IApplicationDbContext context,
|
||||
IMediator mediator)
|
||||
{
|
||||
_context = context;
|
||||
_mediator = mediator;
|
||||
}
|
||||
|
||||
public async Task<TriggerWeeklyCalculationResponseDto> Handle(
|
||||
TriggerWeeklyCalculationCommand request,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
var executionId = Guid.NewGuid().ToString();
|
||||
var startedAt = DateTime.UtcNow;
|
||||
|
||||
try
|
||||
{
|
||||
// Validate week number format
|
||||
if (string.IsNullOrWhiteSpace(request.WeekNumber))
|
||||
{
|
||||
return new TriggerWeeklyCalculationResponseDto
|
||||
{
|
||||
Success = false,
|
||||
Message = "شماره هفته نمیتواند خالی باشد",
|
||||
ExecutionId = executionId,
|
||||
StartedAt = startedAt
|
||||
};
|
||||
}
|
||||
|
||||
var steps = new List<string>();
|
||||
|
||||
// Step 1: Calculate Weekly Balances
|
||||
if (!request.SkipBalances)
|
||||
{
|
||||
await _mediator.Send(new CalculateWeeklyBalancesCommand
|
||||
{
|
||||
WeekNumber = request.WeekNumber,
|
||||
ForceRecalculate = request.ForceRecalculate
|
||||
}, cancellationToken);
|
||||
steps.Add("محاسبه امتیازات هفتگی");
|
||||
}
|
||||
|
||||
// Step 2: Calculate Weekly Commission Pool
|
||||
if (!request.SkipPool)
|
||||
{
|
||||
await _mediator.Send(new CalculateWeeklyCommissionPoolCommand
|
||||
{
|
||||
WeekNumber = request.WeekNumber
|
||||
}, cancellationToken);
|
||||
steps.Add("محاسبه استخر کمیسیون");
|
||||
}
|
||||
|
||||
// Step 3: Process User Payouts
|
||||
if (!request.SkipPayouts)
|
||||
{
|
||||
await _mediator.Send(new ProcessUserPayoutsCommand
|
||||
{
|
||||
WeekNumber = request.WeekNumber,
|
||||
ForceReprocess = request.ForceRecalculate
|
||||
}, cancellationToken);
|
||||
steps.Add("پردازش پرداختهای کاربران");
|
||||
}
|
||||
|
||||
return new TriggerWeeklyCalculationResponseDto
|
||||
{
|
||||
Success = true,
|
||||
Message = $"محاسبات هفته {request.WeekNumber} با موفقیت انجام شد. مراحل: {string.Join(", ", steps)}",
|
||||
ExecutionId = executionId,
|
||||
StartedAt = startedAt
|
||||
};
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
return new TriggerWeeklyCalculationResponseDto
|
||||
{
|
||||
Success = false,
|
||||
Message = $"خطا در اجرای محاسبات: {ex.Message}",
|
||||
ExecutionId = executionId,
|
||||
StartedAt = startedAt
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace CMSMicroservice.Application.CommissionCQ.Commands.TriggerWeeklyCalculation;
|
||||
|
||||
public class TriggerWeeklyCalculationResponseDto
|
||||
{
|
||||
public bool Success { get; set; }
|
||||
public string Message { get; set; } = string.Empty;
|
||||
public string ExecutionId { get; set; } = string.Empty;
|
||||
public DateTime StartedAt { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user