feat: 实现租户管理及套餐流程
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
using MediatR;
|
||||
using Microsoft.Extensions.Logging;
|
||||
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;
|
||||
|
||||
namespace TakeoutSaaS.Application.App.Tenants.Handlers;
|
||||
|
||||
/// <summary>
|
||||
/// 租户注册处理器。
|
||||
/// </summary>
|
||||
public sealed class RegisterTenantCommandHandler(
|
||||
ITenantRepository tenantRepository,
|
||||
IIdGenerator idGenerator,
|
||||
ILogger<RegisterTenantCommandHandler> logger)
|
||||
: IRequestHandler<RegisterTenantCommand, TenantDto>
|
||||
{
|
||||
private readonly ITenantRepository _tenantRepository = tenantRepository;
|
||||
private readonly IIdGenerator _idGenerator = idGenerator;
|
||||
private readonly ILogger<RegisterTenantCommandHandler> _logger = logger;
|
||||
|
||||
/// <inheritdoc />
|
||||
public async Task<TenantDto> Handle(RegisterTenantCommand request, CancellationToken cancellationToken)
|
||||
{
|
||||
if (request.DurationMonths <= 0)
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.BadRequest, "订阅时长必须大于 0");
|
||||
}
|
||||
|
||||
if (await _tenantRepository.ExistsByCodeAsync(request.Code, cancellationToken))
|
||||
{
|
||||
throw new BusinessException(ErrorCodes.Conflict, $"租户编码 {request.Code} 已存在");
|
||||
}
|
||||
|
||||
var now = DateTime.UtcNow;
|
||||
var effectiveFrom = request.EffectiveFrom ?? now;
|
||||
var effectiveTo = effectiveFrom.AddMonths(request.DurationMonths);
|
||||
|
||||
var tenant = new Tenant
|
||||
{
|
||||
Id = _idGenerator.NextId(),
|
||||
Code = request.Code.Trim(),
|
||||
Name = request.Name,
|
||||
ShortName = request.ShortName,
|
||||
Industry = request.Industry,
|
||||
ContactName = request.ContactName,
|
||||
ContactPhone = request.ContactPhone,
|
||||
ContactEmail = request.ContactEmail,
|
||||
Status = TenantStatus.PendingReview,
|
||||
EffectiveFrom = effectiveFrom,
|
||||
EffectiveTo = effectiveTo
|
||||
};
|
||||
|
||||
var subscription = new TenantSubscription
|
||||
{
|
||||
Id = _idGenerator.NextId(),
|
||||
TenantId = tenant.Id,
|
||||
TenantPackageId = request.TenantPackageId,
|
||||
EffectiveFrom = effectiveFrom,
|
||||
EffectiveTo = effectiveTo,
|
||||
NextBillingDate = effectiveTo,
|
||||
Status = SubscriptionStatus.Pending,
|
||||
AutoRenew = request.AutoRenew,
|
||||
Notes = "Init subscription"
|
||||
};
|
||||
|
||||
await _tenantRepository.AddTenantAsync(tenant, cancellationToken);
|
||||
await _tenantRepository.AddSubscriptionAsync(subscription, cancellationToken);
|
||||
await _tenantRepository.AddAuditLogAsync(new TenantAuditLog
|
||||
{
|
||||
TenantId = tenant.Id,
|
||||
Action = TenantAuditAction.RegistrationSubmitted,
|
||||
Title = "租户注册",
|
||||
Description = $"提交套餐 {request.TenantPackageId},时长 {request.DurationMonths} 月"
|
||||
}, cancellationToken);
|
||||
|
||||
await _tenantRepository.SaveChangesAsync(cancellationToken);
|
||||
|
||||
_logger.LogInformation("已注册租户 {TenantCode}", tenant.Code);
|
||||
|
||||
return TenantMapping.ToDto(tenant, subscription, null);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user