using MediatR; using TakeoutSaaS.Application.App.Billings.Commands; using TakeoutSaaS.Application.App.Billings.Dto; using TakeoutSaaS.Domain.Tenants.Repositories; using TakeoutSaaS.Shared.Abstractions.Constants; using TakeoutSaaS.Shared.Abstractions.Exceptions; using TakeoutSaaS.Shared.Abstractions.Security; namespace TakeoutSaaS.Application.App.Billings.Handlers; /// /// 审核支付命令处理器。 /// public sealed class VerifyPaymentCommandHandler( ITenantPaymentRepository paymentRepository, ITenantBillingRepository billingRepository, ICurrentUserAccessor currentUserAccessor) : IRequestHandler { /// public async Task Handle(VerifyPaymentCommand request, CancellationToken cancellationToken) { // 1. 校验操作者身份 if (!currentUserAccessor.IsAuthenticated || currentUserAccessor.UserId <= 0) { throw new BusinessException(ErrorCodes.Unauthorized, "未登录或无效的操作者身份"); } // 2. 查询支付记录 var payment = await paymentRepository.FindByIdAsync(request.PaymentId, cancellationToken); if (payment is null) { throw new BusinessException(ErrorCodes.NotFound, "支付记录不存在"); } // 3. 查询关联账单 var billing = await billingRepository.FindByIdAsync(payment.BillingStatementId, cancellationToken); if (billing is null) { throw new BusinessException(ErrorCodes.NotFound, "关联账单不存在"); } // 4. 归一化审核备注 var normalizedNotes = string.IsNullOrWhiteSpace(request.Notes) ? null : request.Notes.Trim(); // 5. 根据审核结果更新支付与账单状态 if (request.Approved) { payment.Verify(currentUserAccessor.UserId); payment.Notes = normalizedNotes; billing.MarkAsPaid(payment.Amount, payment.TransactionNo ?? string.Empty); } else { payment.Reject(currentUserAccessor.UserId, normalizedNotes ?? string.Empty); payment.Notes = normalizedNotes; } // 6. 持久化更新状态 await paymentRepository.UpdateAsync(payment, cancellationToken); if (request.Approved) { await billingRepository.UpdateAsync(billing, cancellationToken); } // 7. 保存数据库更改 await paymentRepository.SaveChangesAsync(cancellationToken); // 8. 返回 DTO return payment.ToPaymentRecordDto(); } }