using MediatR; using TakeoutSaaS.Application.App.Tenants.Commands; using TakeoutSaaS.Application.App.Tenants.Dto; using TakeoutSaaS.Application.Identity.Abstractions; using TakeoutSaaS.Domain.Tenants.Entities; using TakeoutSaaS.Domain.Tenants.Enums; using TakeoutSaaS.Domain.Tenants.Repositories; using TakeoutSaaS.Shared.Abstractions.Constants; using TakeoutSaaS.Shared.Abstractions.Exceptions; using TakeoutSaaS.Shared.Abstractions.Security; namespace TakeoutSaaS.Application.App.Tenants.Handlers; /// /// 释放租户入驻审核领取处理器。 /// public sealed class ReleaseTenantReviewClaimCommandHandler( ITenantRepository tenantRepository, ICurrentUserAccessor currentUserAccessor, IAdminAuthService adminAuthService) : IRequestHandler { /// public async Task Handle(ReleaseTenantReviewClaimCommand request, CancellationToken cancellationToken) { // 1. 校验租户存在 var tenant = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken) ?? throw new BusinessException(ErrorCodes.NotFound, "租户不存在"); // 2. 查询当前领取记录 var claim = await tenantRepository.FindActiveReviewClaimAsync(request.TenantId, cancellationToken); if (claim == null) { return null; } // 3. (空行后) 非领取人不允许释放(如需接管请使用强制接管) if (claim.ClaimedBy != currentUserAccessor.UserId) { throw new BusinessException(ErrorCodes.Conflict, $"该审核已被 {claim.ClaimedByName} 领取"); } // 4. (空行后) 释放领取并记录审计 var profile = await adminAuthService.GetProfileAsync(currentUserAccessor.UserId, cancellationToken); var displayName = string.IsNullOrWhiteSpace(profile.DisplayName) ? $"user:{currentUserAccessor.UserId}" : profile.DisplayName; claim.ReleasedAt = DateTime.UtcNow; await tenantRepository.UpdateReviewClaimAsync(claim, cancellationToken); await tenantRepository.AddAuditLogAsync(new TenantAuditLog { TenantId = tenant.Id, Action = TenantAuditAction.ReviewClaimReleased, Title = "释放审核", Description = $"释放人:{displayName}", OperatorId = currentUserAccessor.UserId, OperatorName = displayName, PreviousStatus = tenant.Status, CurrentStatus = tenant.Status }, cancellationToken); await tenantRepository.SaveChangesAsync(cancellationToken); return claim.ToDto(); } }