docs: add xml comments for tenant modules
This commit is contained in:
@@ -7,9 +7,33 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 套餐升降配命令。
|
/// 套餐升降配命令。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record ChangeTenantSubscriptionPlanCommand(
|
public sealed record ChangeTenantSubscriptionPlanCommand : IRequest<TenantSubscriptionDto>
|
||||||
[property: Required] long TenantId,
|
{
|
||||||
[property: Required] long TenantSubscriptionId,
|
/// <summary>
|
||||||
[property: Required] long TargetPackageId,
|
/// 租户 ID(雪花算法)。
|
||||||
bool Immediate,
|
/// </summary>
|
||||||
string? Notes) : IRequest<TenantSubscriptionDto>;
|
[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; }
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,12 +9,43 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record CreateTenantAnnouncementCommand : IRequest<TenantAnnouncementDto>
|
public sealed record CreateTenantAnnouncementCommand : IRequest<TenantAnnouncementDto>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告标题。
|
||||||
|
/// </summary>
|
||||||
public string Title { get; init; } = string.Empty;
|
public string Title { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告正文内容。
|
||||||
|
/// </summary>
|
||||||
public string Content { get; init; } = string.Empty;
|
public string Content { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告类型。
|
||||||
|
/// </summary>
|
||||||
public TenantAnnouncementType AnnouncementType { get; init; } = TenantAnnouncementType.System;
|
public TenantAnnouncementType AnnouncementType { get; init; } = TenantAnnouncementType.System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 优先级,数值越大越靠前。
|
||||||
|
/// </summary>
|
||||||
public int Priority { get; init; } = 0;
|
public int Priority { get; init; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生效开始时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime EffectiveFrom { get; init; } = DateTime.UtcNow;
|
public DateTime EffectiveFrom { get; init; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生效结束时间(UTC),为空则长期有效。
|
||||||
|
/// </summary>
|
||||||
public DateTime? EffectiveTo { get; init; }
|
public DateTime? EffectiveTo { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用。
|
||||||
|
/// </summary>
|
||||||
public bool IsActive { get; init; } = true;
|
public bool IsActive { get; init; } = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,13 +9,48 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record CreateTenantBillingCommand : IRequest<TenantBillingDto>
|
public sealed record CreateTenantBillingCommand : IRequest<TenantBillingDto>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单编号。
|
||||||
|
/// </summary>
|
||||||
public string StatementNo { get; init; } = string.Empty;
|
public string StatementNo { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计费周期开始时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime PeriodStart { get; init; }
|
public DateTime PeriodStart { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计费周期结束时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime PeriodEnd { get; init; }
|
public DateTime PeriodEnd { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应付金额。
|
||||||
|
/// </summary>
|
||||||
public decimal AmountDue { get; init; }
|
public decimal AmountDue { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 已付金额。
|
||||||
|
/// </summary>
|
||||||
public decimal AmountPaid { get; init; }
|
public decimal AmountPaid { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单状态。
|
||||||
|
/// </summary>
|
||||||
public TenantBillingStatus Status { get; init; } = TenantBillingStatus.Pending;
|
public TenantBillingStatus Status { get; init; } = TenantBillingStatus.Pending;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 到期日(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime DueDate { get; init; }
|
public DateTime DueDate { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单明细 JSON。
|
||||||
|
/// </summary>
|
||||||
public string? LineItemsJson { get; init; }
|
public string? LineItemsJson { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,32 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 新建或续费订阅。
|
/// 新建或续费订阅。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record CreateTenantSubscriptionCommand(
|
public sealed record CreateTenantSubscriptionCommand : IRequest<TenantSubscriptionDto>
|
||||||
[property: Required] long TenantId,
|
{
|
||||||
[property: Required] long TenantPackageId,
|
/// <summary>
|
||||||
int DurationMonths,
|
/// 租户 ID(雪花算法)。
|
||||||
bool AutoRenew,
|
/// </summary>
|
||||||
string? Notes) : IRequest<TenantSubscriptionDto>;
|
[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; }
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record DeleteTenantAnnouncementCommand : IRequest<bool>
|
public sealed record DeleteTenantAnnouncementCommand : IRequest<bool>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告 ID。
|
||||||
|
/// </summary>
|
||||||
public long AnnouncementId { get; init; }
|
public long AnnouncementId { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record MarkTenantAnnouncementReadCommand : IRequest<TenantAnnouncementDto?>
|
public sealed record MarkTenantAnnouncementReadCommand : IRequest<TenantAnnouncementDto?>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告 ID。
|
||||||
|
/// </summary>
|
||||||
public long AnnouncementId { get; init; }
|
public long AnnouncementId { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,8 +8,23 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record MarkTenantBillingPaidCommand : IRequest<TenantBillingDto?>
|
public sealed record MarkTenantBillingPaidCommand : IRequest<TenantBillingDto?>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单 ID。
|
||||||
|
/// </summary>
|
||||||
public long BillingId { get; init; }
|
public long BillingId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 本次支付金额。
|
||||||
|
/// </summary>
|
||||||
public decimal AmountPaid { get; init; }
|
public decimal AmountPaid { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 支付时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime PaidAt { get; init; } = DateTime.UtcNow;
|
public DateTime PaidAt { get; init; } = DateTime.UtcNow;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record MarkTenantNotificationReadCommand : IRequest<TenantNotificationDto?>
|
public sealed record MarkTenantNotificationReadCommand : IRequest<TenantNotificationDto?>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通知 ID。
|
||||||
|
/// </summary>
|
||||||
public long NotificationId { get; init; }
|
public long NotificationId { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,15 +7,65 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 注册租户命令。
|
/// 注册租户命令。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record RegisterTenantCommand(
|
public sealed record RegisterTenantCommand : IRequest<TenantDto>
|
||||||
[property: Required, StringLength(64)] string Code,
|
{
|
||||||
[property: Required, StringLength(128)] string Name,
|
/// <summary>
|
||||||
string? ShortName,
|
/// 唯一租户编码。
|
||||||
string? Industry,
|
/// </summary>
|
||||||
string? ContactName,
|
[Required]
|
||||||
string? ContactPhone,
|
[StringLength(64)]
|
||||||
string? ContactEmail,
|
public string Code { get; init; } = string.Empty;
|
||||||
[property: Required] long TenantPackageId,
|
|
||||||
int DurationMonths = 12,
|
/// <summary>
|
||||||
bool AutoRenew = true,
|
/// 租户名称。
|
||||||
DateTime? EffectiveFrom = null) : IRequest<TenantDto>;
|
/// </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; }
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,7 +7,21 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 审核租户命令。
|
/// 审核租户命令。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record ReviewTenantCommand(
|
public sealed record ReviewTenantCommand : IRequest<TenantDto>
|
||||||
[property: Required] long TenantId,
|
{
|
||||||
bool Approve,
|
/// <summary>
|
||||||
string? Reason) : IRequest<TenantDto>;
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
|
[Required]
|
||||||
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否通过审核。
|
||||||
|
/// </summary>
|
||||||
|
public bool Approve { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 审核备注或拒绝原因。
|
||||||
|
/// </summary>
|
||||||
|
public string? Reason { get; init; }
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,15 +7,61 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 提交租户实名认证资料。
|
/// 提交租户实名认证资料。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record SubmitTenantVerificationCommand(
|
public sealed record SubmitTenantVerificationCommand : IRequest<TenantVerificationDto>
|
||||||
[property: Required] long TenantId,
|
{
|
||||||
string? BusinessLicenseNumber,
|
/// <summary>
|
||||||
string? BusinessLicenseUrl,
|
/// 租户 ID(雪花算法)。
|
||||||
string? LegalPersonName,
|
/// </summary>
|
||||||
string? LegalPersonIdNumber,
|
[Required]
|
||||||
string? LegalPersonIdFrontUrl,
|
public long TenantId { get; init; }
|
||||||
string? LegalPersonIdBackUrl,
|
|
||||||
string? BankAccountName,
|
/// <summary>
|
||||||
string? BankAccountNumber,
|
/// 营业执照编号。
|
||||||
string? BankName,
|
/// </summary>
|
||||||
string? AdditionalDataJson) : IRequest<TenantVerificationDto>;
|
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; }
|
||||||
|
}
|
||||||
|
|||||||
@@ -9,13 +9,48 @@ namespace TakeoutSaaS.Application.App.Tenants.Commands;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record UpdateTenantAnnouncementCommand : IRequest<TenantAnnouncementDto?>
|
public sealed record UpdateTenantAnnouncementCommand : IRequest<TenantAnnouncementDto?>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告 ID。
|
||||||
|
/// </summary>
|
||||||
public long AnnouncementId { get; init; }
|
public long AnnouncementId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告标题。
|
||||||
|
/// </summary>
|
||||||
public string Title { get; init; } = string.Empty;
|
public string Title { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告内容。
|
||||||
|
/// </summary>
|
||||||
public string Content { get; init; } = string.Empty;
|
public string Content { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告类型。
|
||||||
|
/// </summary>
|
||||||
public TenantAnnouncementType AnnouncementType { get; init; } = TenantAnnouncementType.System;
|
public TenantAnnouncementType AnnouncementType { get; init; } = TenantAnnouncementType.System;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 优先级,数值越大越靠前。
|
||||||
|
/// </summary>
|
||||||
public int Priority { get; init; } = 0;
|
public int Priority { get; init; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生效开始时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime EffectiveFrom { get; init; } = DateTime.UtcNow;
|
public DateTime EffectiveFrom { get; init; } = DateTime.UtcNow;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生效结束时间(UTC),为空则长期有效。
|
||||||
|
/// </summary>
|
||||||
public DateTime? EffectiveTo { get; init; }
|
public DateTime? EffectiveTo { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用。
|
||||||
|
/// </summary>
|
||||||
public bool IsActive { get; init; } = true;
|
public bool IsActive { get; init; } = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,27 +9,60 @@ namespace TakeoutSaaS.Application.App.Tenants.Dto;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class TenantAnnouncementDto
|
public sealed class TenantAnnouncementDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 公告 ID(雪花算法,序列化为字符串)。
|
||||||
|
/// </summary>
|
||||||
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
||||||
public long Id { get; init; }
|
public long Id { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法,序列化为字符串)。
|
||||||
|
/// </summary>
|
||||||
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告标题。
|
||||||
|
/// </summary>
|
||||||
public string Title { get; init; } = string.Empty;
|
public string Title { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告正文内容。
|
||||||
|
/// </summary>
|
||||||
public string Content { get; init; } = string.Empty;
|
public string Content { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告类型。
|
||||||
|
/// </summary>
|
||||||
public TenantAnnouncementType AnnouncementType { get; init; }
|
public TenantAnnouncementType AnnouncementType { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 优先级,数值越大越靠前。
|
||||||
|
/// </summary>
|
||||||
public int Priority { get; init; }
|
public int Priority { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生效开始时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime EffectiveFrom { get; init; }
|
public DateTime EffectiveFrom { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生效结束时间(UTC),为空则长期有效。
|
||||||
|
/// </summary>
|
||||||
public DateTime? EffectiveTo { get; init; }
|
public DateTime? EffectiveTo { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否启用。
|
||||||
|
/// </summary>
|
||||||
public bool IsActive { get; init; }
|
public bool IsActive { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 当前用户是否已读。
|
||||||
|
/// </summary>
|
||||||
public bool IsRead { get; init; }
|
public bool IsRead { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 已读时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime? ReadAt { get; init; }
|
public DateTime? ReadAt { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,25 +9,55 @@ namespace TakeoutSaaS.Application.App.Tenants.Dto;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class TenantBillingDto
|
public sealed class TenantBillingDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 账单 ID(雪花算法,序列化为字符串)。
|
||||||
|
/// </summary>
|
||||||
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
||||||
public long Id { get; init; }
|
public long Id { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法,序列化为字符串)。
|
||||||
|
/// </summary>
|
||||||
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单编号。
|
||||||
|
/// </summary>
|
||||||
public string StatementNo { get; init; } = string.Empty;
|
public string StatementNo { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计费周期开始时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime PeriodStart { get; init; }
|
public DateTime PeriodStart { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 计费周期结束时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime PeriodEnd { get; init; }
|
public DateTime PeriodEnd { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 应付金额。
|
||||||
|
/// </summary>
|
||||||
public decimal AmountDue { get; init; }
|
public decimal AmountDue { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 已付金额。
|
||||||
|
/// </summary>
|
||||||
public decimal AmountPaid { get; init; }
|
public decimal AmountPaid { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单状态。
|
||||||
|
/// </summary>
|
||||||
public TenantBillingStatus Status { get; init; }
|
public TenantBillingStatus Status { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 到期日(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime DueDate { get; init; }
|
public DateTime DueDate { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单明细 JSON。
|
||||||
|
/// </summary>
|
||||||
public string? LineItemsJson { get; init; }
|
public string? LineItemsJson { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,23 +9,50 @@ namespace TakeoutSaaS.Application.App.Tenants.Dto;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class TenantNotificationDto
|
public sealed class TenantNotificationDto
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 通知 ID(雪花算法,序列化为字符串)。
|
||||||
|
/// </summary>
|
||||||
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
||||||
public long Id { get; init; }
|
public long Id { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法,序列化为字符串)。
|
||||||
|
/// </summary>
|
||||||
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通知标题。
|
||||||
|
/// </summary>
|
||||||
public string Title { get; init; } = string.Empty;
|
public string Title { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通知内容。
|
||||||
|
/// </summary>
|
||||||
public string Message { get; init; } = string.Empty;
|
public string Message { get; init; } = string.Empty;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通道类型(如站内信、短信、邮件)。
|
||||||
|
/// </summary>
|
||||||
public TenantNotificationChannel Channel { get; init; }
|
public TenantNotificationChannel Channel { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通知等级。
|
||||||
|
/// </summary>
|
||||||
public TenantNotificationSeverity Severity { get; init; }
|
public TenantNotificationSeverity Severity { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 发送时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime SentAt { get; init; }
|
public DateTime SentAt { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 阅读时间(UTC)。
|
||||||
|
/// </summary>
|
||||||
public DateTime? ReadAt { get; init; }
|
public DateTime? ReadAt { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 附加元数据 JSON。
|
||||||
|
/// </summary>
|
||||||
public string? MetadataJson { get; init; }
|
public string? MetadataJson { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record GetTenantAnnouncementQuery : IRequest<TenantAnnouncementDto?>
|
public sealed record GetTenantAnnouncementQuery : IRequest<TenantAnnouncementDto?>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告 ID。
|
||||||
|
/// </summary>
|
||||||
public long AnnouncementId { get; init; }
|
public long AnnouncementId { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record GetTenantBillQuery : IRequest<TenantBillingDto?>
|
public sealed record GetTenantBillQuery : IRequest<TenantBillingDto?>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单 ID。
|
||||||
|
/// </summary>
|
||||||
public long BillingId { get; init; }
|
public long BillingId { get; init; }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,33 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record SearchTenantAnnouncementsQuery : IRequest<PagedResult<TenantAnnouncementDto>>
|
public sealed record SearchTenantAnnouncementsQuery : IRequest<PagedResult<TenantAnnouncementDto>>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 公告类型筛选。
|
||||||
|
/// </summary>
|
||||||
public TenantAnnouncementType? AnnouncementType { get; init; }
|
public TenantAnnouncementType? AnnouncementType { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 是否筛选启用状态。
|
||||||
|
/// </summary>
|
||||||
public bool? IsActive { get; init; }
|
public bool? IsActive { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 仅返回当前有效期内的公告。
|
||||||
|
/// </summary>
|
||||||
public bool? OnlyEffective { get; init; }
|
public bool? OnlyEffective { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页码(从 1 开始)。
|
||||||
|
/// </summary>
|
||||||
public int Page { get; init; } = 1;
|
public int Page { get; init; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每页条数。
|
||||||
|
/// </summary>
|
||||||
public int PageSize { get; init; } = 20;
|
public int PageSize { get; init; } = 20;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,10 +10,33 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record SearchTenantBillsQuery : IRequest<PagedResult<TenantBillingDto>>
|
public sealed record SearchTenantBillsQuery : IRequest<PagedResult<TenantBillingDto>>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单状态筛选。
|
||||||
|
/// </summary>
|
||||||
public TenantBillingStatus? Status { get; init; }
|
public TenantBillingStatus? Status { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单起始时间(UTC)筛选。
|
||||||
|
/// </summary>
|
||||||
public DateTime? From { get; init; }
|
public DateTime? From { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 账单结束时间(UTC)筛选。
|
||||||
|
/// </summary>
|
||||||
public DateTime? To { get; init; }
|
public DateTime? To { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页码(从 1 开始)。
|
||||||
|
/// </summary>
|
||||||
public int Page { get; init; } = 1;
|
public int Page { get; init; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每页条数。
|
||||||
|
/// </summary>
|
||||||
public int PageSize { get; init; } = 20;
|
public int PageSize { get; init; } = 20;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,28 @@ namespace TakeoutSaaS.Application.App.Tenants.Queries;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed record SearchTenantNotificationsQuery : IRequest<PagedResult<TenantNotificationDto>>
|
public sealed record SearchTenantNotificationsQuery : IRequest<PagedResult<TenantNotificationDto>>
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 租户 ID(雪花算法)。
|
||||||
|
/// </summary>
|
||||||
public long TenantId { get; init; }
|
public long TenantId { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 通知等级筛选。
|
||||||
|
/// </summary>
|
||||||
public TenantNotificationSeverity? Severity { get; init; }
|
public TenantNotificationSeverity? Severity { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 仅返回未读通知。
|
||||||
|
/// </summary>
|
||||||
public bool? UnreadOnly { get; init; }
|
public bool? UnreadOnly { get; init; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 页码(从 1 开始)。
|
||||||
|
/// </summary>
|
||||||
public int Page { get; init; } = 1;
|
public int Page { get; init; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 每页条数。
|
||||||
|
/// </summary>
|
||||||
public int PageSize { get; init; } = 20;
|
public int PageSize { get; init; } = 20;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,13 +10,45 @@ namespace TakeoutSaaS.Domain.Tenants.Repositories;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITenantAnnouncementReadRepository
|
public interface ITenantAnnouncementReadRepository
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 按公告查询已读记录。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="announcementId">公告 ID。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>指定公告的已读列表。</returns>
|
||||||
Task<IReadOnlyList<TenantAnnouncementRead>> GetByAnnouncementAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default);
|
Task<IReadOnlyList<TenantAnnouncementRead>> GetByAnnouncementAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 批量按公告查询已读记录,可选按用户过滤。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="announcementIds">公告 ID 集合。</param>
|
||||||
|
/// <param name="userId">用户 ID,空则不按用户筛选。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>匹配条件的已读列表。</returns>
|
||||||
Task<IReadOnlyList<TenantAnnouncementRead>> GetByAnnouncementAsync(long tenantId, IEnumerable<long> announcementIds, long? userId, CancellationToken cancellationToken = default);
|
Task<IReadOnlyList<TenantAnnouncementRead>> GetByAnnouncementAsync(long tenantId, IEnumerable<long> announcementIds, long? userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 查询指定用户对某公告的已读记录。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="announcementId">公告 ID。</param>
|
||||||
|
/// <param name="userId">用户 ID。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>已读记录,未读返回 null。</returns>
|
||||||
Task<TenantAnnouncementRead?> FindAsync(long tenantId, long announcementId, long? userId, CancellationToken cancellationToken = default);
|
Task<TenantAnnouncementRead?> FindAsync(long tenantId, long announcementId, long? userId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新增已读记录。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="record">已读实体。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task AddAsync(TenantAnnouncementRead record, CancellationToken cancellationToken = default);
|
Task AddAsync(TenantAnnouncementRead record, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存变更。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,15 @@ namespace TakeoutSaaS.Domain.Tenants.Repositories;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITenantAnnouncementRepository
|
public interface ITenantAnnouncementRepository
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 查询公告列表,按类型、启用状态与生效时间筛选。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="type">公告类型。</param>
|
||||||
|
/// <param name="isActive">启用状态。</param>
|
||||||
|
/// <param name="effectiveAt">生效时间点,为空不限制。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>公告集合。</returns>
|
||||||
Task<IReadOnlyList<TenantAnnouncement>> SearchAsync(
|
Task<IReadOnlyList<TenantAnnouncement>> SearchAsync(
|
||||||
long tenantId,
|
long tenantId,
|
||||||
TenantAnnouncementType? type,
|
TenantAnnouncementType? type,
|
||||||
@@ -18,13 +27,40 @@ public interface ITenantAnnouncementRepository
|
|||||||
DateTime? effectiveAt,
|
DateTime? effectiveAt,
|
||||||
CancellationToken cancellationToken = default);
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按 ID 获取公告。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="announcementId">公告 ID。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>公告实体或 null。</returns>
|
||||||
Task<TenantAnnouncement?> FindByIdAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default);
|
Task<TenantAnnouncement?> FindByIdAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新增公告。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="announcement">公告实体。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task AddAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default);
|
Task AddAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新公告。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="announcement">公告实体。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task UpdateAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default);
|
Task UpdateAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 删除公告。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="announcementId">公告 ID。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task DeleteAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default);
|
Task DeleteAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存变更。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,15 @@ namespace TakeoutSaaS.Domain.Tenants.Repositories;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITenantBillingRepository
|
public interface ITenantBillingRepository
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 查询账单列表,按状态与时间范围筛选。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="status">账单状态。</param>
|
||||||
|
/// <param name="from">开始时间(UTC)。</param>
|
||||||
|
/// <param name="to">结束时间(UTC)。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>账单集合。</returns>
|
||||||
Task<IReadOnlyList<TenantBillingStatement>> SearchAsync(
|
Task<IReadOnlyList<TenantBillingStatement>> SearchAsync(
|
||||||
long tenantId,
|
long tenantId,
|
||||||
TenantBillingStatus? status,
|
TenantBillingStatus? status,
|
||||||
@@ -18,13 +27,41 @@ public interface ITenantBillingRepository
|
|||||||
DateTime? to,
|
DateTime? to,
|
||||||
CancellationToken cancellationToken = default);
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按 ID 获取账单。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="billingId">账单 ID。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>账单实体或 null。</returns>
|
||||||
Task<TenantBillingStatement?> FindByIdAsync(long tenantId, long billingId, CancellationToken cancellationToken = default);
|
Task<TenantBillingStatement?> FindByIdAsync(long tenantId, long billingId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按账单编号获取账单。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="statementNo">账单编号。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>账单实体或 null。</returns>
|
||||||
Task<TenantBillingStatement?> FindByStatementNoAsync(long tenantId, string statementNo, CancellationToken cancellationToken = default);
|
Task<TenantBillingStatement?> FindByStatementNoAsync(long tenantId, string statementNo, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新增账单。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bill">账单实体。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task AddAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default);
|
Task AddAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新账单。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="bill">账单实体。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task UpdateAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default);
|
Task UpdateAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存变更。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,16 @@ namespace TakeoutSaaS.Domain.Tenants.Repositories;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ITenantNotificationRepository
|
public interface ITenantNotificationRepository
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 查询通知列表,按等级、未读状态与时间范围筛选。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="severity">通知等级。</param>
|
||||||
|
/// <param name="unreadOnly">仅返回未读。</param>
|
||||||
|
/// <param name="from">开始时间(UTC)。</param>
|
||||||
|
/// <param name="to">结束时间(UTC)。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>通知集合。</returns>
|
||||||
Task<IReadOnlyList<TenantNotification>> SearchAsync(
|
Task<IReadOnlyList<TenantNotification>> SearchAsync(
|
||||||
long tenantId,
|
long tenantId,
|
||||||
TenantNotificationSeverity? severity,
|
TenantNotificationSeverity? severity,
|
||||||
@@ -19,11 +29,32 @@ public interface ITenantNotificationRepository
|
|||||||
DateTime? to,
|
DateTime? to,
|
||||||
CancellationToken cancellationToken = default);
|
CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 按 ID 获取通知。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="tenantId">租户 ID。</param>
|
||||||
|
/// <param name="notificationId">通知 ID。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
|
/// <returns>通知实体或 null。</returns>
|
||||||
Task<TenantNotification?> FindByIdAsync(long tenantId, long notificationId, CancellationToken cancellationToken = default);
|
Task<TenantNotification?> FindByIdAsync(long tenantId, long notificationId, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 新增通知。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="notification">通知实体。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task AddAsync(TenantNotification notification, CancellationToken cancellationToken = default);
|
Task AddAsync(TenantNotification notification, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 更新通知。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="notification">通知实体。</param>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task UpdateAsync(TenantNotification notification, CancellationToken cancellationToken = default);
|
Task UpdateAsync(TenantNotification notification, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 保存变更。
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">取消标记。</param>
|
||||||
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class EfTenantAnnouncementReadRepository(TakeoutAppDbContext context) : ITenantAnnouncementReadRepository
|
public sealed class EfTenantAnnouncementReadRepository(TakeoutAppDbContext context) : ITenantAnnouncementReadRepository
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<IReadOnlyList<TenantAnnouncementRead>> GetByAnnouncementAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default)
|
public Task<IReadOnlyList<TenantAnnouncementRead>> GetByAnnouncementAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.TenantAnnouncementReads.AsNoTracking()
|
return context.TenantAnnouncementReads.AsNoTracking()
|
||||||
@@ -20,6 +21,7 @@ public sealed class EfTenantAnnouncementReadRepository(TakeoutAppDbContext conte
|
|||||||
.ContinueWith(t => (IReadOnlyList<TenantAnnouncementRead>)t.Result, cancellationToken);
|
.ContinueWith(t => (IReadOnlyList<TenantAnnouncementRead>)t.Result, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<IReadOnlyList<TenantAnnouncementRead>> GetByAnnouncementAsync(long tenantId, IEnumerable<long> announcementIds, long? userId, CancellationToken cancellationToken = default)
|
public Task<IReadOnlyList<TenantAnnouncementRead>> GetByAnnouncementAsync(long tenantId, IEnumerable<long> announcementIds, long? userId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
var ids = announcementIds.Distinct().ToArray();
|
var ids = announcementIds.Distinct().ToArray();
|
||||||
@@ -46,17 +48,20 @@ public sealed class EfTenantAnnouncementReadRepository(TakeoutAppDbContext conte
|
|||||||
.ContinueWith(t => (IReadOnlyList<TenantAnnouncementRead>)t.Result, cancellationToken);
|
.ContinueWith(t => (IReadOnlyList<TenantAnnouncementRead>)t.Result, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<TenantAnnouncementRead?> FindAsync(long tenantId, long announcementId, long? userId, CancellationToken cancellationToken = default)
|
public Task<TenantAnnouncementRead?> FindAsync(long tenantId, long announcementId, long? userId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.TenantAnnouncementReads
|
return context.TenantAnnouncementReads
|
||||||
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.AnnouncementId == announcementId && x.UserId == userId, cancellationToken);
|
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.AnnouncementId == announcementId && x.UserId == userId, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task AddAsync(TenantAnnouncementRead record, CancellationToken cancellationToken = default)
|
public Task AddAsync(TenantAnnouncementRead record, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.TenantAnnouncementReads.AddAsync(record, cancellationToken).AsTask();
|
return context.TenantAnnouncementReads.AddAsync(record, cancellationToken).AsTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.SaveChangesAsync(cancellationToken);
|
return context.SaveChangesAsync(cancellationToken);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class EfTenantAnnouncementRepository(TakeoutAppDbContext context) : ITenantAnnouncementRepository
|
public sealed class EfTenantAnnouncementRepository(TakeoutAppDbContext context) : ITenantAnnouncementRepository
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<IReadOnlyList<TenantAnnouncement>> SearchAsync(
|
public Task<IReadOnlyList<TenantAnnouncement>> SearchAsync(
|
||||||
long tenantId,
|
long tenantId,
|
||||||
TenantAnnouncementType? type,
|
TenantAnnouncementType? type,
|
||||||
@@ -45,23 +46,27 @@ public sealed class EfTenantAnnouncementRepository(TakeoutAppDbContext context)
|
|||||||
.ContinueWith(t => (IReadOnlyList<TenantAnnouncement>)t.Result, cancellationToken);
|
.ContinueWith(t => (IReadOnlyList<TenantAnnouncement>)t.Result, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<TenantAnnouncement?> FindByIdAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default)
|
public Task<TenantAnnouncement?> FindByIdAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.TenantAnnouncements.AsNoTracking()
|
return context.TenantAnnouncements.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == announcementId, cancellationToken);
|
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == announcementId, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task AddAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default)
|
public Task AddAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.TenantAnnouncements.AddAsync(announcement, cancellationToken).AsTask();
|
return context.TenantAnnouncements.AddAsync(announcement, cancellationToken).AsTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task UpdateAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default)
|
public Task UpdateAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
context.TenantAnnouncements.Update(announcement);
|
context.TenantAnnouncements.Update(announcement);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public async Task DeleteAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default)
|
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);
|
var entity = await context.TenantAnnouncements.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == announcementId, cancellationToken);
|
||||||
@@ -71,6 +76,7 @@ public sealed class EfTenantAnnouncementRepository(TakeoutAppDbContext context)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.SaveChangesAsync(cancellationToken);
|
return context.SaveChangesAsync(cancellationToken);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class EfTenantBillingRepository(TakeoutAppDbContext context) : ITenantBillingRepository
|
public sealed class EfTenantBillingRepository(TakeoutAppDbContext context) : ITenantBillingRepository
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<IReadOnlyList<TenantBillingStatement>> SearchAsync(
|
public Task<IReadOnlyList<TenantBillingStatement>> SearchAsync(
|
||||||
long tenantId,
|
long tenantId,
|
||||||
TenantBillingStatus? status,
|
TenantBillingStatus? status,
|
||||||
@@ -43,29 +44,34 @@ public sealed class EfTenantBillingRepository(TakeoutAppDbContext context) : ITe
|
|||||||
.ContinueWith(t => (IReadOnlyList<TenantBillingStatement>)t.Result, cancellationToken);
|
.ContinueWith(t => (IReadOnlyList<TenantBillingStatement>)t.Result, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<TenantBillingStatement?> FindByIdAsync(long tenantId, long billingId, CancellationToken cancellationToken = default)
|
public Task<TenantBillingStatement?> FindByIdAsync(long tenantId, long billingId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.TenantBillingStatements.AsNoTracking()
|
return context.TenantBillingStatements.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == billingId, cancellationToken);
|
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == billingId, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<TenantBillingStatement?> FindByStatementNoAsync(long tenantId, string statementNo, CancellationToken cancellationToken = default)
|
public Task<TenantBillingStatement?> FindByStatementNoAsync(long tenantId, string statementNo, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.TenantBillingStatements.AsNoTracking()
|
return context.TenantBillingStatements.AsNoTracking()
|
||||||
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.StatementNo == statementNo, cancellationToken);
|
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.StatementNo == statementNo, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task AddAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default)
|
public Task AddAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.TenantBillingStatements.AddAsync(bill, cancellationToken).AsTask();
|
return context.TenantBillingStatements.AddAsync(bill, cancellationToken).AsTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task UpdateAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default)
|
public Task UpdateAsync(TenantBillingStatement bill, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
context.TenantBillingStatements.Update(bill);
|
context.TenantBillingStatements.Update(bill);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.SaveChangesAsync(cancellationToken);
|
return context.SaveChangesAsync(cancellationToken);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace TakeoutSaaS.Infrastructure.App.Repositories;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class EfTenantNotificationRepository(TakeoutAppDbContext context) : ITenantNotificationRepository
|
public sealed class EfTenantNotificationRepository(TakeoutAppDbContext context) : ITenantNotificationRepository
|
||||||
{
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<IReadOnlyList<TenantNotification>> SearchAsync(
|
public Task<IReadOnlyList<TenantNotification>> SearchAsync(
|
||||||
long tenantId,
|
long tenantId,
|
||||||
TenantNotificationSeverity? severity,
|
TenantNotificationSeverity? severity,
|
||||||
@@ -49,23 +50,27 @@ public sealed class EfTenantNotificationRepository(TakeoutAppDbContext context)
|
|||||||
.ContinueWith(t => (IReadOnlyList<TenantNotification>)t.Result, cancellationToken);
|
.ContinueWith(t => (IReadOnlyList<TenantNotification>)t.Result, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task<TenantNotification?> FindByIdAsync(long tenantId, long notificationId, CancellationToken cancellationToken = default)
|
public Task<TenantNotification?> FindByIdAsync(long tenantId, long notificationId, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.TenantNotifications
|
return context.TenantNotifications
|
||||||
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == notificationId, cancellationToken);
|
.FirstOrDefaultAsync(x => x.TenantId == tenantId && x.Id == notificationId, cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task AddAsync(TenantNotification notification, CancellationToken cancellationToken = default)
|
public Task AddAsync(TenantNotification notification, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.TenantNotifications.AddAsync(notification, cancellationToken).AsTask();
|
return context.TenantNotifications.AddAsync(notification, cancellationToken).AsTask();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task UpdateAsync(TenantNotification notification, CancellationToken cancellationToken = default)
|
public Task UpdateAsync(TenantNotification notification, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
context.TenantNotifications.Update(notification);
|
context.TenantNotifications.Update(notification);
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
public Task SaveChangesAsync(CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
return context.SaveChangesAsync(cancellationToken);
|
return context.SaveChangesAsync(cancellationToken);
|
||||||
|
|||||||
Reference in New Issue
Block a user