using MediatR; using TakeoutSaaS.Application.App.Billings.Commands; using TakeoutSaaS.Application.App.Billings.Contracts; using TakeoutSaaS.Domain.Billings.Entities; using TakeoutSaaS.Domain.Billings.Enums; using TakeoutSaaS.Domain.Billings.Repositories; using TakeoutSaaS.Shared.Abstractions.Security; namespace TakeoutSaaS.Application.App.Billings.Handlers; /// /// 确认收款命令处理器。 /// public sealed class ConfirmPaymentCommandHandler( IBillingRepository billingRepository, ICurrentUserAccessor currentUserAccessor) : IRequestHandler { /// public async Task Handle( ConfirmPaymentCommand request, CancellationToken cancellationToken) { // 1. 获取账单(带跟踪) var billing = await billingRepository.GetByIdForUpdateAsync(request.BillingId, cancellationToken); // 2. 如果不存在,返回 null if (billing is null) { return null; } // 3. 获取当前用户 ID var currentUserId = currentUserAccessor.UserId; var now = DateTime.UtcNow; // 4. 创建支付记录(已审核通过状态) var payment = new TenantPayment { TenantId = billing.TenantId, BillingStatementId = billing.Id, Amount = request.Amount, Method = request.Method, Status = TenantPaymentStatus.Success, TransactionNo = request.TransactionNo, ProofUrl = request.ProofUrl, Notes = request.Notes, PaidAt = now, VerifiedBy = currentUserId, VerifiedAt = now, CreatedAt = now, CreatedBy = currentUserId }; // 5. 添加支付记录 await billingRepository.AddPaymentAsync(payment, cancellationToken); // 6. 更新账单已付金额 billing.AmountPaid += request.Amount; // 7. 如果已付金额 >= 应付金额,更新账单状态为已支付 if (billing.AmountPaid >= billing.AmountDue) { billing.Status = TenantBillingStatus.Paid; } // 8. 更新账单时间戳 billing.UpdatedAt = now; // 9. 保存变更 await billingRepository.SaveChangesAsync(cancellationToken); // 10. 返回支付记录 DTO return new PaymentRecordDto { Id = payment.Id, BillingStatementId = payment.BillingStatementId, Amount = payment.Amount, Method = (int)payment.Method, Status = (int)payment.Status, TransactionNo = payment.TransactionNo, ProofUrl = payment.ProofUrl, PaidAt = payment.PaidAt, Notes = payment.Notes, VerifiedBy = payment.VerifiedBy, VerifiedAt = payment.VerifiedAt, RefundReason = payment.RefundReason, RefundedAt = payment.RefundedAt, CreatedAt = payment.CreatedAt }; } }