Files
TakeoutSaaS.TenantApi/src/Application/TakeoutSaaS.Application/App/Tenants/Handlers/SubmitTenantVerificationCommandHandler.cs
2026-02-17 12:12:01 +08:00

81 lines
3.6 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using MediatR;
using TakeoutSaaS.Application.App.Tenants.Commands;
using TakeoutSaaS.Application.App.Tenants.Dto;
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.Tenancy;
namespace TakeoutSaaS.Application.App.Tenants.Handlers;
/// <summary>
/// 实名资料提交流程。
/// </summary>
public sealed class SubmitTenantVerificationCommandHandler(
ITenantRepository tenantRepository,
ITenantProvider tenantProvider,
IIdGenerator idGenerator)
: IRequestHandler<SubmitTenantVerificationCommand, TenantVerificationDto>
{
/// <inheritdoc />
public async Task<TenantVerificationDto> Handle(SubmitTenantVerificationCommand request, CancellationToken cancellationToken)
{
// 1. 校验租户上下文(租户端禁止跨租户)
var currentTenantId = tenantProvider.GetCurrentTenantId();
if (currentTenantId <= 0)
{
throw new BusinessException(ErrorCodes.BadRequest, "缺少租户标识");
}
// 2. (空行后) 兼容旧调用:若传入 TenantId则必须与当前租户一致
if (request.TenantId > 0 && request.TenantId != currentTenantId)
{
throw new BusinessException(ErrorCodes.Forbidden, "无权提交其他租户实名认证资料");
}
// 3. (空行后) 获取租户
var tenant = await tenantRepository.FindByIdAsync(currentTenantId, cancellationToken)
?? throw new BusinessException(ErrorCodes.NotFound, "租户不存在");
// 4. (空行后) 读取或初始化实名资料
var profile = await tenantRepository.GetVerificationProfileAsync(currentTenantId, cancellationToken)
?? new TenantVerificationProfile { Id = idGenerator.NextId(), TenantId = tenant.Id };
// 5. (空行后) 填充资料
profile.BusinessLicenseNumber = request.BusinessLicenseNumber;
profile.BusinessLicenseUrl = request.BusinessLicenseUrl;
profile.LegalPersonName = request.LegalPersonName;
profile.LegalPersonIdNumber = request.LegalPersonIdNumber;
profile.LegalPersonIdFrontUrl = request.LegalPersonIdFrontUrl;
profile.LegalPersonIdBackUrl = request.LegalPersonIdBackUrl;
profile.BankAccountName = request.BankAccountName;
profile.BankAccountNumber = request.BankAccountNumber;
profile.BankName = request.BankName;
profile.AdditionalDataJson = request.AdditionalDataJson;
profile.Status = TenantVerificationStatus.Pending;
profile.SubmittedAt = DateTime.UtcNow;
profile.ReviewedAt = null;
profile.ReviewRemarks = null;
profile.ReviewedBy = null;
profile.ReviewedByName = null;
// 6. (空行后) 保存资料并记录审计
await tenantRepository.UpsertVerificationProfileAsync(profile, cancellationToken);
await tenantRepository.AddAuditLogAsync(new TenantAuditLog
{
TenantId = tenant.Id,
Action = TenantAuditAction.VerificationSubmitted,
Title = "提交实名认证资料",
Description = request.BusinessLicenseNumber
}, cancellationToken);
await tenantRepository.SaveChangesAsync(cancellationToken);
// 7. (空行后) 返回 DTO
return profile.ToVerificationDto()
?? throw new BusinessException(ErrorCodes.InternalServerError, "实名资料保存失败");
}
}