From bf88f0e0412bbb4d002b510e2b2b974ae09706d0 Mon Sep 17 00:00:00 2001
From: MSuMshk <2039814060@qq.com>
Date: Wed, 3 Dec 2025 22:56:35 +0800
Subject: [PATCH] docs: add xml comments for tenant modules
---
.../ChangeTenantSubscriptionPlanCommand.cs | 36 +++++++--
.../CreateTenantAnnouncementCommand.cs | 31 ++++++++
.../Commands/CreateTenantBillingCommand.cs | 35 +++++++++
.../CreateTenantSubscriptionCommand.cs | 35 +++++++--
.../DeleteTenantAnnouncementCommand.cs | 7 ++
.../MarkTenantAnnouncementReadCommand.cs | 7 ++
.../Commands/MarkTenantBillingPaidCommand.cs | 15 ++++
.../MarkTenantNotificationReadCommand.cs | 7 ++
.../Tenants/Commands/RegisterTenantCommand.cs | 74 ++++++++++++++++---
.../Tenants/Commands/ReviewTenantCommand.cs | 22 +++++-
.../SubmitTenantVerificationCommand.cs | 70 +++++++++++++++---
.../UpdateTenantAnnouncementCommand.cs | 35 +++++++++
.../App/Tenants/Dto/TenantAnnouncementDto.cs | 33 +++++++++
.../App/Tenants/Dto/TenantBillingDto.cs | 30 ++++++++
.../App/Tenants/Dto/TenantNotificationDto.cs | 27 +++++++
.../Queries/GetTenantAnnouncementQuery.cs | 7 ++
.../App/Tenants/Queries/GetTenantBillQuery.cs | 7 ++
.../Queries/SearchTenantAnnouncementsQuery.cs | 23 ++++++
.../Tenants/Queries/SearchTenantBillsQuery.cs | 23 ++++++
.../Queries/SearchTenantNotificationsQuery.cs | 19 +++++
.../ITenantAnnouncementReadRepository.cs | 32 ++++++++
.../ITenantAnnouncementRepository.cs | 36 +++++++++
.../Repositories/ITenantBillingRepository.cs | 37 ++++++++++
.../ITenantNotificationRepository.cs | 31 ++++++++
.../EfTenantAnnouncementReadRepository.cs | 5 ++
.../EfTenantAnnouncementRepository.cs | 6 ++
.../Repositories/EfTenantBillingRepository.cs | 6 ++
.../EfTenantNotificationRepository.cs | 5 ++
28 files changed, 661 insertions(+), 40 deletions(-)
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/ChangeTenantSubscriptionPlanCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/ChangeTenantSubscriptionPlanCommand.cs
index d9c6287..5c052be 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/ChangeTenantSubscriptionPlanCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/ChangeTenantSubscriptionPlanCommand.cs
@@ -7,9 +7,33 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
/// 套餐升降配命令。
///
-public sealed record ChangeTenantSubscriptionPlanCommand(
- [property: Required] long TenantId,
- [property: Required] long TenantSubscriptionId,
- [property: Required] long TargetPackageId,
- bool Immediate,
- string? Notes) : IRequest;
+public sealed record ChangeTenantSubscriptionPlanCommand : IRequest
+{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
+ [Required]
+ public long TenantId { get; init; }
+
+ ///
+ /// 现有订阅 ID。
+ ///
+ [Required]
+ public long TenantSubscriptionId { get; init; }
+
+ ///
+ /// 目标套餐 ID。
+ ///
+ [Required]
+ public long TargetPackageId { get; init; }
+
+ ///
+ /// 是否立即生效,否则在下一结算周期生效。
+ ///
+ public bool Immediate { get; init; }
+
+ ///
+ /// 调整备注。
+ ///
+ public string? Notes { get; init; }
+}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantAnnouncementCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantAnnouncementCommand.cs
index da68b6f..dd6735a 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantAnnouncementCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantAnnouncementCommand.cs
@@ -9,12 +9,43 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
public sealed record CreateTenantAnnouncementCommand : IRequest
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 公告标题。
+ ///
public string Title { get; init; } = string.Empty;
+
+ ///
+ /// 公告正文内容。
+ ///
public string Content { get; init; } = string.Empty;
+
+ ///
+ /// 公告类型。
+ ///
public TenantAnnouncementType AnnouncementType { get; init; } = TenantAnnouncementType.System;
+
+ ///
+ /// 优先级,数值越大越靠前。
+ ///
public int Priority { get; init; } = 0;
+
+ ///
+ /// 生效开始时间(UTC)。
+ ///
public DateTime EffectiveFrom { get; init; } = DateTime.UtcNow;
+
+ ///
+ /// 生效结束时间(UTC),为空则长期有效。
+ ///
public DateTime? EffectiveTo { get; init; }
+
+ ///
+ /// 是否启用。
+ ///
public bool IsActive { get; init; } = true;
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantBillingCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantBillingCommand.cs
index 16c771d..1bc64a7 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantBillingCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantBillingCommand.cs
@@ -9,13 +9,48 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
public sealed record CreateTenantBillingCommand : IRequest
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 账单编号。
+ ///
public string StatementNo { get; init; } = string.Empty;
+
+ ///
+ /// 计费周期开始时间(UTC)。
+ ///
public DateTime PeriodStart { get; init; }
+
+ ///
+ /// 计费周期结束时间(UTC)。
+ ///
public DateTime PeriodEnd { get; init; }
+
+ ///
+ /// 应付金额。
+ ///
public decimal AmountDue { get; init; }
+
+ ///
+ /// 已付金额。
+ ///
public decimal AmountPaid { get; init; }
+
+ ///
+ /// 账单状态。
+ ///
public TenantBillingStatus Status { get; init; } = TenantBillingStatus.Pending;
+
+ ///
+ /// 到期日(UTC)。
+ ///
public DateTime DueDate { get; init; }
+
+ ///
+ /// 账单明细 JSON。
+ ///
public string? LineItemsJson { get; init; }
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantSubscriptionCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantSubscriptionCommand.cs
index 468ace2..b31a92d 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantSubscriptionCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/CreateTenantSubscriptionCommand.cs
@@ -7,9 +7,32 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
/// 新建或续费订阅。
///
-public sealed record CreateTenantSubscriptionCommand(
- [property: Required] long TenantId,
- [property: Required] long TenantPackageId,
- int DurationMonths,
- bool AutoRenew,
- string? Notes) : IRequest;
+public sealed record CreateTenantSubscriptionCommand : IRequest
+{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
+ [Required]
+ public long TenantId { get; init; }
+
+ ///
+ /// 套餐 ID。
+ ///
+ [Required]
+ public long TenantPackageId { get; init; }
+
+ ///
+ /// 订阅时长(月)。
+ ///
+ public int DurationMonths { get; init; }
+
+ ///
+ /// 是否自动续费。
+ ///
+ public bool AutoRenew { get; init; }
+
+ ///
+ /// 备注信息。
+ ///
+ public string? Notes { get; init; }
+}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/DeleteTenantAnnouncementCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/DeleteTenantAnnouncementCommand.cs
index c67877c..3cd5964 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/DeleteTenantAnnouncementCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/DeleteTenantAnnouncementCommand.cs
@@ -7,6 +7,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
public sealed record DeleteTenantAnnouncementCommand : IRequest
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 公告 ID。
+ ///
public long AnnouncementId { get; init; }
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantAnnouncementReadCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantAnnouncementReadCommand.cs
index 85c679a..97ce6e1 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantAnnouncementReadCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantAnnouncementReadCommand.cs
@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
public sealed record MarkTenantAnnouncementReadCommand : IRequest
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 公告 ID。
+ ///
public long AnnouncementId { get; init; }
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantBillingPaidCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantBillingPaidCommand.cs
index 5479882..e2c9f18 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantBillingPaidCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantBillingPaidCommand.cs
@@ -8,8 +8,23 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
public sealed record MarkTenantBillingPaidCommand : IRequest
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 账单 ID。
+ ///
public long BillingId { get; init; }
+
+ ///
+ /// 本次支付金额。
+ ///
public decimal AmountPaid { get; init; }
+
+ ///
+ /// 支付时间(UTC)。
+ ///
public DateTime PaidAt { get; init; } = DateTime.UtcNow;
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantNotificationReadCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantNotificationReadCommand.cs
index 31ddb58..149a74a 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantNotificationReadCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/MarkTenantNotificationReadCommand.cs
@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
public sealed record MarkTenantNotificationReadCommand : IRequest
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 通知 ID。
+ ///
public long NotificationId { get; init; }
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/RegisterTenantCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/RegisterTenantCommand.cs
index 43cc053..d26a96b 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/RegisterTenantCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/RegisterTenantCommand.cs
@@ -7,15 +7,65 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
/// 注册租户命令。
///
-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;
+public sealed record RegisterTenantCommand : IRequest
+{
+ ///
+ /// 唯一租户编码。
+ ///
+ [Required]
+ [StringLength(64)]
+ public string Code { get; init; } = string.Empty;
+
+ ///
+ /// 租户名称。
+ ///
+ [Required]
+ [StringLength(128)]
+ public string Name { get; init; } = string.Empty;
+
+ ///
+ /// 租户简称。
+ ///
+ public string? ShortName { get; init; }
+
+ ///
+ /// 行业类型。
+ ///
+ public string? Industry { get; init; }
+
+ ///
+ /// 联系人姓名。
+ ///
+ public string? ContactName { get; init; }
+
+ ///
+ /// 联系人电话。
+ ///
+ public string? ContactPhone { get; init; }
+
+ ///
+ /// 联系人邮箱。
+ ///
+ public string? ContactEmail { get; init; }
+
+ ///
+ /// 购买套餐 ID。
+ ///
+ [Required]
+ public long TenantPackageId { get; init; }
+
+ ///
+ /// 订阅时长(月),默认 12 个月。
+ ///
+ public int DurationMonths { get; init; } = 12;
+
+ ///
+ /// 是否自动续费。
+ ///
+ public bool AutoRenew { get; init; } = true;
+
+ ///
+ /// 生效时间(UTC),为空则立即生效。
+ ///
+ public DateTime? EffectiveFrom { get; init; }
+}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/ReviewTenantCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/ReviewTenantCommand.cs
index 5784f9b..7b1c6b6 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/ReviewTenantCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/ReviewTenantCommand.cs
@@ -7,7 +7,21 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
/// 审核租户命令。
///
-public sealed record ReviewTenantCommand(
- [property: Required] long TenantId,
- bool Approve,
- string? Reason) : IRequest;
+public sealed record ReviewTenantCommand : IRequest
+{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
+ [Required]
+ public long TenantId { get; init; }
+
+ ///
+ /// 是否通过审核。
+ ///
+ public bool Approve { get; init; }
+
+ ///
+ /// 审核备注或拒绝原因。
+ ///
+ public string? Reason { get; init; }
+}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SubmitTenantVerificationCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SubmitTenantVerificationCommand.cs
index 8a94a46..94de46d 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SubmitTenantVerificationCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/SubmitTenantVerificationCommand.cs
@@ -7,15 +7,61 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
/// 提交租户实名认证资料。
///
-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;
+public sealed record SubmitTenantVerificationCommand : IRequest
+{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
+ [Required]
+ public long TenantId { get; init; }
+
+ ///
+ /// 营业执照编号。
+ ///
+ public string? BusinessLicenseNumber { get; init; }
+
+ ///
+ /// 营业执照扫描件地址。
+ ///
+ public string? BusinessLicenseUrl { get; init; }
+
+ ///
+ /// 法人姓名。
+ ///
+ public string? LegalPersonName { get; init; }
+
+ ///
+ /// 法人身份证号。
+ ///
+ public string? LegalPersonIdNumber { get; init; }
+
+ ///
+ /// 法人身份证人像面图片地址。
+ ///
+ public string? LegalPersonIdFrontUrl { get; init; }
+
+ ///
+ /// 法人身份证国徽面图片地址。
+ ///
+ public string? LegalPersonIdBackUrl { get; init; }
+
+ ///
+ /// 对公账户户名。
+ ///
+ public string? BankAccountName { get; init; }
+
+ ///
+ /// 对公银行账号。
+ ///
+ public string? BankAccountNumber { get; init; }
+
+ ///
+ /// 开户行名称。
+ ///
+ public string? BankName { get; init; }
+
+ ///
+ /// 其他补充资料 JSON。
+ ///
+ public string? AdditionalDataJson { get; init; }
+}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantAnnouncementCommand.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantAnnouncementCommand.cs
index 57c6569..b495d69 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantAnnouncementCommand.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Commands/UpdateTenantAnnouncementCommand.cs
@@ -9,13 +9,48 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
///
public sealed record UpdateTenantAnnouncementCommand : IRequest
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 公告 ID。
+ ///
public long AnnouncementId { get; init; }
+
+ ///
+ /// 公告标题。
+ ///
public string Title { get; init; } = string.Empty;
+
+ ///
+ /// 公告内容。
+ ///
public string Content { get; init; } = string.Empty;
+
+ ///
+ /// 公告类型。
+ ///
public TenantAnnouncementType AnnouncementType { get; init; } = TenantAnnouncementType.System;
+
+ ///
+ /// 优先级,数值越大越靠前。
+ ///
public int Priority { get; init; } = 0;
+
+ ///
+ /// 生效开始时间(UTC)。
+ ///
public DateTime EffectiveFrom { get; init; } = DateTime.UtcNow;
+
+ ///
+ /// 生效结束时间(UTC),为空则长期有效。
+ ///
public DateTime? EffectiveTo { get; init; }
+
+ ///
+ /// 是否启用。
+ ///
public bool IsActive { get; init; } = true;
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantAnnouncementDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantAnnouncementDto.cs
index 5a0a7bf..79fbbe8 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantAnnouncementDto.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantAnnouncementDto.cs
@@ -9,27 +9,60 @@ namespace TakeoutSaaS.Application.App.Tenants.Dto;
///
public sealed class TenantAnnouncementDto
{
+ ///
+ /// 公告 ID(雪花算法,序列化为字符串)。
+ ///
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long Id { get; init; }
+ ///
+ /// 租户 ID(雪花算法,序列化为字符串)。
+ ///
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long TenantId { get; init; }
+ ///
+ /// 公告标题。
+ ///
public string Title { get; init; } = string.Empty;
+ ///
+ /// 公告正文内容。
+ ///
public string Content { get; init; } = string.Empty;
+ ///
+ /// 公告类型。
+ ///
public TenantAnnouncementType AnnouncementType { get; init; }
+ ///
+ /// 优先级,数值越大越靠前。
+ ///
public int Priority { get; init; }
+ ///
+ /// 生效开始时间(UTC)。
+ ///
public DateTime EffectiveFrom { get; init; }
+ ///
+ /// 生效结束时间(UTC),为空则长期有效。
+ ///
public DateTime? EffectiveTo { get; init; }
+ ///
+ /// 是否启用。
+ ///
public bool IsActive { get; init; }
+ ///
+ /// 当前用户是否已读。
+ ///
public bool IsRead { get; init; }
+ ///
+ /// 已读时间(UTC)。
+ ///
public DateTime? ReadAt { get; init; }
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantBillingDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantBillingDto.cs
index d2b426b..1007224 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantBillingDto.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantBillingDto.cs
@@ -9,25 +9,55 @@ namespace TakeoutSaaS.Application.App.Tenants.Dto;
///
public sealed class TenantBillingDto
{
+ ///
+ /// 账单 ID(雪花算法,序列化为字符串)。
+ ///
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long Id { get; init; }
+ ///
+ /// 租户 ID(雪花算法,序列化为字符串)。
+ ///
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long TenantId { get; init; }
+ ///
+ /// 账单编号。
+ ///
public string StatementNo { get; init; } = string.Empty;
+ ///
+ /// 计费周期开始时间(UTC)。
+ ///
public DateTime PeriodStart { get; init; }
+ ///
+ /// 计费周期结束时间(UTC)。
+ ///
public DateTime PeriodEnd { get; init; }
+ ///
+ /// 应付金额。
+ ///
public decimal AmountDue { get; init; }
+ ///
+ /// 已付金额。
+ ///
public decimal AmountPaid { get; init; }
+ ///
+ /// 账单状态。
+ ///
public TenantBillingStatus Status { get; init; }
+ ///
+ /// 到期日(UTC)。
+ ///
public DateTime DueDate { get; init; }
+ ///
+ /// 账单明细 JSON。
+ ///
public string? LineItemsJson { get; init; }
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantNotificationDto.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantNotificationDto.cs
index e6ab6a9..9a33244 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantNotificationDto.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Dto/TenantNotificationDto.cs
@@ -9,23 +9,50 @@ namespace TakeoutSaaS.Application.App.Tenants.Dto;
///
public sealed class TenantNotificationDto
{
+ ///
+ /// 通知 ID(雪花算法,序列化为字符串)。
+ ///
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long Id { get; init; }
+ ///
+ /// 租户 ID(雪花算法,序列化为字符串)。
+ ///
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long TenantId { get; init; }
+ ///
+ /// 通知标题。
+ ///
public string Title { get; init; } = string.Empty;
+ ///
+ /// 通知内容。
+ ///
public string Message { get; init; } = string.Empty;
+ ///
+ /// 通道类型(如站内信、短信、邮件)。
+ ///
public TenantNotificationChannel Channel { get; init; }
+ ///
+ /// 通知等级。
+ ///
public TenantNotificationSeverity Severity { get; init; }
+ ///
+ /// 发送时间(UTC)。
+ ///
public DateTime SentAt { get; init; }
+ ///
+ /// 阅读时间(UTC)。
+ ///
public DateTime? ReadAt { get; init; }
+ ///
+ /// 附加元数据 JSON。
+ ///
public string? MetadataJson { get; init; }
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantAnnouncementQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantAnnouncementQuery.cs
index 52bdcfb..74a28b3 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantAnnouncementQuery.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantAnnouncementQuery.cs
@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
///
public sealed record GetTenantAnnouncementQuery : IRequest
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 公告 ID。
+ ///
public long AnnouncementId { get; init; }
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantBillQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantBillQuery.cs
index f22eb99..a5ece15 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantBillQuery.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/GetTenantBillQuery.cs
@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
///
public sealed record GetTenantBillQuery : IRequest
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 账单 ID。
+ ///
public long BillingId { get; init; }
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantAnnouncementsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantAnnouncementsQuery.cs
index 3f059ad..140acb1 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantAnnouncementsQuery.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantAnnouncementsQuery.cs
@@ -10,10 +10,33 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
///
public sealed record SearchTenantAnnouncementsQuery : IRequest>
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 公告类型筛选。
+ ///
public TenantAnnouncementType? AnnouncementType { get; init; }
+
+ ///
+ /// 是否筛选启用状态。
+ ///
public bool? IsActive { get; init; }
+
+ ///
+ /// 仅返回当前有效期内的公告。
+ ///
public bool? OnlyEffective { get; init; }
+
+ ///
+ /// 页码(从 1 开始)。
+ ///
public int Page { get; init; } = 1;
+
+ ///
+ /// 每页条数。
+ ///
public int PageSize { get; init; } = 20;
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantBillsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantBillsQuery.cs
index b8747e0..67d0103 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantBillsQuery.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantBillsQuery.cs
@@ -10,10 +10,33 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
///
public sealed record SearchTenantBillsQuery : IRequest>
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 账单状态筛选。
+ ///
public TenantBillingStatus? Status { get; init; }
+
+ ///
+ /// 账单起始时间(UTC)筛选。
+ ///
public DateTime? From { get; init; }
+
+ ///
+ /// 账单结束时间(UTC)筛选。
+ ///
public DateTime? To { get; init; }
+
+ ///
+ /// 页码(从 1 开始)。
+ ///
public int Page { get; init; } = 1;
+
+ ///
+ /// 每页条数。
+ ///
public int PageSize { get; init; } = 20;
}
diff --git a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantNotificationsQuery.cs b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantNotificationsQuery.cs
index 92875ff..ff5e8eb 100644
--- a/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantNotificationsQuery.cs
+++ b/src/Application/TakeoutSaaS.Application/App/Tenants/Queries/SearchTenantNotificationsQuery.cs
@@ -10,9 +10,28 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
///
public sealed record SearchTenantNotificationsQuery : IRequest>
{
+ ///
+ /// 租户 ID(雪花算法)。
+ ///
public long TenantId { get; init; }
+
+ ///
+ /// 通知等级筛选。
+ ///
public TenantNotificationSeverity? Severity { get; init; }
+
+ ///
+ /// 仅返回未读通知。
+ ///
public bool? UnreadOnly { get; init; }
+
+ ///
+ /// 页码(从 1 开始)。
+ ///
public int Page { get; init; } = 1;
+
+ ///
+ /// 每页条数。
+ ///
public int PageSize { get; init; } = 20;
}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementReadRepository.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementReadRepository.cs
index 5265ff2..ac76bc8 100644
--- a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementReadRepository.cs
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementReadRepository.cs
@@ -10,13 +10,45 @@ namespace TakeoutSaaS.Domain.Tenants.Repositories;
///
public interface ITenantAnnouncementReadRepository
{
+ ///
+ /// 按公告查询已读记录。
+ ///
+ /// 租户 ID。
+ /// 公告 ID。
+ /// 取消标记。
+ /// 指定公告的已读列表。
Task> GetByAnnouncementAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default);
+ ///
+ /// 批量按公告查询已读记录,可选按用户过滤。
+ ///
+ /// 租户 ID。
+ /// 公告 ID 集合。
+ /// 用户 ID,空则不按用户筛选。
+ /// 取消标记。
+ /// 匹配条件的已读列表。
Task> GetByAnnouncementAsync(long tenantId, IEnumerable announcementIds, long? userId, CancellationToken cancellationToken = default);
+ ///
+ /// 查询指定用户对某公告的已读记录。
+ ///
+ /// 租户 ID。
+ /// 公告 ID。
+ /// 用户 ID。
+ /// 取消标记。
+ /// 已读记录,未读返回 null。
Task FindAsync(long tenantId, long announcementId, long? userId, CancellationToken cancellationToken = default);
+ ///
+ /// 新增已读记录。
+ ///
+ /// 已读实体。
+ /// 取消标记。
Task AddAsync(TenantAnnouncementRead record, CancellationToken cancellationToken = default);
+ ///
+ /// 保存变更。
+ ///
+ /// 取消标记。
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementRepository.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementRepository.cs
index f42b041..c3e34b6 100644
--- a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementRepository.cs
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantAnnouncementRepository.cs
@@ -11,6 +11,15 @@ namespace TakeoutSaaS.Domain.Tenants.Repositories;
///
public interface ITenantAnnouncementRepository
{
+ ///
+ /// 查询公告列表,按类型、启用状态与生效时间筛选。
+ ///
+ /// 租户 ID。
+ /// 公告类型。
+ /// 启用状态。
+ /// 生效时间点,为空不限制。
+ /// 取消标记。
+ /// 公告集合。
Task> SearchAsync(
long tenantId,
TenantAnnouncementType? type,
@@ -18,13 +27,40 @@ public interface ITenantAnnouncementRepository
DateTime? effectiveAt,
CancellationToken cancellationToken = default);
+ ///
+ /// 按 ID 获取公告。
+ ///
+ /// 租户 ID。
+ /// 公告 ID。
+ /// 取消标记。
+ /// 公告实体或 null。
Task FindByIdAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default);
+ ///
+ /// 新增公告。
+ ///
+ /// 公告实体。
+ /// 取消标记。
Task AddAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default);
+ ///
+ /// 更新公告。
+ ///
+ /// 公告实体。
+ /// 取消标记。
Task UpdateAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default);
+ ///
+ /// 删除公告。
+ ///
+ /// 租户 ID。
+ /// 公告 ID。
+ /// 取消标记。
Task DeleteAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default);
+ ///
+ /// 保存变更。
+ ///
+ /// 取消标记。
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantBillingRepository.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantBillingRepository.cs
index 88d7fef..d4ddfa8 100644
--- a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantBillingRepository.cs
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantBillingRepository.cs
@@ -11,6 +11,15 @@ namespace TakeoutSaaS.Domain.Tenants.Repositories;
///
public interface ITenantBillingRepository
{
+ ///
+ /// 查询账单列表,按状态与时间范围筛选。
+ ///
+ /// 租户 ID。
+ /// 账单状态。
+ /// 开始时间(UTC)。
+ /// 结束时间(UTC)。
+ /// 取消标记。
+ /// 账单集合。
Task> SearchAsync(
long tenantId,
TenantBillingStatus? status,
@@ -18,13 +27,41 @@ public interface ITenantBillingRepository
DateTime? to,
CancellationToken cancellationToken = default);
+ ///
+ /// 按 ID 获取账单。
+ ///
+ /// 租户 ID。
+ /// 账单 ID。
+ /// 取消标记。
+ /// 账单实体或 null。
Task FindByIdAsync(long tenantId, long billingId, CancellationToken cancellationToken = default);
+ ///
+ /// 按账单编号获取账单。
+ ///
+ /// 租户 ID。
+ /// 账单编号。
+ /// 取消标记。
+ /// 账单实体或 null。
Task FindByStatementNoAsync(long tenantId, string statementNo, CancellationToken cancellationToken = default);
+ ///
+ /// 新增账单。
+ ///
+ /// 账单实体。
+ /// 取消标记。
Task AddAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default);
+ ///
+ /// 更新账单。
+ ///
+ /// 账单实体。
+ /// 取消标记。
Task UpdateAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default);
+ ///
+ /// 保存变更。
+ ///
+ /// 取消标记。
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantNotificationRepository.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantNotificationRepository.cs
index 2ee3735..b66093d 100644
--- a/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantNotificationRepository.cs
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Repositories/ITenantNotificationRepository.cs
@@ -11,6 +11,16 @@ namespace TakeoutSaaS.Domain.Tenants.Repositories;
///
public interface ITenantNotificationRepository
{
+ ///
+ /// 查询通知列表,按等级、未读状态与时间范围筛选。
+ ///
+ /// 租户 ID。
+ /// 通知等级。
+ /// 仅返回未读。
+ /// 开始时间(UTC)。
+ /// 结束时间(UTC)。
+ /// 取消标记。
+ /// 通知集合。
Task> SearchAsync(
long tenantId,
TenantNotificationSeverity? severity,
@@ -19,11 +29,32 @@ public interface ITenantNotificationRepository
DateTime? to,
CancellationToken cancellationToken = default);
+ ///
+ /// 按 ID 获取通知。
+ ///
+ /// 租户 ID。
+ /// 通知 ID。
+ /// 取消标记。
+ /// 通知实体或 null。
Task FindByIdAsync(long tenantId, long notificationId, CancellationToken cancellationToken = default);
+ ///
+ /// 新增通知。
+ ///
+ /// 通知实体。
+ /// 取消标记。
Task AddAsync(TenantNotification notification, CancellationToken cancellationToken = default);
+ ///
+ /// 更新通知。
+ ///
+ /// 通知实体。
+ /// 取消标记。
Task UpdateAsync(TenantNotification notification, CancellationToken cancellationToken = default);
+ ///
+ /// 保存变更。
+ ///
+ /// 取消标记。
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementReadRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementReadRepository.cs
index 96a1fd3..94b26a2 100644
--- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementReadRepository.cs
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementReadRepository.cs
@@ -11,6 +11,7 @@ namespace TakeoutSaaS.Infrastructure.App.Repositories;
///
public sealed class EfTenantAnnouncementReadRepository(TakeoutAppDbContext context) : ITenantAnnouncementReadRepository
{
+ ///
public Task> GetByAnnouncementAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default)
{
return context.TenantAnnouncementReads.AsNoTracking()
@@ -20,6 +21,7 @@ public sealed class EfTenantAnnouncementReadRepository(TakeoutAppDbContext conte
.ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken);
}
+ ///
public Task> GetByAnnouncementAsync(long tenantId, IEnumerable announcementIds, long? userId, CancellationToken cancellationToken = default)
{
var ids = announcementIds.Distinct().ToArray();
@@ -46,17 +48,20 @@ public sealed class EfTenantAnnouncementReadRepository(TakeoutAppDbContext conte
.ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken);
}
+ ///
public Task FindAsync(long tenantId, long announcementId, long? userId, CancellationToken cancellationToken = default)
{
return context.TenantAnnouncementReads
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.AnnouncementId == announcementId && x.UserId == userId, cancellationToken);
}
+ ///
public Task AddAsync(TenantAnnouncementRead record, CancellationToken cancellationToken = default)
{
return context.TenantAnnouncementReads.AddAsync(record, cancellationToken).AsTask();
}
+ ///
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
{
return context.SaveChangesAsync(cancellationToken);
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementRepository.cs
index a03d206..404152f 100644
--- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementRepository.cs
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantAnnouncementRepository.cs
@@ -12,6 +12,7 @@ namespace TakeoutSaaS.Infrastructure.App.Repositories;
///
public sealed class EfTenantAnnouncementRepository(TakeoutAppDbContext context) : ITenantAnnouncementRepository
{
+ ///
public Task> SearchAsync(
long tenantId,
TenantAnnouncementType? type,
@@ -45,23 +46,27 @@ public sealed class EfTenantAnnouncementRepository(TakeoutAppDbContext context)
.ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken);
}
+ ///
public Task FindByIdAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default)
{
return context.TenantAnnouncements.AsNoTracking()
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == announcementId, cancellationToken);
}
+ ///
public Task AddAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default)
{
return context.TenantAnnouncements.AddAsync(announcement, cancellationToken).AsTask();
}
+ ///
public Task UpdateAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default)
{
context.TenantAnnouncements.Update(announcement);
return Task.CompletedTask;
}
+ ///
public async Task DeleteAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default)
{
var entity = await context.TenantAnnouncements.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == announcementId, cancellationToken);
@@ -71,6 +76,7 @@ public sealed class EfTenantAnnouncementRepository(TakeoutAppDbContext context)
}
}
+ ///
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
{
return context.SaveChangesAsync(cancellationToken);
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantBillingRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantBillingRepository.cs
index 23acd1d..3083de5 100644
--- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantBillingRepository.cs
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantBillingRepository.cs
@@ -12,6 +12,7 @@ namespace TakeoutSaaS.Infrastructure.App.Repositories;
///
public sealed class EfTenantBillingRepository(TakeoutAppDbContext context) : ITenantBillingRepository
{
+ ///
public Task> SearchAsync(
long tenantId,
TenantBillingStatus? status,
@@ -43,29 +44,34 @@ public sealed class EfTenantBillingRepository(TakeoutAppDbContext context) : ITe
.ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken);
}
+ ///
public Task FindByIdAsync(long tenantId, long billingId, CancellationToken cancellationToken = default)
{
return context.TenantBillingStatements.AsNoTracking()
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == billingId, cancellationToken);
}
+ ///
public Task FindByStatementNoAsync(long tenantId, string statementNo, CancellationToken cancellationToken = default)
{
return context.TenantBillingStatements.AsNoTracking()
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.StatementNo == statementNo, cancellationToken);
}
+ ///
public Task AddAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default)
{
return context.TenantBillingStatements.AddAsync(bill, cancellationToken).AsTask();
}
+ ///
public Task UpdateAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default)
{
context.TenantBillingStatements.Update(bill);
return Task.CompletedTask;
}
+ ///
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
{
return context.SaveChangesAsync(cancellationToken);
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantNotificationRepository.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantNotificationRepository.cs
index 1265c25..56cea39 100644
--- a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantNotificationRepository.cs
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Repositories/EfTenantNotificationRepository.cs
@@ -12,6 +12,7 @@ namespace TakeoutSaaS.Infrastructure.App.Repositories;
///
public sealed class EfTenantNotificationRepository(TakeoutAppDbContext context) : ITenantNotificationRepository
{
+ ///
public Task> SearchAsync(
long tenantId,
TenantNotificationSeverity? severity,
@@ -49,23 +50,27 @@ public sealed class EfTenantNotificationRepository(TakeoutAppDbContext context)
.ContinueWith(t => (IReadOnlyList)t.Result, cancellationToken);
}
+ ///
public Task FindByIdAsync(long tenantId, long notificationId, CancellationToken cancellationToken = default)
{
return context.TenantNotifications
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == notificationId, cancellationToken);
}
+ ///
public Task AddAsync(TenantNotification notification, CancellationToken cancellationToken = default)
{
return context.TenantNotifications.AddAsync(notification, cancellationToken).AsTask();
}
+ ///
public Task UpdateAsync(TenantNotification notification, CancellationToken cancellationToken = default)
{
context.TenantNotifications.Update(notification);
return Task.CompletedTask;
}
+ ///
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
{
return context.SaveChangesAsync(cancellationToken);