docs: 补全租户与字典模块注释

This commit is contained in:
2025-12-12 11:29:15 +08:00
parent 641598de86
commit 2da009c68a
17 changed files with 220 additions and 17 deletions

View File

@@ -14,6 +14,12 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
public sealed class CreateTenantAnnouncementCommandHandler(ITenantAnnouncementRepository announcementRepository)
: IRequestHandler<CreateTenantAnnouncementCommand, TenantAnnouncementDto>
{
/// <summary>
/// 处理创建租户公告请求。
/// </summary>
/// <param name="request">创建命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>公告 DTO。</returns>
public async Task<TenantAnnouncementDto> Handle(CreateTenantAnnouncementCommand request, CancellationToken cancellationToken)
{
// 1. 校验标题与内容

View File

@@ -14,6 +14,12 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
public sealed class CreateTenantBillingCommandHandler(ITenantBillingRepository billingRepository)
: IRequestHandler<CreateTenantBillingCommand, TenantBillingDto>
{
/// <summary>
/// 处理创建租户账单请求。
/// </summary>
/// <param name="request">创建命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>账单 DTO。</returns>
public async Task<TenantBillingDto> Handle(CreateTenantBillingCommand request, CancellationToken cancellationToken)
{
// 1. 校验账单编号

View File

@@ -10,6 +10,12 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
public sealed class DeleteTenantAnnouncementCommandHandler(ITenantAnnouncementRepository announcementRepository)
: IRequestHandler<DeleteTenantAnnouncementCommand, bool>
{
/// <summary>
/// 处理删除公告请求。
/// </summary>
/// <param name="request">删除命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>执行结果。</returns>
public async Task<bool> Handle(DeleteTenantAnnouncementCommand request, CancellationToken cancellationToken)
{
// 1. 删除公告

View File

@@ -15,6 +15,12 @@ public sealed class GetTenantAnnouncementQueryHandler(
ICurrentUserAccessor? currentUserAccessor = null)
: IRequestHandler<GetTenantAnnouncementQuery, TenantAnnouncementDto?>
{
/// <summary>
/// 查询公告详情。
/// </summary>
/// <param name="request">查询请求。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>公告 DTO 或 null。</returns>
public async Task<TenantAnnouncementDto?> Handle(GetTenantAnnouncementQuery request, CancellationToken cancellationToken)
{
// 1. 查询公告主体

View File

@@ -11,6 +11,12 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
public sealed class GetTenantBillQueryHandler(ITenantBillingRepository billingRepository)
: IRequestHandler<GetTenantBillQuery, TenantBillingDto?>
{
/// <summary>
/// 查询账单详情。
/// </summary>
/// <param name="request">查询请求。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>账单 DTO 或 null。</returns>
public async Task<TenantBillingDto?> Handle(GetTenantBillQuery request, CancellationToken cancellationToken)
{
// 1. 查询账单

View File

@@ -16,6 +16,12 @@ public sealed class MarkTenantAnnouncementReadCommandHandler(
ICurrentUserAccessor? currentUserAccessor = null)
: IRequestHandler<MarkTenantAnnouncementReadCommand, TenantAnnouncementDto?>
{
/// <summary>
/// 标记公告已读。
/// </summary>
/// <param name="request">标记命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>公告 DTO 或 null。</returns>
public async Task<TenantAnnouncementDto?> Handle(MarkTenantAnnouncementReadCommand request, CancellationToken cancellationToken)
{
// 1. 查询公告

View File

@@ -12,6 +12,12 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
public sealed class MarkTenantBillingPaidCommandHandler(ITenantBillingRepository billingRepository)
: IRequestHandler<MarkTenantBillingPaidCommand, TenantBillingDto?>
{
/// <summary>
/// 标记账单支付。
/// </summary>
/// <param name="request">标记命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>账单 DTO 或 null。</returns>
public async Task<TenantBillingDto?> Handle(MarkTenantBillingPaidCommand request, CancellationToken cancellationToken)
{
// 1. 查询账单

View File

@@ -11,6 +11,12 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
public sealed class MarkTenantNotificationReadCommandHandler(ITenantNotificationRepository notificationRepository)
: IRequestHandler<MarkTenantNotificationReadCommand, TenantNotificationDto?>
{
/// <summary>
/// 标记通知已读。
/// </summary>
/// <param name="request">标记命令。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>通知 DTO 或 null。</returns>
public async Task<TenantNotificationDto?> Handle(MarkTenantNotificationReadCommand request, CancellationToken cancellationToken)
{
// 1. 查询通知

View File

@@ -16,6 +16,12 @@ public sealed class SearchTenantAnnouncementsQueryHandler(
ICurrentUserAccessor? currentUserAccessor = null)
: IRequestHandler<SearchTenantAnnouncementsQuery, PagedResult<TenantAnnouncementDto>>
{
/// <summary>
/// 分页查询公告列表。
/// </summary>
/// <param name="request">查询条件。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分页结果。</returns>
public async Task<PagedResult<TenantAnnouncementDto>> Handle(SearchTenantAnnouncementsQuery request, CancellationToken cancellationToken)
{
// 1. 过滤有效期条件

View File

@@ -12,6 +12,12 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
public sealed class SearchTenantBillsQueryHandler(ITenantBillingRepository billingRepository)
: IRequestHandler<SearchTenantBillsQuery, PagedResult<TenantBillingDto>>
{
/// <summary>
/// 分页查询账单列表。
/// </summary>
/// <param name="request">查询条件。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分页结果。</returns>
public async Task<PagedResult<TenantBillingDto>> Handle(SearchTenantBillsQuery request, CancellationToken cancellationToken)
{
// 1. 查询账单

View File

@@ -12,6 +12,12 @@ namespace TakeoutSaaS.Application.App.Tenants.Handlers;
public sealed class SearchTenantNotificationsQueryHandler(ITenantNotificationRepository notificationRepository)
: IRequestHandler<SearchTenantNotificationsQuery, PagedResult<TenantNotificationDto>>
{
/// <summary>
/// 分页查询通知列表。
/// </summary>
/// <param name="request">查询条件。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分页结果。</returns>
public async Task<PagedResult<TenantNotificationDto>> Handle(SearchTenantNotificationsQuery request, CancellationToken cancellationToken)
{
// 1. 查询通知

View File

@@ -8,6 +8,13 @@ namespace TakeoutSaaS.Application.App.Tenants;
/// </summary>
internal static class TenantMapping
{
/// <summary>
/// 将租户实体与订阅、认证信息映射为租户 DTO。
/// </summary>
/// <param name="tenant">租户实体。</param>
/// <param name="subscription">订阅信息。</param>
/// <param name="verification">认证信息。</param>
/// <returns>租户 DTO。</returns>
public static TenantDto ToDto(Tenant tenant, TenantSubscription? subscription, TenantVerificationProfile? verification)
=> new()
{
@@ -26,6 +33,11 @@ internal static class TenantMapping
AutoRenew = subscription?.AutoRenew ?? false
};
/// <summary>
/// 将租户认证实体映射为 DTO。
/// </summary>
/// <param name="profile">认证实体。</param>
/// <returns>认证 DTO 或 null。</returns>
public static TenantVerificationDto? ToVerificationDto(this TenantVerificationProfile? profile)
=> profile == null
? null
@@ -45,6 +57,11 @@ internal static class TenantMapping
ReviewedAt = profile.ReviewedAt
};
/// <summary>
/// 将订阅实体映射为 DTO。
/// </summary>
/// <param name="subscription">订阅实体。</param>
/// <returns>订阅 DTO 或 null。</returns>
public static TenantSubscriptionDto? ToSubscriptionDto(this TenantSubscription? subscription)
=> subscription == null
? null
@@ -60,6 +77,11 @@ internal static class TenantMapping
AutoRenew = subscription.AutoRenew
};
/// <summary>
/// 将审计日志实体映射为 DTO。
/// </summary>
/// <param name="log">审计日志实体。</param>
/// <returns>审计日志 DTO。</returns>
public static TenantAuditLogDto ToDto(this TenantAuditLog log)
=> new()
{
@@ -74,6 +96,11 @@ internal static class TenantMapping
CreatedAt = log.CreatedAt
};
/// <summary>
/// 将套餐实体映射为 DTO。
/// </summary>
/// <param name="package">套餐实体。</param>
/// <returns>套餐 DTO。</returns>
public static TenantPackageDto ToDto(this TenantPackage package)
=> new()
{
@@ -93,6 +120,11 @@ internal static class TenantMapping
SortOrder = package.SortOrder
};
/// <summary>
/// 将账单实体映射为 DTO。
/// </summary>
/// <param name="bill">账单实体。</param>
/// <returns>账单 DTO。</returns>
public static TenantBillingDto ToDto(this TenantBillingStatement bill)
=> new()
{
@@ -108,6 +140,13 @@ internal static class TenantMapping
LineItemsJson = bill.LineItemsJson
};
/// <summary>
/// 将公告实体映射为 DTO。
/// </summary>
/// <param name="announcement">公告实体。</param>
/// <param name="isRead">是否已读。</param>
/// <param name="readAt">阅读时间。</param>
/// <returns>公告 DTO。</returns>
public static TenantAnnouncementDto ToDto(this TenantAnnouncement announcement, bool isRead, DateTime? readAt)
=> new()
{
@@ -124,6 +163,11 @@ internal static class TenantMapping
ReadAt = readAt
};
/// <summary>
/// 将通知实体映射为 DTO。
/// </summary>
/// <param name="notification">通知实体。</param>
/// <returns>通知 DTO。</returns>
public static TenantNotificationDto ToDto(this TenantNotification notification)
=> new()
{

View File

@@ -9,18 +9,39 @@ namespace TakeoutSaaS.Application.Dictionary.Models;
/// </summary>
public sealed class DictionaryGroupDto
{
/// <summary>
/// 分组 ID。
/// </summary>
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long Id { get; init; }
/// <summary>
/// 分组编码。
/// </summary>
public string Code { get; init; } = string.Empty;
/// <summary>
/// 分组名称。
/// </summary>
public string Name { get; init; } = string.Empty;
/// <summary>
/// 字典作用域。
/// </summary>
public DictionaryScope Scope { get; init; }
/// <summary>
/// 描述。
/// </summary>
public string? Description { get; init; }
/// <summary>
/// 是否启用。
/// </summary>
public bool IsEnabled { get; init; }
/// <summary>
/// 字典项集合。
/// </summary>
public IReadOnlyList<DictionaryItemDto> Items { get; init; } = Array.Empty<DictionaryItemDto>();
}

View File

@@ -8,21 +8,45 @@ namespace TakeoutSaaS.Application.Dictionary.Models;
/// </summary>
public sealed class DictionaryItemDto
{
/// <summary>
/// 字典项 ID。
/// </summary>
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long Id { get; init; }
/// <summary>
/// 分组 ID。
/// </summary>
[JsonConverter(typeof(SnowflakeIdJsonConverter))]
public long GroupId { get; init; }
/// <summary>
/// 键。
/// </summary>
public string Key { get; init; } = string.Empty;
/// <summary>
/// 值。
/// </summary>
public string Value { get; init; } = string.Empty;
/// <summary>
/// 是否默认值。
/// </summary>
public bool IsDefault { get; init; }
/// <summary>
/// 是否启用。
/// </summary>
public bool IsEnabled { get; init; }
/// <summary>
/// 排序序号。
/// </summary>
public int SortOrder { get; init; }
/// <summary>
/// 描述。
/// </summary>
public string? Description { get; init; }
}

View File

@@ -20,6 +20,12 @@ public sealed class DictionaryAppService(
ITenantProvider tenantProvider,
ILogger<DictionaryAppService> logger) : IDictionaryAppService
{
/// <summary>
/// 创建字典分组。
/// </summary>
/// <param name="request">创建请求。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组 DTO。</returns>
public async Task<DictionaryGroupDto> CreateGroupAsync(CreateDictionaryGroupRequest request, CancellationToken cancellationToken = default)
{
// 1. 规范化编码并确定租户
@@ -52,6 +58,13 @@ public sealed class DictionaryAppService(
return MapGroup(group, includeItems: false);
}
/// <summary>
/// 更新字典分组。
/// </summary>
/// <param name="groupId">分组 ID。</param>
/// <param name="request">更新请求。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组 DTO。</returns>
public async Task<DictionaryGroupDto> UpdateGroupAsync(long groupId, UpdateDictionaryGroupRequest request, CancellationToken cancellationToken = default)
{
// 1. 读取分组并校验权限
@@ -70,6 +83,11 @@ public sealed class DictionaryAppService(
return MapGroup(group, includeItems: false);
}
/// <summary>
/// 删除字典分组。
/// </summary>
/// <param name="groupId">分组 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
public async Task DeleteGroupAsync(long groupId, CancellationToken cancellationToken = default)
{
// 1. 读取分组并校验权限
@@ -83,6 +101,12 @@ public sealed class DictionaryAppService(
logger.LogInformation("删除字典分组:{GroupId}", group.Id);
}
/// <summary>
/// 搜索字典分组。
/// </summary>
/// <param name="request">查询条件。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组列表。</returns>
public async Task<IReadOnlyList<DictionaryGroupDto>> SearchGroupsAsync(DictionaryGroupQuery request, CancellationToken cancellationToken = default)
{
// 1. 确定查询范围并校验权限
@@ -111,6 +135,12 @@ public sealed class DictionaryAppService(
return result;
}
/// <summary>
/// 创建字典项。
/// </summary>
/// <param name="request">创建请求。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>字典项 DTO。</returns>
public async Task<DictionaryItemDto> CreateItemAsync(CreateDictionaryItemRequest request, CancellationToken cancellationToken = default)
{
// 1. 校验分组与权限
@@ -139,6 +169,13 @@ public sealed class DictionaryAppService(
return MapItem(item);
}
/// <summary>
/// 更新字典项。
/// </summary>
/// <param name="itemId">字典项 ID。</param>
/// <param name="request">更新请求。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>字典项 DTO。</returns>
public async Task<DictionaryItemDto> UpdateItemAsync(long itemId, UpdateDictionaryItemRequest request, CancellationToken cancellationToken = default)
{
// 1. 读取字典项与分组并校验权限
@@ -160,6 +197,11 @@ public sealed class DictionaryAppService(
return MapItem(item);
}
/// <summary>
/// 删除字典项。
/// </summary>
/// <param name="itemId">字典项 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
public async Task DeleteItemAsync(long itemId, CancellationToken cancellationToken = default)
{
// 1. 读取字典项与分组并校验权限
@@ -174,6 +216,12 @@ public sealed class DictionaryAppService(
logger.LogInformation("删除字典项:{ItemId}", item.Id);
}
/// <summary>
/// 批量获取缓存中的字典项。
/// </summary>
/// <param name="request">批量查询请求。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>按编码分组的字典项集合。</returns>
public async Task<IReadOnlyDictionary<string, IReadOnlyList<DictionaryItemDto>>> GetCachedItemsAsync(DictionaryBatchQueryRequest request, CancellationToken cancellationToken = default)
{
// 1. 规范化编码

View File

@@ -5,6 +5,12 @@ namespace TakeoutSaaS.Application.Identity.Abstractions;
/// </summary>
public interface IWeChatAuthService
{
/// <summary>
/// 调用微信接口完成 code2Session 交换。
/// </summary>
/// <param name="code">临时登录凭证 code。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>会话信息。</returns>
Task<WeChatSessionInfo> Code2SessionAsync(string code, CancellationToken cancellationToken = default);
}
@@ -13,7 +19,18 @@ public interface IWeChatAuthService
/// </summary>
public sealed class WeChatSessionInfo
{
/// <summary>
/// OpenId。
/// </summary>
public string OpenId { get; init; } = string.Empty;
/// <summary>
/// UnionId。
/// </summary>
public string? UnionId { get; init; }
/// <summary>
/// 会话密钥。
/// </summary>
public string SessionKey { get; init; } = string.Empty;
}