feat: 新增租户审核领取和审核日志接口
- 新增 TenantReviewClaim 和 TenantAuditLog 实体 - 新增 TenantAuditAction 枚举 - 新增审核领取相关接口:GET/POST /review/claim, /review/force-claim, /review/release - 新增审核日志接口:GET /audits - 更新 ITenantRepository 和 EfTenantRepository - 更新 TakeoutAppDbContext 添加 DbSet Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,103 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using TakeoutSaaS.Application.App.Tenants.Commands;
|
||||
using TakeoutSaaS.Application.App.Tenants.Contracts;
|
||||
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,
|
||||
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;
|
||||
var actorName = currentUserAccessor.IsAuthenticated
|
||||
? $"user:{currentUserAccessor.UserId}"
|
||||
: "system";
|
||||
|
||||
var claim = new TenantReviewClaim
|
||||
{
|
||||
Id = idGenerator.NextId(),
|
||||
TenantId = request.TenantId,
|
||||
ClaimedBy = currentUserAccessor.UserId,
|
||||
ClaimedByName = actorName,
|
||||
ClaimedAt = now
|
||||
};
|
||||
|
||||
// 7. 保存领取记录
|
||||
await tenantRepository.AddReviewClaimAsync(claim, cancellationToken);
|
||||
|
||||
// 8. 添加审核日志
|
||||
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);
|
||||
|
||||
// 9. 保存变更
|
||||
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
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user