refactor: 删除旧的 approve/reject 接口,统一使用 /review

- 删除 PUT /approve 和 PUT /reject 接口
- 删除 ApproveTenantCommand/Handler
- 删除 RejectTenantCommand/Handler
- 保留统一的 POST /review 接口

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
MSuMshk
2026-02-02 21:07:30 +08:00
parent a55ebad675
commit 2c90aa6f5c
5 changed files with 0 additions and 243 deletions

View File

@@ -212,60 +212,6 @@ public sealed class TenantsController(IMediator mediator) : BaseApiController
return ApiResponse<PagedResult<TenantBillingListDto>>.Ok(result); return ApiResponse<PagedResult<TenantBillingListDto>>.Ok(result);
} }
/// <summary>
/// 审核通过租户。
/// </summary>
/// <param name="id">租户 ID雪花算法。</param>
/// <param name="command">审核通过命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>无内容。</returns>
[HttpPut("{id:long}/approve")]
[PermissionAuthorize("tenant:review")]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
public async Task<ApiResponse<object>> Approve(
long id,
[FromBody] ApproveTenantCommand command,
CancellationToken cancellationToken = default)
{
// 1. 确保路径参数与请求体一致
var updatedCommand = command with { TenantId = id.ToString() };
// 2. 执行命令
await mediator.Send(updatedCommand, cancellationToken);
// 3. 返回成功
return ApiResponse<object>.Ok(null, "审核通过");
}
/// <summary>
/// 审核驳回租户。
/// </summary>
/// <param name="id">租户 ID雪花算法。</param>
/// <param name="command">审核驳回命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>无内容。</returns>
[HttpPut("{id:long}/reject")]
[PermissionAuthorize("tenant:review")]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status200OK)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status400BadRequest)]
[ProducesResponseType(typeof(ApiResponse<object>), StatusCodes.Status404NotFound)]
public async Task<ApiResponse<object>> Reject(
long id,
[FromBody] RejectTenantCommand command,
CancellationToken cancellationToken = default)
{
// 1. 确保路径参数与请求体一致
var updatedCommand = command with { TenantId = id.ToString() };
// 2. 执行命令
await mediator.Send(updatedCommand, cancellationToken);
// 3. 返回成功
return ApiResponse<object>.Ok(null, "审核驳回");
}
/// <summary> /// <summary>
/// 审核租户(统一接口,支持通过/驳回)。 /// 审核租户(统一接口,支持通过/驳回)。
/// </summary> /// </summary>

View File

@@ -1,24 +0,0 @@
using MediatR;
namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// <summary>
/// 审核通过租户命令。
/// </summary>
public sealed record ApproveTenantCommand : IRequest
{
/// <summary>
/// 租户 ID雪花算法字符串传输
/// </summary>
public required string TenantId { get; init; }
/// <summary>
/// 审核人姓名(可选,用于显示)。
/// </summary>
public string? ReviewedByName { get; init; }
/// <summary>
/// 审核备注。
/// </summary>
public string? ReviewRemarks { get; init; }
}

View File

@@ -1,24 +0,0 @@
using MediatR;
namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// <summary>
/// 审核驳回租户命令。
/// </summary>
public sealed record RejectTenantCommand : IRequest
{
/// <summary>
/// 租户 ID雪花算法字符串传输
/// </summary>
public required string TenantId { get; init; }
/// <summary>
/// 审核人姓名(可选,用于显示)。
/// </summary>
public string? ReviewedByName { get; init; }
/// <summary>
/// 驳回原因(必填)。
/// </summary>
public required string RejectReason { get; init; }
}

View File

@@ -1,68 +0,0 @@
using MediatR;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Application.App.Tenants.Commands;
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;
/// <summary>
/// 审核通过租户命令处理器。
/// </summary>
public sealed class ApproveTenantCommandHandler(
ITenantRepository tenantRepository,
ICurrentUserAccessor currentUserAccessor,
ILogger<ApproveTenantCommandHandler> logger)
: IRequestHandler<ApproveTenantCommand>
{
/// <inheritdoc />
public async Task Handle(ApproveTenantCommand request, CancellationToken cancellationToken)
{
// 1. 解析租户 ID
if (!long.TryParse(request.TenantId, out var tenantId) || tenantId <= 0)
{
throw new BusinessException(ErrorCodes.BadRequest, "租户 ID 无效");
}
// 2. 获取租户(带跟踪)
var tenant = await tenantRepository.GetByIdForUpdateAsync(tenantId, cancellationToken);
if (tenant is null)
{
throw new BusinessException(ErrorCodes.NotFound, "租户不存在");
}
// 3. 校验租户状态(只有待审核状态才能审核通过)
if (tenant.Status != TenantStatus.PendingReview)
{
throw new BusinessException(ErrorCodes.BadRequest, $"租户当前状态为 {tenant.Status},无法审核通过");
}
// 4. 获取认证资料(带跟踪)
var verification = await tenantRepository.GetVerificationForUpdateAsync(tenantId, cancellationToken);
if (verification is null)
{
throw new BusinessException(ErrorCodes.NotFound, "租户认证资料不存在");
}
// 5. 更新租户状态
tenant.Status = TenantStatus.Active;
// 6. 更新认证资料状态
verification.Status = TenantVerificationStatus.Approved;
verification.ReviewedAt = DateTime.UtcNow;
verification.ReviewedBy = currentUserAccessor.UserId;
verification.ReviewedByName = request.ReviewedByName?.Trim();
verification.ReviewRemarks = request.ReviewRemarks?.Trim();
// 7. 保存变更
await tenantRepository.SaveChangesAsync(cancellationToken);
logger.LogInformation(
"租户 {TenantId} 审核通过,审核人:{ReviewedBy}",
tenantId,
currentUserAccessor.UserId);
}
}

View File

@@ -1,73 +0,0 @@
using MediatR;
using Microsoft.Extensions.Logging;
using TakeoutSaaS.Application.App.Tenants.Commands;
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;
/// <summary>
/// 审核驳回租户命令处理器。
/// </summary>
public sealed class RejectTenantCommandHandler(
ITenantRepository tenantRepository,
ICurrentUserAccessor currentUserAccessor,
ILogger<RejectTenantCommandHandler> logger)
: IRequestHandler<RejectTenantCommand>
{
/// <inheritdoc />
public async Task Handle(RejectTenantCommand request, CancellationToken cancellationToken)
{
// 1. 解析租户 ID
if (!long.TryParse(request.TenantId, out var tenantId) || tenantId <= 0)
{
throw new BusinessException(ErrorCodes.BadRequest, "租户 ID 无效");
}
// 2. 校验驳回原因
var rejectReason = request.RejectReason?.Trim();
if (string.IsNullOrWhiteSpace(rejectReason))
{
throw new BusinessException(ErrorCodes.BadRequest, "驳回原因不能为空");
}
// 3. 获取租户(带跟踪)
var tenant = await tenantRepository.GetByIdForUpdateAsync(tenantId, cancellationToken);
if (tenant is null)
{
throw new BusinessException(ErrorCodes.NotFound, "租户不存在");
}
// 4. 校验租户状态(只有待审核状态才能驳回)
if (tenant.Status != TenantStatus.PendingReview)
{
throw new BusinessException(ErrorCodes.BadRequest, $"租户当前状态为 {tenant.Status},无法驳回");
}
// 5. 获取认证资料(带跟踪)
var verification = await tenantRepository.GetVerificationForUpdateAsync(tenantId, cancellationToken);
if (verification is null)
{
throw new BusinessException(ErrorCodes.NotFound, "租户认证资料不存在");
}
// 6. 更新认证资料状态(租户状态保持 PendingReview等待重新提交
verification.Status = TenantVerificationStatus.Rejected;
verification.ReviewedAt = DateTime.UtcNow;
verification.ReviewedBy = currentUserAccessor.UserId;
verification.ReviewedByName = request.ReviewedByName?.Trim();
verification.ReviewRemarks = rejectReason;
// 7. 保存变更
await tenantRepository.SaveChangesAsync(cancellationToken);
logger.LogInformation(
"租户 {TenantId} 审核驳回,驳回原因:{RejectReason},审核人:{ReviewedBy}",
tenantId,
rejectReason,
currentUserAccessor.UserId);
}
}