using MediatR; using TakeoutSaaS.Application.App.Merchants.Commands; using TakeoutSaaS.Application.App.Merchants.Dto; using TakeoutSaaS.Domain.Merchants.Entities; using TakeoutSaaS.Domain.Merchants.Enums; using TakeoutSaaS.Domain.Merchants.Repositories; using TakeoutSaaS.Shared.Abstractions.Constants; using TakeoutSaaS.Shared.Abstractions.Exceptions; using TakeoutSaaS.Shared.Abstractions.Security; using TakeoutSaaS.Shared.Abstractions.Tenancy; namespace TakeoutSaaS.Application.App.Merchants.Handlers; /// /// 商户审核处理器。 /// public sealed class ReviewMerchantCommandHandler( IMerchantRepository merchantRepository, ITenantProvider tenantProvider, ICurrentUserAccessor currentUserAccessor) : IRequestHandler { public async Task Handle(ReviewMerchantCommand request, CancellationToken cancellationToken) { // 1. 读取商户 var tenantId = tenantProvider.GetCurrentTenantId(); var merchant = await merchantRepository.FindByIdAsync(request.MerchantId, tenantId, cancellationToken) ?? throw new BusinessException(ErrorCodes.NotFound, "商户不存在"); // 2. 已审核通过则直接返回 if (request.Approve && merchant.Status == MerchantStatus.Approved) { return MerchantMapping.ToDto(merchant); } // 3. 更新审核状态 var previousStatus = merchant.Status; merchant.Status = request.Approve ? MerchantStatus.Approved : MerchantStatus.Rejected; merchant.ReviewRemarks = request.Remarks; merchant.LastReviewedAt = DateTime.UtcNow; if (request.Approve && merchant.JoinedAt == null) { merchant.JoinedAt = DateTime.UtcNow; } // 4. 持久化与审计 await merchantRepository.UpdateMerchantAsync(merchant, cancellationToken); await merchantRepository.AddAuditLogAsync(new MerchantAuditLog { TenantId = tenantId, MerchantId = merchant.Id, Action = MerchantAuditAction.MerchantReviewed, Title = request.Approve ? "商户审核通过" : "商户审核驳回", Description = request.Remarks, OperatorId = ResolveOperatorId(), OperatorName = ResolveOperatorName() }, cancellationToken); await merchantRepository.SaveChangesAsync(cancellationToken); // 5. 返回 DTO return MerchantMapping.ToDto(merchant); } private long? ResolveOperatorId() { var id = currentUserAccessor.UserId; return id == 0 ? null : id; } private string ResolveOperatorName() { var id = currentUserAccessor.UserId; return id == 0 ? "system" : $"user:{id}"; } }