docs: add xml comments for tenant modules

This commit is contained in:
2025-12-03 22:56:35 +08:00
parent 83c81d5fd1
commit bf88f0e041
28 changed files with 661 additions and 40 deletions

View File

@@ -7,9 +7,33 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// <summary>
/// 套餐升降配命令。
/// </summary>
public sealed record ChangeTenantSubscriptionPlanCommand(
[property: Required] long TenantId,
[property: Required] long TenantSubscriptionId,
[property: Required] long TargetPackageId,
bool Immediate,
string? Notes) : IRequest<TenantSubscriptionDto>;
public sealed record ChangeTenantSubscriptionPlanCommand : IRequest<TenantSubscriptionDto>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
[Required]
public long TenantId { get; init; }
/// <summary>
/// 现有订阅 ID。
/// </summary>
[Required]
public long TenantSubscriptionId { get; init; }
/// <summary>
/// 目标套餐 ID。
/// </summary>
[Required]
public long TargetPackageId { get; init; }
/// <summary>
/// 是否立即生效,否则在下一结算周期生效。
/// </summary>
public bool Immediate { get; init; }
/// <summary>
/// 调整备注。
/// </summary>
public string? Notes { get; init; }
}

View File

@@ -9,12 +9,43 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// </summary>
public sealed record CreateTenantAnnouncementCommand : IRequest<TenantAnnouncementDto>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 公告标题。
/// </summary>
public string Title { get; init; } = string.Empty;
/// <summary>
/// 公告正文内容。
/// </summary>
public string Content { get; init; } = string.Empty;
/// <summary>
/// 公告类型。
/// </summary>
public TenantAnnouncementType AnnouncementType { get; init; } = TenantAnnouncementType.System;
/// <summary>
/// 优先级,数值越大越靠前。
/// </summary>
public int Priority { get; init; } = 0;
/// <summary>
/// 生效开始时间UTC
/// </summary>
public DateTime EffectiveFrom { get; init; } = DateTime.UtcNow;
/// <summary>
/// 生效结束时间UTC为空则长期有效。
/// </summary>
public DateTime? EffectiveTo { get; init; }
/// <summary>
/// 是否启用。
/// </summary>
public bool IsActive { get; init; } = true;
}

View File

@@ -9,13 +9,48 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// </summary>
public sealed record CreateTenantBillingCommand : IRequest<TenantBillingDto>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 账单编号。
/// </summary>
public string StatementNo { get; init; } = string.Empty;
/// <summary>
/// 计费周期开始时间UTC
/// </summary>
public DateTime PeriodStart { get; init; }
/// <summary>
/// 计费周期结束时间UTC
/// </summary>
public DateTime PeriodEnd { get; init; }
/// <summary>
/// 应付金额。
/// </summary>
public decimal AmountDue { get; init; }
/// <summary>
/// 已付金额。
/// </summary>
public decimal AmountPaid { get; init; }
/// <summary>
/// 账单状态。
/// </summary>
public TenantBillingStatus Status { get; init; } = TenantBillingStatus.Pending;
/// <summary>
/// 到期日UTC
/// </summary>
public DateTime DueDate { get; init; }
/// <summary>
/// 账单明细 JSON。
/// </summary>
public string? LineItemsJson { get; init; }
}

View File

@@ -7,9 +7,32 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// <summary>
/// 新建或续费订阅。
/// </summary>
public sealed record CreateTenantSubscriptionCommand(
[property: Required] long TenantId,
[property: Required] long TenantPackageId,
int DurationMonths,
bool AutoRenew,
string? Notes) : IRequest<TenantSubscriptionDto>;
public sealed record CreateTenantSubscriptionCommand : IRequest<TenantSubscriptionDto>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
[Required]
public long TenantId { get; init; }
/// <summary>
/// 套餐 ID。
/// </summary>
[Required]
public long TenantPackageId { get; init; }
/// <summary>
/// 订阅时长(月)。
/// </summary>
public int DurationMonths { get; init; }
/// <summary>
/// 是否自动续费。
/// </summary>
public bool AutoRenew { get; init; }
/// <summary>
/// 备注信息。
/// </summary>
public string? Notes { get; init; }
}

View File

@@ -7,6 +7,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// </summary>
public sealed record DeleteTenantAnnouncementCommand : IRequest<bool>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 公告 ID。
/// </summary>
public long AnnouncementId { get; init; }
}

View File

@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// </summary>
public sealed record MarkTenantAnnouncementReadCommand : IRequest<TenantAnnouncementDto?>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 公告 ID。
/// </summary>
public long AnnouncementId { get; init; }
}

View File

@@ -8,8 +8,23 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// </summary>
public sealed record MarkTenantBillingPaidCommand : IRequest<TenantBillingDto?>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 账单 ID。
/// </summary>
public long BillingId { get; init; }
/// <summary>
/// 本次支付金额。
/// </summary>
public decimal AmountPaid { get; init; }
/// <summary>
/// 支付时间UTC
/// </summary>
public DateTime PaidAt { get; init; } = DateTime.UtcNow;
}

View File

@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// </summary>
public sealed record MarkTenantNotificationReadCommand : IRequest<TenantNotificationDto?>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 通知 ID。
/// </summary>
public long NotificationId { get; init; }
}

View File

@@ -7,15 +7,65 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// <summary>
/// 注册租户命令。
/// </summary>
public sealed record RegisterTenantCommand(
[property: Required, StringLength(64)] string Code,
[property: Required, StringLength(128)] string Name,
string? ShortName,
string? Industry,
string? ContactName,
string? ContactPhone,
string? ContactEmail,
[property: Required] long TenantPackageId,
int DurationMonths = 12,
bool AutoRenew = true,
DateTime? EffectiveFrom = null) : IRequest<TenantDto>;
public sealed record RegisterTenantCommand : IRequest<TenantDto>
{
/// <summary>
/// 唯一租户编码。
/// </summary>
[Required]
[StringLength(64)]
public string Code { get; init; } = string.Empty;
/// <summary>
/// 租户名称。
/// </summary>
[Required]
[StringLength(128)]
public string Name { get; init; } = string.Empty;
/// <summary>
/// 租户简称。
/// </summary>
public string? ShortName { get; init; }
/// <summary>
/// 行业类型。
/// </summary>
public string? Industry { get; init; }
/// <summary>
/// 联系人姓名。
/// </summary>
public string? ContactName { get; init; }
/// <summary>
/// 联系人电话。
/// </summary>
public string? ContactPhone { get; init; }
/// <summary>
/// 联系人邮箱。
/// </summary>
public string? ContactEmail { get; init; }
/// <summary>
/// 购买套餐 ID。
/// </summary>
[Required]
public long TenantPackageId { get; init; }
/// <summary>
/// 订阅时长(月),默认 12 个月。
/// </summary>
public int DurationMonths { get; init; } = 12;
/// <summary>
/// 是否自动续费。
/// </summary>
public bool AutoRenew { get; init; } = true;
/// <summary>
/// 生效时间UTC为空则立即生效。
/// </summary>
public DateTime? EffectiveFrom { get; init; }
}

View File

@@ -7,7 +7,21 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// <summary>
/// 审核租户命令。
/// </summary>
public sealed record ReviewTenantCommand(
[property: Required] long TenantId,
bool Approve,
string? Reason) : IRequest<TenantDto>;
public sealed record ReviewTenantCommand : IRequest<TenantDto>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
[Required]
public long TenantId { get; init; }
/// <summary>
/// 是否通过审核。
/// </summary>
public bool Approve { get; init; }
/// <summary>
/// 审核备注或拒绝原因。
/// </summary>
public string? Reason { get; init; }
}

View File

@@ -7,15 +7,61 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// <summary>
/// 提交租户实名认证资料。
/// </summary>
public sealed record SubmitTenantVerificationCommand(
[property: Required] long TenantId,
string? BusinessLicenseNumber,
string? BusinessLicenseUrl,
string? LegalPersonName,
string? LegalPersonIdNumber,
string? LegalPersonIdFrontUrl,
string? LegalPersonIdBackUrl,
string? BankAccountName,
string? BankAccountNumber,
string? BankName,
string? AdditionalDataJson) : IRequest<TenantVerificationDto>;
public sealed record SubmitTenantVerificationCommand : IRequest<TenantVerificationDto>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
[Required]
public long TenantId { get; init; }
/// <summary>
/// 营业执照编号。
/// </summary>
public string? BusinessLicenseNumber { get; init; }
/// <summary>
/// 营业执照扫描件地址。
/// </summary>
public string? BusinessLicenseUrl { get; init; }
/// <summary>
/// 法人姓名。
/// </summary>
public string? LegalPersonName { get; init; }
/// <summary>
/// 法人身份证号。
/// </summary>
public string? LegalPersonIdNumber { get; init; }
/// <summary>
/// 法人身份证人像面图片地址。
/// </summary>
public string? LegalPersonIdFrontUrl { get; init; }
/// <summary>
/// 法人身份证国徽面图片地址。
/// </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; }
}

View File

@@ -9,13 +9,48 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
/// </summary>
public sealed record UpdateTenantAnnouncementCommand : IRequest<TenantAnnouncementDto?>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 公告 ID。
/// </summary>
public long AnnouncementId { get; init; }
/// <summary>
/// 公告标题。
/// </summary>
public string Title { get; init; } = string.Empty;
/// <summary>
/// 公告内容。
/// </summary>
public string Content { get; init; } = string.Empty;
/// <summary>
/// 公告类型。
/// </summary>
public TenantAnnouncementType AnnouncementType { get; init; } = TenantAnnouncementType.System;
/// <summary>
/// 优先级,数值越大越靠前。
/// </summary>
public int Priority { get; init; } = 0;
/// <summary>
/// 生效开始时间UTC
/// </summary>
public DateTime EffectiveFrom { get; init; } = DateTime.UtcNow;
/// <summary>
/// 生效结束时间UTC为空则长期有效。
/// </summary>
public DateTime? EffectiveTo { get; init; }
/// <summary>
/// 是否启用。
/// </summary>
public bool IsActive { get; init; } = true;
}

View File

@@ -9,27 +9,60 @@ namespace TakeoutSaaS.Application.App.Tenants.Dto;
/// </summary>
public sealed class TenantAnnouncementDto
{
/// <summary>
/// 公告 ID雪花算法序列化为字符串
/// </summary>
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long Id { get; init; }
/// <summary>
/// 租户 ID雪花算法序列化为字符串
/// </summary>
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long TenantId { get; init; }
/// <summary>
/// 公告标题。
/// </summary>
public string Title { get; init; } = string.Empty;
/// <summary>
/// 公告正文内容。
/// </summary>
public string Content { get; init; } = string.Empty;
/// <summary>
/// 公告类型。
/// </summary>
public TenantAnnouncementType AnnouncementType { get; init; }
/// <summary>
/// 优先级,数值越大越靠前。
/// </summary>
public int Priority { get; init; }
/// <summary>
/// 生效开始时间UTC
/// </summary>
public DateTime EffectiveFrom { get; init; }
/// <summary>
/// 生效结束时间UTC为空则长期有效。
/// </summary>
public DateTime? EffectiveTo { get; init; }
/// <summary>
/// 是否启用。
/// </summary>
public bool IsActive { get; init; }
/// <summary>
/// 当前用户是否已读。
/// </summary>
public bool IsRead { get; init; }
/// <summary>
/// 已读时间UTC
/// </summary>
public DateTime? ReadAt { get; init; }
}

View File

@@ -9,25 +9,55 @@ namespace TakeoutSaaS.Application.App.Tenants.Dto;
/// </summary>
public sealed class TenantBillingDto
{
/// <summary>
/// 账单 ID雪花算法序列化为字符串
/// </summary>
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long Id { get; init; }
/// <summary>
/// 租户 ID雪花算法序列化为字符串
/// </summary>
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long TenantId { get; init; }
/// <summary>
/// 账单编号。
/// </summary>
public string StatementNo { get; init; } = string.Empty;
/// <summary>
/// 计费周期开始时间UTC
/// </summary>
public DateTime PeriodStart { get; init; }
/// <summary>
/// 计费周期结束时间UTC
/// </summary>
public DateTime PeriodEnd { get; init; }
/// <summary>
/// 应付金额。
/// </summary>
public decimal AmountDue { get; init; }
/// <summary>
/// 已付金额。
/// </summary>
public decimal AmountPaid { get; init; }
/// <summary>
/// 账单状态。
/// </summary>
public TenantBillingStatus Status { get; init; }
/// <summary>
/// 到期日UTC
/// </summary>
public DateTime DueDate { get; init; }
/// <summary>
/// 账单明细 JSON。
/// </summary>
public string? LineItemsJson { get; init; }
}

View File

@@ -9,23 +9,50 @@ namespace TakeoutSaaS.Application.App.Tenants.Dto;
/// </summary>
public sealed class TenantNotificationDto
{
/// <summary>
/// 通知 ID雪花算法序列化为字符串
/// </summary>
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long Id { get; init; }
/// <summary>
/// 租户 ID雪花算法序列化为字符串
/// </summary>
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long TenantId { get; init; }
/// <summary>
/// 通知标题。
/// </summary>
public string Title { get; init; } = string.Empty;
/// <summary>
/// 通知内容。
/// </summary>
public string Message { get; init; } = string.Empty;
/// <summary>
/// 通道类型(如站内信、短信、邮件)。
/// </summary>
public TenantNotificationChannel Channel { get; init; }
/// <summary>
/// 通知等级。
/// </summary>
public TenantNotificationSeverity Severity { get; init; }
/// <summary>
/// 发送时间UTC
/// </summary>
public DateTime SentAt { get; init; }
/// <summary>
/// 阅读时间UTC
/// </summary>
public DateTime? ReadAt { get; init; }
/// <summary>
/// 附加元数据 JSON。
/// </summary>
public string? MetadataJson { get; init; }
}

View File

@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
/// </summary>
public sealed record GetTenantAnnouncementQuery : IRequest<TenantAnnouncementDto?>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 公告 ID。
/// </summary>
public long AnnouncementId { get; init; }
}

View File

@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
/// </summary>
public sealed record GetTenantBillQuery : IRequest<TenantBillingDto?>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 账单 ID。
/// </summary>
public long BillingId { get; init; }
}

View File

@@ -10,10 +10,33 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
/// </summary>
public sealed record SearchTenantAnnouncementsQuery : IRequest<PagedResult<TenantAnnouncementDto>>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 公告类型筛选。
/// </summary>
public TenantAnnouncementType? AnnouncementType { get; init; }
/// <summary>
/// 是否筛选启用状态。
/// </summary>
public bool? IsActive { get; init; }
/// <summary>
/// 仅返回当前有效期内的公告。
/// </summary>
public bool? OnlyEffective { get; init; }
/// <summary>
/// 页码(从 1 开始)。
/// </summary>
public int Page { get; init; } = 1;
/// <summary>
/// 每页条数。
/// </summary>
public int PageSize { get; init; } = 20;
}

View File

@@ -10,10 +10,33 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
/// </summary>
public sealed record SearchTenantBillsQuery : IRequest<PagedResult<TenantBillingDto>>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 账单状态筛选。
/// </summary>
public TenantBillingStatus? Status { get; init; }
/// <summary>
/// 账单起始时间UTC筛选。
/// </summary>
public DateTime? From { get; init; }
/// <summary>
/// 账单结束时间UTC筛选。
/// </summary>
public DateTime? To { get; init; }
/// <summary>
/// 页码(从 1 开始)。
/// </summary>
public int Page { get; init; } = 1;
/// <summary>
/// 每页条数。
/// </summary>
public int PageSize { get; init; } = 20;
}

View File

@@ -10,9 +10,28 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
/// </summary>
public sealed record SearchTenantNotificationsQuery : IRequest<PagedResult<TenantNotificationDto>>
{
/// <summary>
/// 租户 ID雪花算法
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 通知等级筛选。
/// </summary>
public TenantNotificationSeverity? Severity { get; init; }
/// <summary>
/// 仅返回未读通知。
/// </summary>
public bool? UnreadOnly { get; init; }
/// <summary>
/// 页码(从 1 开始)。
/// </summary>
public int Page { get; init; } = 1;
/// <summary>
/// 每页条数。
/// </summary>
public int PageSize { get; init; } = 20;
}