Files
TakeoutSaaS.AdminApi/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/ClaimTenantReviewCommandHandler.cs
MSuMshk cfb20ca0d7 fix: 审核领取显示用户真实姓名而非 ID
- ClaimTenantReviewCommandHandler 通过 IIdentityUserRepository 查询用户 DisplayName
- ForceClaimTenantReviewCommandHandler 同步修改
- ReleaseTenantReviewClaimCommandHandler 同步修改

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 20:54:14 +08:00

111 lines
4.1 KiB
C#

using MediatR;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Application.App.Tenants.Commands;
using TakeoutSaaS.Application.App.Tenants.Contracts;
using TakeoutSaaS.Domain.Identity.Repositories;
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.Ids;
using TakeoutSaaS.Shared.Abstractions.Security;
namespace TakeoutSaaS.Application.App.Tenants.Handlers;
/// <summary>
/// 领取租户审核命令处理器。
/// </summary>
public sealed class ClaimTenantReviewCommandHandler(
ITenantRepository tenantRepository,
IIdentityUserRepository identityUserRepository,
ICurrentUserAccessor currentUserAccessor,
IIdGenerator idGenerator,
ILogger<ClaimTenantReviewCommandHandler> logger)
: IRequestHandler<ClaimTenantReviewCommand, TenantReviewClaimDto>
{
/// <inheritdoc />
public async Task<TenantReviewClaimDto> Handle(ClaimTenantReviewCommand request, CancellationToken cancellationToken)
{
// 1. 校验租户是否存在
var tenant = await tenantRepository.FindByIdAsync(request.TenantId, cancellationToken);
if (tenant is null)
{
throw new BusinessException(ErrorCodes.NotFound, "租户不存在");
}
// 2. 校验租户状态(只有待审核状态才能领取)
if (tenant.Status != TenantStatus.PendingReview)
{
throw new BusinessException(ErrorCodes.BadRequest, "租户不在待审核状态,无法领取审核");
}
// 3. 检查是否已被领取
var existingClaim = await tenantRepository.GetActiveReviewClaimAsync(request.TenantId, cancellationToken);
if (existingClaim is not null)
{
// 4. 如果是自己领取的,直接返回
if (existingClaim.ClaimedBy == currentUserAccessor.UserId)
{
return ToDto(existingClaim);
}
// 5. 已被他人领取
throw new BusinessException(ErrorCodes.Conflict, $"该审核已被 {existingClaim.ClaimedByName} 领取");
}
// 6. 创建新的领取记录
var now = DateTime.UtcNow;
// 7. 查询当前用户的显示名称
var actorName = "system";
if (currentUserAccessor.IsAuthenticated && currentUserAccessor.UserId != 0)
{
var user = await identityUserRepository.FindByIdAsync(currentUserAccessor.UserId, cancellationToken);
actorName = user?.DisplayName ?? $"用户{currentUserAccessor.UserId}";
}
var claim = new TenantReviewClaim
{
Id = idGenerator.NextId(),
TenantId = request.TenantId,
ClaimedBy = currentUserAccessor.UserId,
ClaimedByName = actorName,
ClaimedAt = now
};
// 8. 保存领取记录
await tenantRepository.AddReviewClaimAsync(claim, cancellationToken);
// 9. 添加审核日志
await tenantRepository.AddAuditLogAsync(new TenantAuditLog
{
Id = idGenerator.NextId(),
TenantId = request.TenantId,
Action = TenantAuditAction.ReviewClaimed,
Title = "领取审核",
Description = $"领取人:{actorName}",
OperatorId = currentUserAccessor.UserId,
OperatorName = actorName,
CurrentStatus = tenant.Status
}, cancellationToken);
// 10. 保存变更
await tenantRepository.SaveChangesAsync(cancellationToken);
logger.LogInformation("租户 {TenantId} 审核已被 {UserId} 领取", request.TenantId, currentUserAccessor.UserId);
return ToDto(claim);
}
private static TenantReviewClaimDto ToDto(TenantReviewClaim claim)
=> new()
{
Id = claim.Id,
TenantId = claim.TenantId,
ClaimedBy = claim.ClaimedBy,
ClaimedByName = claim.ClaimedByName,
ClaimedAt = claim.ClaimedAt
};
}