Files
TakeoutSaaS.AdminApi/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantManuallyCommand.cs
MSuMshk a586407e60 feat: 手动创建租户支持可选审核,新增审核通过/驳回接口
- CreateTenantManuallyCommand 添加 IsSkipApproval 字段
- 根据 IsSkipApproval 自动设置租户状态和认证状态
- 新增 ApproveTenantCommand/Handler 审核通过逻辑
- 新增 RejectTenantCommand/Handler 审核驳回逻辑
- TenantsController 添加 PUT /approve 和 PUT /reject 接口

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 19:59:03 +08:00

287 lines
7.1 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.Contracts;
using TakeoutSaaS.Domain.Billings.Enums;
using TakeoutSaaS.Domain.Tenants.Enums;
namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// <summary>
/// 后台手动新增租户命令(直接入驻:创建租户 + 认证 + 订阅 + 管理员账号)。
/// </summary>
public sealed record CreateTenantManuallyCommand : IRequest<TenantDetailDto>
{
// 1. 租户基本信息public.tenants
/// <summary>
/// 租户编码(唯一)。
/// </summary>
public required string Code { get; init; }
/// <summary>
/// 租户名称。
/// </summary>
public required string Name { get; init; }
/// <summary>
/// 租户简称。
/// </summary>
public string? ShortName { get; init; }
/// <summary>
/// 法人/公司主体名称。
/// </summary>
public string? LegalEntityName { get; init; }
/// <summary>
/// 所属行业。
/// </summary>
public string? Industry { get; init; }
/// <summary>
/// LOGO 图片地址。
/// </summary>
public string? LogoUrl { get; init; }
/// <summary>
/// 封面图地址。
/// </summary>
public string? CoverImageUrl { get; init; }
/// <summary>
/// 官网地址。
/// </summary>
public string? Website { get; init; }
/// <summary>
/// 国家/地区。
/// </summary>
public string? Country { get; init; }
/// <summary>
/// 省份。
/// </summary>
public string? Province { get; init; }
/// <summary>
/// 城市。
/// </summary>
public string? City { get; init; }
/// <summary>
/// 详细地址。
/// </summary>
public string? Address { get; init; }
/// <summary>
/// 联系人姓名。
/// </summary>
public string? ContactName { get; init; }
/// <summary>
/// 联系人电话。
/// </summary>
public string? ContactPhone { get; init; }
/// <summary>
/// 联系人邮箱。
/// </summary>
public string? ContactEmail { get; init; }
/// <summary>
/// 标签(逗号分隔)。
/// </summary>
public string? Tags { get; init; }
/// <summary>
/// 备注。
/// </summary>
public string? Remarks { get; init; }
/// <summary>
/// 暂停时间。
/// </summary>
public DateTime? SuspendedAt { get; init; }
/// <summary>
/// 暂停原因。
/// </summary>
public string? SuspensionReason { get; init; }
/// <summary>
/// 租户状态。
/// </summary>
public TenantStatus TenantStatus { get; init; } = TenantStatus.Active;
/// <summary>
/// 是否跳过审核(直接激活)。
/// </summary>
/// <remarks>
/// true租户状态设为 Active认证状态设为 Approved默认
/// false租户状态设为 PendingReview认证状态设为 Pending需后续审核。
/// </remarks>
public bool IsSkipApproval { get; init; } = true;
// 2. 订阅信息public.tenant_subscriptions
/// <summary>
/// 套餐 ID雪花算法字符串传输
/// </summary>
public required string TenantPackageId { get; init; }
/// <summary>
/// 订阅时长(月)。
/// </summary>
public int DurationMonths { get; init; } = 12;
/// <summary>
/// 是否自动续费。
/// </summary>
public bool AutoRenew { get; init; }
/// <summary>
/// 订阅生效时间。
/// </summary>
public DateTime? SubscriptionEffectiveFrom { get; init; }
/// <summary>
/// 下次计费日期。
/// </summary>
public DateTime? NextBillingDate { get; init; }
/// <summary>
/// 订阅状态0=待激活, 1=生效中, 2=宽限期, 3=已取消, 4=已暂停)。
/// </summary>
public SubscriptionStatus SubscriptionStatus { get; init; } = SubscriptionStatus.Active;
/// <summary>
/// 预约变更的套餐 ID。
/// </summary>
public string? ScheduledPackageId { get; init; }
/// <summary>
/// 订阅备注。
/// </summary>
public string? SubscriptionNotes { get; init; }
// 3. 认证信息public.tenant_verification_profiles
/// <summary>
/// 认证状态。
/// </summary>
public TenantVerificationStatus VerificationStatus { get; init; } = TenantVerificationStatus.Approved;
/// <summary>
/// 营业执照号。
/// </summary>
public string? BusinessLicenseNumber { get; init; }
/// <summary>
/// 营业执照图片 URL。
/// </summary>
public string? BusinessLicenseUrl { get; init; }
/// <summary>
/// 法人姓名。
/// </summary>
public string? LegalPersonName { get; init; }
/// <summary>
/// 法人身份证号。
/// </summary>
public string? LegalPersonIdNumber { get; init; }
/// <summary>
/// 法人身份证正面 URL。
/// </summary>
public string? LegalPersonIdFrontUrl { get; init; }
/// <summary>
/// 法人身份证背面 URL。
/// </summary>
public string? LegalPersonIdBackUrl { get; init; }
/// <summary>
/// 银行账户名。
/// </summary>
public string? BankAccountName { get; init; }
/// <summary>
/// 银行账号。
/// </summary>
public string? BankAccountNumber { get; init; }
/// <summary>
/// 开户银行。
/// </summary>
public string? BankName { get; init; }
/// <summary>
/// 附加数据 JSON。
/// </summary>
public string? AdditionalDataJson { get; init; }
/// <summary>
/// 审核人姓名。
/// </summary>
public string? ReviewedByName { get; init; }
/// <summary>
/// 审核备注。
/// </summary>
public string? ReviewRemarks { get; init; }
// 4. 管理员账号identity.identity_users
/// <summary>
/// 管理员登录账号。
/// </summary>
public required string AdminAccount { get; init; }
/// <summary>
/// 管理员显示名称。
/// </summary>
public required string AdminDisplayName { get; init; }
/// <summary>
/// 管理员密码(明文,后端哈希)。
/// </summary>
public required string AdminPassword { get; init; }
/// <summary>
/// 管理员头像。
/// </summary>
public string? AdminAvatar { get; init; }
/// <summary>
/// 管理员所属商户 ID。
/// </summary>
public string? AdminMerchantId { get; init; }
// 5. 账单信息public.tenant_billing_statements
/// <summary>
/// 是否创建账单。
/// </summary>
public bool CreateBilling { get; init; } = true;
/// <summary>
/// 账单金额(不填则根据套餐价格×月数计算)。
/// </summary>
public decimal? BillingAmount { get; init; }
/// <summary>
/// 折扣金额。
/// </summary>
public decimal? BillingDiscountAmount { get; init; }
/// <summary>
/// 账单状态(默认已支付)。
/// </summary>
public TenantBillingStatus BillingStatus { get; init; } = TenantBillingStatus.Paid;
/// <summary>
/// 账单备注。
/// </summary>
public string? BillingNotes { get; init; }
}