Files
tiku-backend.net/Tiku.Api/Contracts/PlatformAdminDtos.cs
xiong 33375a38d7
Some checks failed
ci / release-gate (push) Has been cancelled
refactor(architecture): harden module boundaries
2026-08-04 12:10:36 +08:00

580 lines
15 KiB
C#

using System.ComponentModel.DataAnnotations;
using System.Text.Json;
using Tiku.Application.PlatformAdmin;
using Tiku.Domain.Common;
using Tiku.Domain.Identity;
using Tiku.Domain.Platform;
using Tiku.Domain.Tenancy;
namespace Tiku.Api.Contracts;
/// <summary>
/// 平台管理端查询参数。
/// </summary>
public sealed class PlatformAdminQueryDto
{
/// <summary>
/// 状态。
/// </summary>
[StringLength(32)]
public string? Status { get; set; }
/// <summary>
/// 搜索关键字。
/// </summary>
[StringLength(200)]
public string? Search { get; set; }
/// <summary>
/// 返回数量上限。
/// </summary>
[Range(1, 200)]
public int? Limit { get; set; }
public PlatformAdminQuery ToQuery()
{
return new PlatformAdminQuery(Status, Search, Limit);
}
}
/// <summary>
/// 创建平台租户请求 DTO。
/// </summary>
public sealed class CreatePlatformTenantDto
{
/// <summary>
/// 短编码。
/// </summary>
[Required]
[StringLength(100)]
public string Slug { get; set; } = string.Empty;
/// <summary>
/// 名称。
/// </summary>
[Required]
[StringLength(200)]
public string Name { get; set; } = string.Empty;
/// <summary>
/// 法定名称。
/// </summary>
[StringLength(300)]
public string? LegalName { get; set; }
/// <summary>
/// 状态。
/// </summary>
public TenantStatus Status { get; set; } = TenantStatus.Active;
/// <summary>
/// 账务状态。
/// </summary>
public BillingStatus BillingStatus { get; set; } = BillingStatus.Trial;
/// <summary>
/// 扩展元数据。
/// </summary>
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
/// <summary>租户首次开通使用的自定义主域名。</summary>
[Required]
[StringLength(253, MinimumLength = 4)]
public string PrimaryDomainHost { get; set; } = string.Empty;
/// <summary>
/// 租户负责人邮箱。
/// </summary>
[EmailAddress]
[StringLength(320)]
public string? OwnerEmail { get; set; }
/// <summary>
/// 租户负责人手机号。
/// </summary>
[Phone]
[StringLength(32)]
public string? OwnerPhone { get; set; }
/// <summary>
/// 租户负责人姓名。
/// </summary>
[Required]
[StringLength(100)]
public string OwnerName { get; set; } = string.Empty;
/// <summary>初始试用套餐版本;为空时使用平台配置的默认基础套餐。</summary>
public Guid? InitialOfferingVersionId { get; set; }
/// <summary>试用天数;为空时使用平台配置的默认天数。</summary>
[Range(1, 365)]
public int? TrialDays { get; set; }
/// <summary>收款模式。</summary>
public TenantBillingCollectionMode CollectionMode { get; set; } = TenantBillingCollectionMode.Online;
/// <summary>默认支付 Provider。</summary>
[Required]
[StringLength(50)]
public string DefaultPaymentProvider { get; set; } = "manual";
/// <summary>是否自动生成续费应收。</summary>
public bool AutoGenerateRenewal { get; set; } = true;
/// <summary>续费应收提前生成天数。</summary>
[Range(1, 90)]
public int RenewalLeadDays { get; set; } = 14;
public CreatePlatformTenantCommand ToCommand(string idempotencyKey)
{
return new CreatePlatformTenantCommand(
Slug, Name, LegalName, Status, BillingStatus, Metadata, PrimaryDomainHost,
OwnerEmail, OwnerPhone, OwnerName,
InitialOfferingVersionId, TrialDays, CollectionMode, DefaultPaymentProvider,
AutoGenerateRenewal, RenewalLeadDays, idempotencyKey);
}
}
public sealed class ReplacePlatformPrimaryDomainDto
{
[Required]
[StringLength(253, MinimumLength = 4)]
public string Host { get; set; } = string.Empty;
[Required]
[StringLength(1000, MinimumLength = 3)]
public string Reason { get; set; } = string.Empty;
public ReplacePlatformPrimaryDomainCommand ToCommand(Guid tenantId)
{
return new ReplacePlatformPrimaryDomainCommand(tenantId, Host, Reason);
}
}
public sealed class IssuePlatformOwnerActivationLinkDto
{
[Required]
[StringLength(1000, MinimumLength = 3)]
public string Reason { get; set; } = string.Empty;
public bool ReplaceExisting { get; set; }
public IssuePlatformOwnerActivationLinkCommand ToCommand(Guid tenantId, string idempotencyKey)
{
return new IssuePlatformOwnerActivationLinkCommand(tenantId, idempotencyKey, Reason, ReplaceExisting);
}
}
/// <summary>更新租户收款策略。</summary>
public sealed class UpsertTenantBillingPolicyDto
{
public TenantBillingCollectionMode CollectionMode { get; set; } = TenantBillingCollectionMode.Online;
[Required][StringLength(50)] public string DefaultPaymentProvider { get; set; } = "manual";
public bool AutoGenerateRenewal { get; set; } = true;
[Range(1, 90)] public int RenewalLeadDays { get; set; } = 14;
[Required]
[StringLength(1000, MinimumLength = 3)]
public string Reason { get; set; } = string.Empty;
public UpsertTenantBillingPolicyCommand ToCommand(Guid tenantId)
{
return new UpsertTenantBillingPolicyCommand(
tenantId,
CollectionMode,
DefaultPaymentProvider,
AutoGenerateRenewal,
RenewalLeadDays,
Reason);
}
}
/// <summary>
/// 更新平台租户状态请求 DTO。
/// </summary>
public sealed class UpdatePlatformTenantStatusDto
{
/// <summary>
/// 租户 ID。
/// </summary>
[Required]
public Guid TenantId { get; set; }
/// <summary>
/// 状态。
/// </summary>
public TenantStatus Status { get; set; } = TenantStatus.Active;
/// <summary>
/// 原因。
/// </summary>
[StringLength(1000)]
public string? Reason { get; set; }
public UpdatePlatformTenantStatusCommand ToCommand()
{
return new UpdatePlatformTenantStatusCommand(TenantId, Status, Reason);
}
}
/// <summary>
/// 新增或更新平台租户账务资料请求 DTO。
/// </summary>
public sealed class UpsertPlatformTenantBillingProfileDto
{
/// <summary>
/// 租户 ID。
/// </summary>
[Required]
public Guid TenantId { get; set; }
/// <summary>
/// 账务名称。
/// </summary>
[StringLength(300)]
public string? BillingName { get; set; }
/// <summary>
/// 税号。
/// </summary>
[StringLength(100)]
public string? TaxId { get; set; }
/// <summary>
/// 联系人姓名。
/// </summary>
[StringLength(100)]
public string? ContactName { get; set; }
/// <summary>
/// 联系人手机号。
/// </summary>
[StringLength(32)]
public string? ContactPhone { get; set; }
/// <summary>
/// 联系人邮箱。
/// </summary>
[StringLength(320)]
public string? ContactEmail { get; set; }
/// <summary>
/// 账务地址。
/// </summary>
[StringLength(1000)]
public string? BillingAddress { get; set; }
/// <summary>
/// 发票抬头。
/// </summary>
[StringLength(300)]
public string? InvoiceTitle { get; set; }
/// <summary>
/// 发票类型。
/// </summary>
public TenantBillingInvoiceTitleType? InvoiceType { get; set; }
/// <summary>
/// 开户银行。
/// </summary>
[StringLength(300)]
public string? BankName { get; set; }
/// <summary>
/// 脱敏银行账号。
/// </summary>
[StringLength(100)]
public string? BankAccountMasked { get; set; }
/// <summary>
/// 扩展元数据。
/// </summary>
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
public UpsertPlatformTenantBillingProfileCommand ToCommand()
{
return new UpsertPlatformTenantBillingProfileCommand(
TenantId,
BillingName,
TaxId,
ContactName,
ContactPhone,
ContactEmail,
BillingAddress,
InvoiceTitle,
InvoiceType,
BankName,
BankAccountMasked,
Metadata);
}
}
/// <summary>
/// 新增或更新平台Staff请求 DTO。
/// </summary>
public sealed class UpsertPlatformStaffDto
{
/// <summary>
/// 用户 ID。
/// </summary>
public Guid? UserId { get; set; }
/// <summary>
/// 邮箱。
/// </summary>
[StringLength(320)]
public string? Email { get; set; }
/// <summary>
/// 手机号。
/// </summary>
[StringLength(32)]
public string? Phone { get; set; }
/// <summary>
/// 名称。
/// </summary>
[StringLength(200)]
public string? Name { get; set; }
/// <summary>
/// 状态。
/// </summary>
public UserStatus Status { get; set; } = UserStatus.Active;
/// <summary>
/// 角色 ID 列表。
/// </summary>
public IReadOnlyCollection<Guid> RoleIds { get; set; } = [];
public UpsertPlatformStaffCommand ToCommand()
{
return new UpsertPlatformStaffCommand(UserId, Email, Phone, Name, Status, RoleIds);
}
}
/// <summary>
/// 更新平台Staff状态请求 DTO。
/// </summary>
public sealed class UpdatePlatformStaffStatusDto
{
/// <summary>
/// 用户 ID。
/// </summary>
[Required]
public Guid UserId { get; set; }
/// <summary>
/// 状态。
/// </summary>
public UserStatus Status { get; set; } = UserStatus.Active;
/// <summary>
/// 原因。
/// </summary>
[StringLength(1000)]
public string? Reason { get; set; }
public UpdatePlatformStaffStatusCommand ToCommand()
{
return new UpdatePlatformStaffStatusCommand(UserId, Status, Reason);
}
}
/// <summary>
/// 更新平台审计Alert状态请求 DTO。
/// </summary>
public sealed class UpdatePlatformAuditAlertStatusDto
{
/// <summary>
/// 告警 ID。
/// </summary>
[Required]
public Guid AlertId { get; set; }
/// <summary>
/// 状态。
/// </summary>
public PlatformAuditAlertStatus Status { get; set; } = PlatformAuditAlertStatus.Acknowledged;
/// <summary>
/// 处理备注。
/// </summary>
[StringLength(1000)]
public string? ResolutionNote { get; set; }
public UpdatePlatformAuditAlertStatusCommand ToCommand()
{
return new UpdatePlatformAuditAlertStatusCommand(AlertId, Status, ResolutionNote);
}
}
/// <summary>
/// 新增或更新平台DunningChannel请求 DTO。
/// </summary>
public sealed class UpsertPlatformBillingDunningChannelDto
{
/// <summary>
/// 通知渠道 ID。
/// </summary>
public Guid? ChannelId { get; set; }
/// <summary>
/// 渠道编码。
/// </summary>
[Required]
[StringLength(100)]
public string ChannelCode { get; set; } = string.Empty;
/// <summary>
/// 名称。
/// </summary>
[Required]
[StringLength(200)]
public string Name { get; set; } = string.Empty;
/// <summary>
/// 说明。
/// </summary>
[StringLength(1000)]
public string? Description { get; set; }
/// <summary>
/// 是否启用。
/// </summary>
public bool Enabled { get; set; } = true;
/// <summary>
/// 服务提供方。
/// </summary>
public PlatformBillingDunningProvider Provider { get; set; } = PlatformBillingDunningProvider.Generic;
/// <summary>
/// Webhook 地址。
/// </summary>
[Required]
[StringLength(2048)]
public string WebhookUrl { get; set; } = string.Empty;
/// <summary>
/// 密钥引用。
/// </summary>
[StringLength(300)]
public string? SecretRef { get; set; }
/// <summary>
/// 提醒类型列表。
/// </summary>
public IReadOnlyCollection<string> ReminderTypes { get; set; } = ["overdue", "final_notice"];
/// <summary>
/// 提醒渠道列表。
/// </summary>
public IReadOnlyCollection<string> ReminderChannels { get; set; } = ["internal"];
/// <summary>
/// 最低提醒级别。
/// </summary>
[Range(1, 20)]
public int MinReminderLevel { get; set; } = 1;
/// <summary>
/// 租户 ID 列表。
/// </summary>
public IReadOnlyCollection<Guid> TenantIds { get; set; } = [];
/// <summary>
/// 超时时长,单位为秒。
/// </summary>
[Range(1, 60)]
public int TimeoutSeconds { get; set; } = 10;
/// <summary>
/// 扩展元数据。
/// </summary>
public JsonElement Metadata { get; set; } = JsonDefaults.Object();
public UpsertPlatformBillingDunningChannelCommand ToCommand()
{
return new UpsertPlatformBillingDunningChannelCommand(
ChannelId,
ChannelCode,
Name,
Description,
Enabled,
Provider,
WebhookUrl,
SecretRef,
ReminderTypes,
ReminderChannels,
MinReminderLevel,
TenantIds,
TimeoutSeconds,
Metadata);
}
}
/// <summary>
/// 禁用平台DunningChannel请求 DTO。
/// </summary>
public sealed class DisablePlatformBillingDunningChannelDto
{
/// <summary>
/// 通知渠道 ID。
/// </summary>
[Required]
public Guid ChannelId { get; set; }
/// <summary>
/// 原因。
/// </summary>
[StringLength(1000)]
public string? Reason { get; set; }
public DisablePlatformBillingDunningChannelCommand ToCommand()
{
return new DisablePlatformBillingDunningChannelCommand(ChannelId, Reason);
}
}
/// <summary>
/// 重试平台Dunning事件请求 DTO。
/// </summary>
public sealed class RetryPlatformBillingDunningEventDto
{
/// <summary>
/// 事件 ID。
/// </summary>
[Required]
public Guid EventId { get; set; }
/// <summary>
/// 原因。
/// </summary>
[StringLength(1000)]
public string? Reason { get; set; }
public RetryPlatformBillingDunningEventCommand ToCommand()
{
return new RetryPlatformBillingDunningEventCommand(EventId, Reason);
}
}
/// <summary>人工确认或忽略催缴投递事件。</summary>
public sealed class ResolvePlatformBillingDunningEventDto
{
[Required] public Guid EventId { get; set; }
[Required]
[StringLength(1000, MinimumLength = 3)]
public string Reason { get; set; } = string.Empty;
public ResolvePlatformBillingDunningEventCommand ToCommand()
{
return new ResolvePlatformBillingDunningEventCommand(EventId, Reason);
}
}