refactor: 清理租户API旧模块代码

This commit is contained in:
2026-02-17 09:57:26 +08:00
parent 2711893474
commit 992930a821
924 changed files with 7 additions and 191722 deletions

View File

@@ -1,87 +0,0 @@
using TakeoutSaaS.Domain.Deliveries.Entities;
using TakeoutSaaS.Domain.Deliveries.Enums;
namespace TakeoutSaaS.Domain.Deliveries.Repositories;
/// <summary>
/// 配送聚合仓储契约。
/// </summary>
public interface IDeliveryRepository
{
/// <summary>
/// 依据标识获取配送单。
/// </summary>
/// <param name="deliveryOrderId">配送单 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>配送单实体或 null。</returns>
Task<DeliveryOrder?> FindByIdAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 依据订单标识获取配送单。
/// </summary>
/// <param name="orderId">订单 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>配送单实体或 null。</returns>
Task<DeliveryOrder?> FindByOrderIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取配送事件轨迹。
/// </summary>
/// <param name="deliveryOrderId">配送单 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>配送事件列表。</returns>
Task<IReadOnlyList<DeliveryEvent>> GetEventsAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 新增配送单。
/// </summary>
/// <param name="deliveryOrder">配送单实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddDeliveryOrderAsync(DeliveryOrder deliveryOrder, CancellationToken cancellationToken = default);
/// <summary>
/// 新增配送事件。
/// </summary>
/// <param name="deliveryEvent">配送事件。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddEventAsync(DeliveryEvent deliveryEvent, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化变更。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 按状态查询配送单。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="status">配送状态。</param>
/// <param name="orderId">订单 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>配送单列表。</returns>
Task<IReadOnlyList<DeliveryOrder>> SearchAsync(long tenantId, DeliveryStatus? status, long? orderId, CancellationToken cancellationToken = default);
/// <summary>
/// 更新配送单。
/// </summary>
/// <param name="deliveryOrder">配送单实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task UpdateDeliveryOrderAsync(DeliveryOrder deliveryOrder, CancellationToken cancellationToken = default);
/// <summary>
/// 删除配送单及事件。
/// </summary>
/// <param name="deliveryOrderId">配送单 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task DeleteDeliveryOrderAsync(long deliveryOrderId, long tenantId, CancellationToken cancellationToken = default);
}

View File

@@ -1,29 +0,0 @@
using TakeoutSaaS.Domain.Dictionary.Entities;
namespace TakeoutSaaS.Domain.Dictionary.Repositories;
/// <summary>
/// 缓存失效日志仓储。
/// </summary>
public interface ICacheInvalidationLogRepository
{
/// <summary>
/// 新增失效日志。
/// </summary>
Task AddAsync(CacheInvalidationLog log, CancellationToken cancellationToken = default);
/// <summary>
/// 分页查询失效日志。
/// </summary>
Task<(IReadOnlyList<CacheInvalidationLog> Items, int TotalCount)> GetPagedAsync(
int page,
int pageSize,
DateTime? startDate,
DateTime? endDate,
CancellationToken cancellationToken = default);
/// <summary>
/// 保存变更。
/// </summary>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,104 +0,0 @@
using TakeoutSaaS.Domain.Dictionary.Entities;
using TakeoutSaaS.Domain.Dictionary.Enums;
using TakeoutSaaS.Domain.Dictionary.ValueObjects;
namespace TakeoutSaaS.Domain.Dictionary.Repositories;
/// <summary>
/// 字典分组仓储契约。
/// </summary>
public interface IDictionaryGroupRepository
{
/// <summary>
/// 按 ID 获取字典分组。
/// </summary>
/// <param name="groupId">分组 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组实体或 null。</returns>
Task<DictionaryGroup?> GetByIdAsync(long groupId, CancellationToken cancellationToken = default);
/// <summary>
/// 按编码获取字典分组。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="code">分组编码。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组实体或 null。</returns>
Task<DictionaryGroup?> GetByCodeAsync(long tenantId, DictionaryCode code, CancellationToken cancellationToken = default);
/// <summary>
/// 分页获取字典分组。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="scope">作用域过滤。</param>
/// <param name="keyword">关键字过滤。</param>
/// <param name="isEnabled">启用状态过滤。</param>
/// <param name="page">页码。</param>
/// <param name="pageSize">页大小。</param>
/// <param name="sortBy">排序字段。</param>
/// <param name="sortDescending">是否降序。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组集合。</returns>
Task<IReadOnlyList<DictionaryGroup>> GetPagedAsync(
long tenantId,
DictionaryScope? scope,
string? keyword,
bool? isEnabled,
int page,
int pageSize,
string? sortBy,
bool sortDescending,
CancellationToken cancellationToken = default);
/// <summary>
/// 获取满足条件的分组数量。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="scope">作用域过滤。</param>
/// <param name="keyword">关键字过滤。</param>
/// <param name="isEnabled">启用状态过滤。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组数量。</returns>
Task<int> CountAsync(
long tenantId,
DictionaryScope? scope,
string? keyword,
bool? isEnabled,
CancellationToken cancellationToken = default);
/// <summary>
/// 批量获取字典分组。
/// </summary>
/// <param name="groupIds">分组 ID 列表。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组集合。</returns>
Task<IReadOnlyList<DictionaryGroup>> GetByIdsAsync(IEnumerable<long> groupIds, CancellationToken cancellationToken = default);
/// <summary>
/// 新增分组。
/// </summary>
/// <param name="group">分组实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task AddAsync(DictionaryGroup group, CancellationToken cancellationToken = default);
/// <summary>
/// 更新分组。
/// </summary>
/// <param name="group">分组实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task UpdateAsync(DictionaryGroup group, CancellationToken cancellationToken = default);
/// <summary>
/// 删除分组。
/// </summary>
/// <param name="group">分组实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task RemoveAsync(DictionaryGroup group, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化更改。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,22 +0,0 @@
using TakeoutSaaS.Domain.Dictionary.Entities;
namespace TakeoutSaaS.Domain.Dictionary.Repositories;
/// <summary>
/// 字典导入日志仓储契约。
/// </summary>
public interface IDictionaryImportLogRepository
{
/// <summary>
/// 新增导入日志。
/// </summary>
/// <param name="log">导入日志。</param>
/// <param name="cancellationToken">取消标记。</param>
Task AddAsync(DictionaryImportLog log, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化更改。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,64 +0,0 @@
using TakeoutSaaS.Domain.Dictionary.Entities;
namespace TakeoutSaaS.Domain.Dictionary.Repositories;
/// <summary>
/// 字典项仓储契约。
/// </summary>
public interface IDictionaryItemRepository
{
/// <summary>
/// 根据 ID 获取字典项。
/// </summary>
/// <param name="itemId">字典项 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>字典项或 null。</returns>
Task<DictionaryItem?> GetByIdAsync(long itemId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取分组下字典项列表。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="groupId">分组 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>字典项集合。</returns>
Task<IReadOnlyList<DictionaryItem>> GetByGroupIdAsync(long tenantId, long groupId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取合并后的系统/租户字典项。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="systemGroupId">系统分组 ID。</param>
/// <param name="includeOverrides">是否包含租户覆盖。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>字典项集合。</returns>
Task<IReadOnlyList<DictionaryItem>> GetMergedItemsAsync(long tenantId, long systemGroupId, bool includeOverrides, CancellationToken cancellationToken = default);
/// <summary>
/// 新增字典项。
/// </summary>
/// <param name="item">字典项实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task AddAsync(DictionaryItem item, CancellationToken cancellationToken = default);
/// <summary>
/// 更新字典项。
/// </summary>
/// <param name="item">字典项实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task UpdateAsync(DictionaryItem item, CancellationToken cancellationToken = default);
/// <summary>
/// 删除字典项。
/// </summary>
/// <param name="item">字典项实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task RemoveAsync(DictionaryItem item, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化更改。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,65 +0,0 @@
using TakeoutSaaS.Domain.Dictionary.Entities;
using TakeoutSaaS.Domain.Dictionary.Enums;
namespace TakeoutSaaS.Domain.Dictionary.Repositories;
/// <summary>
/// 字典标签覆盖仓储契约。
/// </summary>
public interface IDictionaryLabelOverrideRepository
{
/// <summary>
/// 根据 ID 获取覆盖配置。
/// </summary>
Task<DictionaryLabelOverride?> GetByIdAsync(long id, CancellationToken cancellationToken = default);
/// <summary>
/// 获取指定字典项的覆盖配置。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="dictionaryItemId">字典项 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
Task<DictionaryLabelOverride?> GetByItemIdAsync(long tenantId, long dictionaryItemId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取租户的所有覆盖配置。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="overrideType">可选的覆盖类型过滤。</param>
/// <param name="cancellationToken">取消标记。</param>
Task<IReadOnlyList<DictionaryLabelOverride>> ListByTenantAsync(
long tenantId,
OverrideType? overrideType = null,
CancellationToken cancellationToken = default);
/// <summary>
/// 批量获取多个字典项的覆盖配置。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="dictionaryItemIds">字典项 ID 列表。</param>
/// <param name="cancellationToken">取消标记。</param>
Task<IReadOnlyList<DictionaryLabelOverride>> GetByItemIdsAsync(
long tenantId,
IEnumerable<long> dictionaryItemIds,
CancellationToken cancellationToken = default);
/// <summary>
/// 新增覆盖配置。
/// </summary>
Task AddAsync(DictionaryLabelOverride entity, CancellationToken cancellationToken = default);
/// <summary>
/// 更新覆盖配置。
/// </summary>
Task UpdateAsync(DictionaryLabelOverride entity, CancellationToken cancellationToken = default);
/// <summary>
/// 删除覆盖配置。
/// </summary>
Task DeleteAsync(DictionaryLabelOverride entity, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化更改。
/// </summary>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,99 +0,0 @@
using TakeoutSaaS.Domain.Dictionary.Entities;
using TakeoutSaaS.Domain.Dictionary.Enums;
namespace TakeoutSaaS.Domain.Dictionary.Repositories;
/// <summary>
/// 参数字典仓储契约。
/// </summary>
public interface IDictionaryRepository
{
/// <summary>
/// 依据 ID 获取分组。
/// </summary>
/// <param name="id">分组 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组实体或 null。</returns>
Task<DictionaryGroup?> FindGroupByIdAsync(long id, CancellationToken cancellationToken = default);
/// <summary>
/// 依据编码获取分组。
/// </summary>
/// <param name="code">分组编码。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组实体或 null。</returns>
Task<DictionaryGroup?> FindGroupByCodeAsync(string code, CancellationToken cancellationToken = default);
/// <summary>
/// 搜索分组,可按作用域过滤。
/// </summary>
/// <param name="scope">作用域。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分组集合。</returns>
Task<IReadOnlyList<DictionaryGroup>> SearchGroupsAsync(DictionaryScope? scope, CancellationToken cancellationToken = default);
/// <summary>
/// 新增分组。
/// </summary>
/// <param name="group">分组实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddGroupAsync(DictionaryGroup group, CancellationToken cancellationToken = default);
/// <summary>
/// 删除分组。
/// </summary>
/// <param name="group">分组实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task RemoveGroupAsync(DictionaryGroup group, CancellationToken cancellationToken = default);
/// <summary>
/// 依据 ID 获取字典项。
/// </summary>
/// <param name="id">字典项 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>字典项或 null。</returns>
Task<DictionaryItem?> FindItemByIdAsync(long id, CancellationToken cancellationToken = default);
/// <summary>
/// 获取某分组下的所有字典项。
/// </summary>
/// <param name="groupId">分组 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>字典项集合。</returns>
Task<IReadOnlyList<DictionaryItem>> GetItemsByGroupIdAsync(long groupId, CancellationToken cancellationToken = default);
/// <summary>
/// 按分组编码集合获取字典项(可包含系统参数)。
/// </summary>
/// <param name="codes">分组编码集合。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="includeSystem">是否包含系统分组。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>字典项集合。</returns>
Task<IReadOnlyList<DictionaryItem>> GetItemsByCodesAsync(IEnumerable<string> codes, long tenantId, bool includeSystem, CancellationToken cancellationToken = default);
/// <summary>
/// 新增字典项。
/// </summary>
/// <param name="item">字典项实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddItemAsync(DictionaryItem item, CancellationToken cancellationToken = default);
/// <summary>
/// 删除字典项。
/// </summary>
/// <param name="item">字典项实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task RemoveItemAsync(DictionaryItem item, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化更改。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,47 +0,0 @@
using TakeoutSaaS.Domain.Dictionary.Entities;
namespace TakeoutSaaS.Domain.Dictionary.Repositories;
/// <summary>
/// 租户字典覆盖仓储契约。
/// </summary>
public interface ITenantDictionaryOverrideRepository
{
/// <summary>
/// 获取租户覆盖配置。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="systemGroupId">系统字典分组 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>覆盖配置或 null。</returns>
Task<TenantDictionaryOverride?> GetAsync(long tenantId, long systemGroupId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取租户全部覆盖配置。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>覆盖配置列表。</returns>
Task<IReadOnlyList<TenantDictionaryOverride>> ListAsync(long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 新增覆盖配置。
/// </summary>
/// <param name="overrideConfig">覆盖配置。</param>
/// <param name="cancellationToken">取消标记。</param>
Task AddAsync(TenantDictionaryOverride overrideConfig, CancellationToken cancellationToken = default);
/// <summary>
/// 更新覆盖配置。
/// </summary>
/// <param name="overrideConfig">覆盖配置。</param>
/// <param name="cancellationToken">取消标记。</param>
Task UpdateAsync(TenantDictionaryOverride overrideConfig, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化更改。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,151 +0,0 @@
using System.Text.Encodings.Web;
using System.Text.Json;
namespace TakeoutSaaS.Domain.Dictionary.ValueObjects;
/// <summary>
/// 多语言字典值对象,封装语言键值映射。
/// </summary>
public sealed class I18nValue : IEquatable<I18nValue>
{
private static readonly string[] FallbackLocales = ["zh-CN", "en"];
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web)
{
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
};
private readonly Dictionary<string, string> _values;
/// <summary>
/// 初始化多语言值。
/// </summary>
/// <param name="values">语言键值映射。</param>
/// <exception cref="ArgumentException">传入值为空或无有效条目时抛出。</exception>
public I18nValue(IDictionary<string, string> values)
{
if (values == null)
{
throw new ArgumentNullException(nameof(values));
}
_values = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach (var (key, value) in values)
{
if (string.IsNullOrWhiteSpace(key) || string.IsNullOrWhiteSpace(value))
{
continue;
}
_values[key.Trim()] = value.Trim();
}
if (_values.Count == 0)
{
throw new ArgumentException("I18nValue requires at least one non-empty entry.", nameof(values));
}
}
/// <summary>
/// 语言键值只读视图。
/// </summary>
public IReadOnlyDictionary<string, string> Values => _values;
/// <summary>
/// 获取指定语言值,支持回退策略。
/// </summary>
/// <param name="locale">语言标识。</param>
/// <returns>匹配语言值。</returns>
public string Extract(string? locale)
{
if (!string.IsNullOrWhiteSpace(locale) && _values.TryGetValue(locale, out var value))
{
return value;
}
foreach (var fallback in FallbackLocales)
{
if (_values.TryGetValue(fallback, out var fallbackValue))
{
return fallbackValue;
}
}
return _values.Values.First();
}
/// <summary>
/// 转换为普通字典。
/// </summary>
public Dictionary<string, string> ToDictionary()
=> new(_values, StringComparer.OrdinalIgnoreCase);
/// <summary>
/// 转换为 JSON 字符串。
/// </summary>
public string ToJson()
=> JsonSerializer.Serialize(_values, JsonOptions);
/// <summary>
/// 从 JSON 字符串解析多语言值。
/// </summary>
public static I18nValue FromJson(string json)
{
if (string.IsNullOrWhiteSpace(json))
{
throw new ArgumentException("JSON payload is required.", nameof(json));
}
var values = JsonSerializer.Deserialize<Dictionary<string, string>>(json, JsonOptions) ?? new Dictionary<string, string>();
return new I18nValue(values);
}
/// <inheritdoc />
public bool Equals(I18nValue? other)
{
if (other == null)
{
return false;
}
if (ReferenceEquals(this, other))
{
return true;
}
if (_values.Count != other._values.Count)
{
return false;
}
foreach (var (key, value) in _values)
{
if (!other._values.TryGetValue(key, out var otherValue))
{
return false;
}
if (!string.Equals(value, otherValue, StringComparison.Ordinal))
{
return false;
}
}
return true;
}
/// <inheritdoc />
public override bool Equals(object? obj)
=> obj is I18nValue other && Equals(other);
/// <inheritdoc />
public override int GetHashCode()
{
var hash = new HashCode();
foreach (var pair in _values.OrderBy(item => item.Key, StringComparer.OrdinalIgnoreCase))
{
hash.Add(pair.Key, StringComparer.OrdinalIgnoreCase);
hash.Add(pair.Value, StringComparer.Ordinal);
}
return hash.ToHashCode();
}
}

View File

@@ -1,37 +0,0 @@
using TakeoutSaaS.Domain.Identity.Entities;
namespace TakeoutSaaS.Domain.Identity.Repositories;
/// <summary>
/// 小程序用户仓储契约。
/// </summary>
public interface IMiniUserRepository
{
/// <summary>
/// 根据微信 OpenId 查找小程序用户。
/// </summary>
/// <param name="openId">微信 OpenId</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>小程序用户,如果不存在则返回 null</returns>
Task<MiniUser?> FindByOpenIdAsync(string openId, CancellationToken cancellationToken = default);
/// <summary>
/// 根据用户 ID 查找小程序用户。
/// </summary>
/// <param name="id">用户 ID</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>小程序用户,如果不存在则返回 null</returns>
Task<MiniUser?> FindByIdAsync(long id, CancellationToken cancellationToken = default);
/// <summary>
/// 创建或更新小程序用户(如果 OpenId 已存在则更新,否则创建)。
/// </summary>
/// <param name="openId">微信 OpenId</param>
/// <param name="unionId">微信 UnionId可选</param>
/// <param name="nickname">昵称</param>
/// <param name="avatar">头像地址(可选)</param>
/// <param name="tenantId">租户 ID</param>
/// <param name="cancellationToken">取消令牌</param>
/// <returns>创建或更新后的小程序用户</returns>
Task<MiniUser> CreateOrUpdateAsync(string openId, string? unionId, string? nickname, string? avatar, long tenantId, CancellationToken cancellationToken = default);
}

View File

@@ -1,74 +0,0 @@
using TakeoutSaaS.Domain.Identity.Entities;
namespace TakeoutSaaS.Domain.Identity.Repositories;
/// <summary>
/// 角色模板仓储。
/// </summary>
public interface IRoleTemplateRepository
{
/// <summary>
/// 查询角色模板列表。
/// </summary>
/// <param name="isActive">启用状态过滤。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>角色模板集合。</returns>
Task<IReadOnlyList<RoleTemplate>> GetAllAsync(bool? isActive, CancellationToken cancellationToken = default);
/// <summary>
/// 通过模板编码获取模板信息。
/// </summary>
/// <param name="templateCode">模板编码。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>模板实体或 null。</returns>
Task<RoleTemplate?> FindByCodeAsync(string templateCode, CancellationToken cancellationToken = default);
/// <summary>
/// 获取模板的权限列表。
/// </summary>
/// <param name="roleTemplateId">模板 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>权限集合。</returns>
Task<IReadOnlyList<RoleTemplatePermission>> GetPermissionsAsync(long roleTemplateId, CancellationToken cancellationToken = default);
/// <summary>
/// 批量获取多个模板的权限映射。
/// </summary>
/// <param name="roleTemplateIds">模板 ID 集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>模板与权限列表的映射。</returns>
Task<IDictionary<long, IReadOnlyList<RoleTemplatePermission>>> GetPermissionsAsync(IEnumerable<long> roleTemplateIds, CancellationToken cancellationToken = default);
/// <summary>
/// 新增模板及其权限。
/// </summary>
/// <param name="template">模板实体。</param>
/// <param name="permissionCodes">权限编码集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步操作任务。</returns>
Task AddAsync(RoleTemplate template, IEnumerable<string> permissionCodes, CancellationToken cancellationToken = default);
/// <summary>
/// 更新模板及权限。
/// </summary>
/// <param name="template">模板实体。</param>
/// <param name="permissionCodes">权限编码集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步操作任务。</returns>
Task UpdateAsync(RoleTemplate template, IEnumerable<string> permissionCodes, CancellationToken cancellationToken = default);
/// <summary>
/// 删除模板。
/// </summary>
/// <param name="roleTemplateId">模板 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步操作任务。</returns>
Task DeleteAsync(long roleTemplateId, CancellationToken cancellationToken = default);
/// <summary>
/// 保存仓储变更。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步操作任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,95 +0,0 @@
using System;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using TakeoutSaaS.Domain.Inventory.Entities;
using TakeoutSaaS.Domain.Inventory.Enums;
namespace TakeoutSaaS.Domain.Inventory.Repositories;
/// <summary>
/// 库存仓储契约。
/// </summary>
public interface IInventoryRepository
{
/// <summary>
/// 依据标识查询库存。
/// </summary>
Task<InventoryItem?> FindByIdAsync(long inventoryItemId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 按门店与 SKU 查询库存(只读)。
/// </summary>
Task<InventoryItem?> FindBySkuAsync(long tenantId, long storeId, long productSkuId, CancellationToken cancellationToken = default);
/// <summary>
/// 按门店与 SKU 查询库存(跟踪用于更新)。
/// </summary>
Task<InventoryItem?> GetForUpdateAsync(long tenantId, long storeId, long productSkuId, CancellationToken cancellationToken = default);
/// <summary>
/// 新增库存记录。
/// </summary>
Task AddItemAsync(InventoryItem item, CancellationToken cancellationToken = default);
/// <summary>
/// 更新库存记录。
/// </summary>
Task UpdateItemAsync(InventoryItem item, CancellationToken cancellationToken = default);
/// <summary>
/// 新增库存调整记录。
/// </summary>
Task AddAdjustmentAsync(InventoryAdjustment adjustment, CancellationToken cancellationToken = default);
/// <summary>
/// 新增锁定记录。
/// </summary>
Task AddLockAsync(InventoryLockRecord lockRecord, CancellationToken cancellationToken = default);
/// <summary>
/// 按幂等键查询锁记录。
/// </summary>
Task<InventoryLockRecord?> FindLockByKeyAsync(long tenantId, string idempotencyKey, CancellationToken cancellationToken = default);
/// <summary>
/// 更新锁状态。
/// </summary>
Task MarkLockStatusAsync(InventoryLockRecord lockRecord, InventoryLockStatus status, CancellationToken cancellationToken = default);
/// <summary>
/// 查询过期锁定。
/// </summary>
Task<IReadOnlyList<InventoryLockRecord>> FindExpiredLocksAsync(long tenantId, DateTime utcNow, CancellationToken cancellationToken = default);
/// <summary>
/// 查询批次列表。
/// </summary>
Task<IReadOnlyList<InventoryBatch>> GetBatchesAsync(long tenantId, long storeId, long productSkuId, CancellationToken cancellationToken = default);
/// <summary>
/// 批次扣减读取(带排序策略)。
/// </summary>
Task<IReadOnlyList<InventoryBatch>> GetBatchesForConsumeAsync(long tenantId, long storeId, long productSkuId, InventoryBatchConsumeStrategy strategy, CancellationToken cancellationToken = default);
/// <summary>
/// 查询批次(跟踪用于更新)。
/// </summary>
Task<InventoryBatch?> GetBatchForUpdateAsync(long tenantId, long storeId, long productSkuId, string batchNumber, CancellationToken cancellationToken = default);
/// <summary>
/// 新增批次。
/// </summary>
Task AddBatchAsync(InventoryBatch batch, CancellationToken cancellationToken = default);
/// <summary>
/// 更新批次。
/// </summary>
Task UpdateBatchAsync(InventoryBatch batch, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化变更。
/// </summary>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,66 +0,0 @@
using TakeoutSaaS.Domain.Merchants.Entities;
namespace TakeoutSaaS.Domain.Merchants.Repositories;
/// <summary>
/// 商户类目仓储契约。
/// </summary>
public interface IMerchantCategoryRepository
{
/// <summary>
/// 列出当前租户的类目。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>类目列表。</returns>
Task<IReadOnlyList<MerchantCategory>> ListAsync(long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 是否存在同名类目。
/// </summary>
/// <param name="name">类目名称。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>存在返回 true。</returns>
Task<bool> ExistsAsync(string name, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 查找类目。
/// </summary>
/// <param name="id">类目 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>类目实体或 null。</returns>
Task<MerchantCategory?> FindByIdAsync(long id, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 新增类目。
/// </summary>
/// <param name="category">类目实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddAsync(MerchantCategory category, CancellationToken cancellationToken = default);
/// <summary>
/// 删除类目。
/// </summary>
/// <param name="category">类目实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task RemoveAsync(MerchantCategory category, CancellationToken cancellationToken = default);
/// <summary>
/// 批量更新类目信息。
/// </summary>
/// <param name="categories">类目集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task UpdateRangeAsync(IEnumerable<MerchantCategory> categories, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化更改。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,26 +0,0 @@
using TakeoutSaaS.Domain.Merchants.Entities;
using TakeoutSaaS.Domain.Stores.Entities;
namespace TakeoutSaaS.Domain.Merchants.Services;
/// <summary>
/// 商户导出服务接口。
/// </summary>
public interface IMerchantExportService
{
/// <summary>
/// 导出为 PDF。
/// </summary>
/// <param name="merchant">商户主体。</param>
/// <param name="tenantName">租户名称。</param>
/// <param name="stores">门店列表。</param>
/// <param name="auditLogs">审核历史。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>PDF 字节数组。</returns>
Task<byte[]> ExportToPdfAsync(
Merchant merchant,
string? tenantName,
IReadOnlyList<Store> stores,
IReadOnlyList<MerchantAuditLog> auditLogs,
CancellationToken cancellationToken = default);
}

View File

@@ -1,122 +0,0 @@
using TakeoutSaaS.Domain.Orders.Entities;
using TakeoutSaaS.Domain.Orders.Enums;
using TakeoutSaaS.Domain.Payments.Enums;
namespace TakeoutSaaS.Domain.Orders.Repositories;
/// <summary>
/// 订单聚合仓储契约。
/// </summary>
public interface IOrderRepository
{
/// <summary>
/// 依据标识获取订单。
/// </summary>
/// <param name="orderId">订单 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>订单实体或 null。</returns>
Task<Order?> FindByIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 依据订单号获取订单。
/// </summary>
/// <param name="orderNo">订单号。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>订单实体或 null。</returns>
Task<Order?> FindByOrderNoAsync(string orderNo, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 按状态筛选订单列表。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="status">订单状态。</param>
/// <param name="paymentStatus">支付状态。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>订单集合。</returns>
Task<IReadOnlyList<Order>> SearchAsync(long tenantId, OrderStatus? status, PaymentStatus? paymentStatus, CancellationToken cancellationToken = default);
/// <summary>
/// 获取订单明细行。
/// </summary>
/// <param name="orderId">订单 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>订单明细集合。</returns>
Task<IReadOnlyList<OrderItem>> GetItemsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取订单状态流转记录。
/// </summary>
/// <param name="orderId">订单 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>状态变更记录列表。</returns>
Task<IReadOnlyList<OrderStatusHistory>> GetStatusHistoryAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取订单退款申请。
/// </summary>
/// <param name="orderId">订单 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>退款申请列表。</returns>
Task<IReadOnlyList<RefundRequest>> GetRefundsAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 新增订单。
/// </summary>
/// <param name="order">订单实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddOrderAsync(Order order, CancellationToken cancellationToken = default);
/// <summary>
/// 新增订单明细。
/// </summary>
/// <param name="items">明细集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddItemsAsync(IEnumerable<OrderItem> items, CancellationToken cancellationToken = default);
/// <summary>
/// 新增订单状态记录。
/// </summary>
/// <param name="history">状态记录。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddStatusHistoryAsync(OrderStatusHistory history, CancellationToken cancellationToken = default);
/// <summary>
/// 新增退款申请。
/// </summary>
/// <param name="refund">退款申请实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddRefundAsync(RefundRequest refund, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化变更。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 更新订单。
/// </summary>
/// <param name="order">订单实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task UpdateOrderAsync(Order order, CancellationToken cancellationToken = default);
/// <summary>
/// 删除订单。
/// </summary>
/// <param name="orderId">订单 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task DeleteOrderAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);
}

View File

@@ -1,86 +0,0 @@
using TakeoutSaaS.Domain.Payments.Entities;
using TakeoutSaaS.Domain.Payments.Enums;
namespace TakeoutSaaS.Domain.Payments.Repositories;
/// <summary>
/// 支付记录仓储契约。
/// </summary>
public interface IPaymentRepository
{
/// <summary>
/// 依据标识获取支付记录。
/// </summary>
/// <param name="paymentId">支付记录 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>支付记录或 null。</returns>
Task<PaymentRecord?> FindByIdAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 依据订单标识获取支付记录。
/// </summary>
/// <param name="orderId">订单 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>支付记录或 null。</returns>
Task<PaymentRecord?> FindByOrderIdAsync(long orderId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取支付对应的退款记录。
/// </summary>
/// <param name="paymentId">支付记录 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>退款记录列表。</returns>
Task<IReadOnlyList<PaymentRefundRecord>> GetRefundsAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 新增支付记录。
/// </summary>
/// <param name="payment">支付实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddPaymentAsync(PaymentRecord payment, CancellationToken cancellationToken = default);
/// <summary>
/// 新增退款记录。
/// </summary>
/// <param name="refund">退款实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddRefundAsync(PaymentRefundRecord refund, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化变更。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 按状态筛选支付记录。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="status">支付状态。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>支付记录列表。</returns>
Task<IReadOnlyList<PaymentRecord>> SearchAsync(long tenantId, PaymentStatus? status, CancellationToken cancellationToken = default);
/// <summary>
/// 更新支付记录。
/// </summary>
/// <param name="payment">支付实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task UpdatePaymentAsync(PaymentRecord payment, CancellationToken cancellationToken = default);
/// <summary>
/// 删除支付记录及关联退款。
/// </summary>
/// <param name="paymentId">支付记录 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task DeletePaymentAsync(long paymentId, long tenantId, CancellationToken cancellationToken = default);
}

View File

@@ -1,268 +0,0 @@
using TakeoutSaaS.Domain.Products.Entities;
using TakeoutSaaS.Domain.Products.Enums;
namespace TakeoutSaaS.Domain.Products.Repositories;
/// <summary>
/// 商品聚合仓储契约。
/// </summary>
public interface IProductRepository
{
/// <summary>
/// 依据标识获取商品。
/// </summary>
Task<Product?> FindByIdAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 按分类与状态筛选商品列表。
/// </summary>
Task<IReadOnlyList<Product>> SearchAsync(long tenantId, long? storeId, long? categoryId, ProductStatus? status, CancellationToken cancellationToken = default, DateTime? updatedAfter = null);
/// <summary>
/// 获取租户下的商品分类。
/// </summary>
Task<IReadOnlyList<ProductCategory>> GetCategoriesAsync(long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取门店商品分类。
/// </summary>
Task<IReadOnlyList<ProductCategory>> GetCategoriesByStoreAsync(long tenantId, long storeId, bool onlyEnabled = true, CancellationToken cancellationToken = default);
/// <summary>
/// 获取商品 SKU。
/// </summary>
Task<IReadOnlyList<ProductSku>> GetSkusAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 批量获取商品 SKU。
/// </summary>
Task<IReadOnlyList<ProductSku>> GetSkusByProductIdsAsync(IReadOnlyCollection<long> productIds, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取商品加料组与选项。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>加料组集合。</returns>
Task<IReadOnlyList<ProductAddonGroup>> GetAddonGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 批量获取商品加料组。
/// </summary>
Task<IReadOnlyList<ProductAddonGroup>> GetAddonGroupsByProductIdsAsync(IReadOnlyCollection<long> productIds, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取商品加料选项。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>加料选项集合。</returns>
Task<IReadOnlyList<ProductAddonOption>> GetAddonOptionsAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 批量获取商品加料选项。
/// </summary>
Task<IReadOnlyList<ProductAddonOption>> GetAddonOptionsByGroupIdsAsync(IReadOnlyCollection<long> addonGroupIds, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取商品规格组与选项。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>规格组集合。</returns>
Task<IReadOnlyList<ProductAttributeGroup>> GetAttributeGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 批量获取商品规格组。
/// </summary>
Task<IReadOnlyList<ProductAttributeGroup>> GetAttributeGroupsByProductIdsAsync(IReadOnlyCollection<long> productIds, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取商品规格选项。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>规格选项集合。</returns>
Task<IReadOnlyList<ProductAttributeOption>> GetAttributeOptionsAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 批量获取商品规格选项。
/// </summary>
Task<IReadOnlyList<ProductAttributeOption>> GetAttributeOptionsByGroupIdsAsync(IReadOnlyCollection<long> attributeGroupIds, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取商品媒资。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>媒资列表。</returns>
Task<IReadOnlyList<ProductMediaAsset>> GetMediaAssetsAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 批量获取商品媒资。
/// </summary>
Task<IReadOnlyList<ProductMediaAsset>> GetMediaAssetsByProductIdsAsync(IReadOnlyCollection<long> productIds, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 获取商品定价规则。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>定价规则集合。</returns>
Task<IReadOnlyList<ProductPricingRule>> GetPricingRulesAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 批量获取商品定价规则。
/// </summary>
Task<IReadOnlyList<ProductPricingRule>> GetPricingRulesByProductIdsAsync(IReadOnlyCollection<long> productIds, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 新增分类。
/// </summary>
/// <param name="category">分类实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddCategoryAsync(ProductCategory category, CancellationToken cancellationToken = default);
/// <summary>
/// 新增商品。
/// </summary>
/// <param name="product">商品实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddProductAsync(Product product, CancellationToken cancellationToken = default);
/// <summary>
/// 新增 SKU。
/// </summary>
/// <param name="skus">SKU 集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddSkusAsync(IEnumerable<ProductSku> skus, CancellationToken cancellationToken = default);
/// <summary>
/// 新增加料组与选项。
/// </summary>
/// <param name="groups">加料组集合。</param>
/// <param name="options">加料选项集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddAddonGroupsAsync(IEnumerable<ProductAddonGroup> groups, IEnumerable<ProductAddonOption> options, CancellationToken cancellationToken = default);
/// <summary>
/// 新增规格组与选项。
/// </summary>
/// <param name="groups">规格组集合。</param>
/// <param name="options">规格选项集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddAttributeGroupsAsync(IEnumerable<ProductAttributeGroup> groups, IEnumerable<ProductAttributeOption> options, CancellationToken cancellationToken = default);
/// <summary>
/// 新增媒资。
/// </summary>
/// <param name="assets">媒资集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddMediaAssetsAsync(IEnumerable<ProductMediaAsset> assets, CancellationToken cancellationToken = default);
/// <summary>
/// 新增定价规则。
/// </summary>
/// <param name="rules">定价规则集合。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddPricingRulesAsync(IEnumerable<ProductPricingRule> rules, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化变更。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 更新商品。
/// </summary>
/// <param name="product">商品实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task UpdateProductAsync(Product product, CancellationToken cancellationToken = default);
/// <summary>
/// 删除商品。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task DeleteProductAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 更新分类。
/// </summary>
/// <param name="category">分类实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task UpdateCategoryAsync(ProductCategory category, CancellationToken cancellationToken = default);
/// <summary>
/// 删除分类。
/// </summary>
/// <param name="categoryId">分类 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task DeleteCategoryAsync(long categoryId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 删除商品下的 SKU。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task RemoveSkusAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 删除商品下的加料组及选项。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task RemoveAddonGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 删除商品下的规格组及选项。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task RemoveAttributeGroupsAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 删除商品媒资。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task RemoveMediaAssetsAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
/// <summary>
/// 删除商品定价规则。
/// </summary>
/// <param name="productId">商品 ID。</param>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task RemovePricingRulesAsync(long productId, long tenantId, CancellationToken cancellationToken = default);
}

View File

@@ -1,22 +0,0 @@
namespace TakeoutSaaS.Domain.Stores.Events;
/// <summary>
/// 门店审核通过事件。
/// </summary>
public sealed class StoreApprovedEvent
{
/// <summary>
/// 门店 ID。
/// </summary>
public long StoreId { get; init; }
/// <summary>
/// 租户 ID。
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 审核通过时间UTC
/// </summary>
public DateTime ApprovedAt { get; init; }
}

View File

@@ -1,27 +0,0 @@
namespace TakeoutSaaS.Domain.Stores.Events;
/// <summary>
/// 门店强制关闭事件。
/// </summary>
public sealed class StoreForceClosedEvent
{
/// <summary>
/// 门店 ID。
/// </summary>
public long StoreId { get; init; }
/// <summary>
/// 租户 ID。
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 强制关闭原因。
/// </summary>
public string? Reason { get; init; }
/// <summary>
/// 强制关闭时间UTC
/// </summary>
public DateTime ForceClosedAt { get; init; }
}

View File

@@ -1,32 +0,0 @@
namespace TakeoutSaaS.Domain.Stores.Events;
/// <summary>
/// 门店审核驳回事件。
/// </summary>
public sealed class StoreRejectedEvent
{
/// <summary>
/// 门店 ID。
/// </summary>
public long StoreId { get; init; }
/// <summary>
/// 租户 ID。
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 驳回理由 ID。
/// </summary>
public long? RejectionReasonId { get; init; }
/// <summary>
/// 驳回理由文本。
/// </summary>
public string? RejectionReason { get; init; }
/// <summary>
/// 驳回时间UTC
/// </summary>
public DateTime RejectedAt { get; init; }
}

View File

@@ -1,22 +0,0 @@
namespace TakeoutSaaS.Domain.Stores.Events;
/// <summary>
/// 门店提交审核事件。
/// </summary>
public sealed class StoreSubmittedEvent
{
/// <summary>
/// 门店 ID。
/// </summary>
public long StoreId { get; init; }
/// <summary>
/// 租户 ID。
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 提交时间UTC
/// </summary>
public DateTime SubmittedAt { get; init; }
}

View File

@@ -1,65 +0,0 @@
using TakeoutSaaS.Domain.SystemParameters.Entities;
namespace TakeoutSaaS.Domain.SystemParameters.Repositories;
/// <summary>
/// 系统参数仓储接口:提供基础 CRUD 与查询能力。
/// </summary>
public interface ISystemParameterRepository
{
/// <summary>
/// 根据标识获取系统参数。
/// </summary>
/// <param name="id">参数 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>系统参数或 null。</returns>
Task<SystemParameter?> FindByIdAsync(long id, CancellationToken cancellationToken = default);
/// <summary>
/// 根据键获取系统参数(当前租户)。
/// </summary>
/// <param name="key">参数键。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>系统参数或 null。</returns>
Task<SystemParameter?> FindByKeyAsync(string key, CancellationToken cancellationToken = default);
/// <summary>
/// 查询系统参数列表。
/// </summary>
/// <param name="keyword">关键字。</param>
/// <param name="isEnabled">启用状态。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>参数列表。</returns>
Task<IReadOnlyList<SystemParameter>> SearchAsync(string? keyword, bool? isEnabled, CancellationToken cancellationToken = default);
/// <summary>
/// 新增系统参数。
/// </summary>
/// <param name="parameter">参数实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddAsync(SystemParameter parameter, CancellationToken cancellationToken = default);
/// <summary>
/// 删除系统参数。
/// </summary>
/// <param name="parameter">参数实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task RemoveAsync(SystemParameter parameter, CancellationToken cancellationToken = default);
/// <summary>
/// 更新系统参数。
/// </summary>
/// <param name="parameter">参数实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task UpdateAsync(SystemParameter parameter, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化更改。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,22 +0,0 @@
namespace TakeoutSaaS.Domain.Tenants.Enums;
/// <summary>
/// 账单导出格式。
/// </summary>
public enum BillingExportFormat
{
/// <summary>
/// Excel 格式(.xlsx
/// </summary>
Excel = 0,
/// <summary>
/// PDF 格式(.pdf
/// </summary>
Pdf = 1,
/// <summary>
/// CSV 格式(.csv
/// </summary>
Csv = 2
}

View File

@@ -1,22 +0,0 @@
namespace TakeoutSaaS.Domain.Tenants.Events;
/// <summary>
/// 公告发布事件。
/// </summary>
public sealed class AnnouncementPublished
{
/// <summary>
/// 公告 ID。
/// </summary>
public long AnnouncementId { get; init; }
/// <summary>
/// 发布时间UTC
/// </summary>
public DateTime PublishedAt { get; init; }
/// <summary>
/// 目标受众类型。
/// </summary>
public string TargetType { get; init; } = string.Empty;
}

View File

@@ -1,17 +0,0 @@
namespace TakeoutSaaS.Domain.Tenants.Events;
/// <summary>
/// 公告撤销事件。
/// </summary>
public sealed class AnnouncementRevoked
{
/// <summary>
/// 公告 ID。
/// </summary>
public long AnnouncementId { get; init; }
/// <summary>
/// 撤销时间UTC
/// </summary>
public DateTime RevokedAt { get; init; }
}

View File

@@ -1,131 +0,0 @@
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
namespace TakeoutSaaS.Domain.Tenants.Repositories;
/// <summary>
/// 配额包仓储。
/// </summary>
public interface IQuotaPackageRepository
{
#region
/// <summary>
/// 按 ID 查找配额包。
/// </summary>
/// <param name="id">配额包 ID雪花算法。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>配额包实体,未找到返回 null。</returns>
Task<QuotaPackage?> FindByIdAsync(long id, CancellationToken cancellationToken = default);
/// <summary>
/// 分页查询配额包。
/// </summary>
/// <param name="quotaType">配额类型,为空不按类型过滤。</param>
/// <param name="isActive">启用状态,为空不按状态过滤。</param>
/// <param name="page">页码(从 1 开始)。</param>
/// <param name="pageSize">每页大小。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分页数据与总数。</returns>
Task<(IReadOnlyList<QuotaPackage> Items, int Total)> SearchPagedAsync(
TenantQuotaType? quotaType,
bool? isActive,
int page,
int pageSize,
CancellationToken cancellationToken = default);
/// <summary>
/// 新增配额包。
/// </summary>
/// <param name="quotaPackage">配额包实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddAsync(QuotaPackage quotaPackage, CancellationToken cancellationToken = default);
/// <summary>
/// 更新配额包。
/// </summary>
/// <param name="quotaPackage">配额包实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task UpdateAsync(QuotaPackage quotaPackage, CancellationToken cancellationToken = default);
/// <summary>
/// 软删除配额包。
/// </summary>
/// <param name="id">配额包 ID雪花算法。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>删除成功返回 true未找到返回 false。</returns>
Task<bool> SoftDeleteAsync(long id, CancellationToken cancellationToken = default);
#endregion
#region
/// <summary>
/// 分页查询租户配额购买记录(包含配额包信息)。
/// </summary>
/// <param name="tenantId">租户 ID雪花算法。</param>
/// <param name="page">页码(从 1 开始)。</param>
/// <param name="pageSize">每页大小。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分页数据与总数。</returns>
Task<(IReadOnlyList<(TenantQuotaPackagePurchase Purchase, QuotaPackage Package)> Items, int Total)> GetPurchasesPagedAsync(
long tenantId,
int page,
int pageSize,
CancellationToken cancellationToken = default);
/// <summary>
/// 新增配额购买记录。
/// </summary>
/// <param name="purchase">购买记录实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddPurchaseAsync(TenantQuotaPackagePurchase purchase, CancellationToken cancellationToken = default);
#endregion
#region 使
/// <summary>
/// 查询租户配额使用情况。
/// </summary>
/// <param name="tenantId">租户 ID雪花算法。</param>
/// <param name="quotaType">配额类型,为空查询全部。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>配额使用情况列表。</returns>
Task<IReadOnlyList<TenantQuotaUsage>> GetUsageByTenantAsync(
long tenantId,
TenantQuotaType? quotaType,
CancellationToken cancellationToken = default);
/// <summary>
/// 查找特定配额使用记录。
/// </summary>
/// <param name="tenantId">租户 ID雪花算法。</param>
/// <param name="quotaType">配额类型。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>配额使用记录,未找到返回 null。</returns>
Task<TenantQuotaUsage?> FindUsageAsync(
long tenantId,
TenantQuotaType quotaType,
CancellationToken cancellationToken = default);
/// <summary>
/// 更新配额使用情况。
/// </summary>
/// <param name="usage">配额使用实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task UpdateUsageAsync(TenantQuotaUsage usage, CancellationToken cancellationToken = default);
#endregion
/// <summary>
/// 持久化。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,112 +0,0 @@
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
namespace TakeoutSaaS.Domain.Tenants.Repositories;
/// <summary>
/// 统计数据仓储接口。
/// </summary>
public interface IStatisticsRepository
{
#region
/// <summary>
/// 获取所有订阅(用于统计)。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>所有订阅记录。</returns>
Task<IReadOnlyList<TenantSubscription>> GetAllSubscriptionsAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 获取即将到期的订阅(含租户和套餐信息)。
/// </summary>
/// <param name="daysAhead">到期天数。</param>
/// <param name="onlyWithoutAutoRenew">是否仅查询未开启自动续费的。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>即将到期的订阅信息列表。</returns>
Task<IReadOnlyList<ExpiringSubscriptionInfo>> GetExpiringSubscriptionsAsync(
int daysAhead,
bool onlyWithoutAutoRenew,
CancellationToken cancellationToken = default);
#endregion
#region
/// <summary>
/// 获取所有已付款账单(用于收入统计)。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>已付款账单列表。</returns>
Task<IReadOnlyList<TenantBillingStatement>> GetPaidBillsAsync(CancellationToken cancellationToken = default);
#endregion
#region 使
/// <summary>
/// 获取配额使用排行(含租户信息)。
/// </summary>
/// <param name="quotaType">配额类型。</param>
/// <param name="topN">前 N 名。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>配额使用排行列表。</returns>
Task<IReadOnlyList<QuotaUsageRankInfo>> GetQuotaUsageRankingAsync(
TenantQuotaType quotaType,
int topN,
CancellationToken cancellationToken = default);
#endregion
}
/// <summary>
/// 即将到期的订阅信息(含关联数据)。
/// </summary>
public record ExpiringSubscriptionInfo
{
/// <summary>
/// 订阅实体。
/// </summary>
public required TenantSubscription Subscription { get; init; }
/// <summary>
/// 租户名称。
/// </summary>
public required string TenantName { get; init; }
/// <summary>
/// 套餐名称。
/// </summary>
public required string PackageName { get; init; }
}
/// <summary>
/// 配额使用排行信息(含租户名称)。
/// </summary>
public record QuotaUsageRankInfo
{
/// <summary>
/// 租户 ID。
/// </summary>
public long TenantId { get; init; }
/// <summary>
/// 租户名称。
/// </summary>
public required string TenantName { get; init; }
/// <summary>
/// 已使用值。
/// </summary>
public decimal UsedValue { get; init; }
/// <summary>
/// 限制值。
/// </summary>
public decimal LimitValue { get; init; }
/// <summary>
/// 使用百分比。
/// </summary>
public decimal UsagePercentage { get; init; }
}

View File

@@ -1,382 +0,0 @@
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
namespace TakeoutSaaS.Domain.Tenants.Repositories;
/// <summary>
/// 订阅管理仓储接口。
/// </summary>
public interface ISubscriptionRepository
{
#region
/// <summary>
/// 按 ID 查询订阅。
/// </summary>
/// <param name="subscriptionId">订阅 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>订阅实体,未找到返回 null。</returns>
Task<TenantSubscription?> FindByIdAsync(
long subscriptionId,
CancellationToken cancellationToken = default);
/// <summary>
/// 按 ID 列表批量查询订阅。
/// </summary>
/// <param name="subscriptionIds">订阅 ID 列表。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>订阅实体列表。</returns>
Task<IReadOnlyList<TenantSubscription>> FindByIdsAsync(
IEnumerable<long> subscriptionIds,
CancellationToken cancellationToken = default);
/// <summary>
/// 分页查询订阅列表(含关联信息)。
/// </summary>
/// <param name="filter">查询过滤条件。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>分页结果。</returns>
Task<(IReadOnlyList<SubscriptionWithRelations> Items, int Total)> SearchPagedAsync(
SubscriptionSearchFilter filter,
CancellationToken cancellationToken = default);
/// <summary>
/// 获取订阅详情(含关联信息)。
/// </summary>
/// <param name="subscriptionId">订阅 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>订阅详情信息。</returns>
Task<SubscriptionDetailInfo?> GetDetailAsync(
long subscriptionId,
CancellationToken cancellationToken = default);
/// <summary>
/// 按 ID 列表批量查询订阅(含租户信息)。
/// </summary>
/// <param name="subscriptionIds">订阅 ID 列表。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>订阅与租户信息列表。</returns>
Task<IReadOnlyList<SubscriptionWithTenant>> FindByIdsWithTenantAsync(
IEnumerable<long> subscriptionIds,
CancellationToken cancellationToken = default);
/// <summary>
/// 查询自动续费候选订阅(活跃 + 开启自动续费 + 即将到期)。
/// </summary>
/// <param name="now">当前时间UTC。</param>
/// <param name="renewalThreshold">续费阈值时间UTC到期时间小于等于该时间视为候选。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>候选订阅集合(含套餐信息)。</returns>
Task<IReadOnlyList<AutoRenewalCandidate>> FindAutoRenewalCandidatesAsync(
DateTime now,
DateTime renewalThreshold,
CancellationToken cancellationToken = default);
/// <summary>
/// 查询续费提醒候选订阅(活跃 + 未开启自动续费 + 到期时间落在指定日期范围)。
/// </summary>
/// <param name="startOfDay">筛选开始时间UTC。</param>
/// <param name="endOfDay">筛选结束时间UTC不含。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>候选订阅集合(含租户与套餐信息)。</returns>
Task<IReadOnlyList<RenewalReminderCandidate>> FindRenewalReminderCandidatesAsync(
DateTime startOfDay,
DateTime endOfDay,
CancellationToken cancellationToken = default);
/// <summary>
/// 查询已到期仍处于 Active 的订阅(用于进入宽限期)。
/// </summary>
/// <param name="now">当前时间UTC。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>到期订阅集合。</returns>
Task<IReadOnlyList<TenantSubscription>> FindExpiredActiveSubscriptionsAsync(
DateTime now,
CancellationToken cancellationToken = default);
/// <summary>
/// 查询宽限期已结束的订阅(用于自动暂停)。
/// </summary>
/// <param name="now">当前时间UTC。</param>
/// <param name="gracePeriodDays">宽限期天数。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>宽限期到期订阅集合。</returns>
Task<IReadOnlyList<TenantSubscription>> FindGracePeriodExpiredSubscriptionsAsync(
DateTime now,
int gracePeriodDays,
CancellationToken cancellationToken = default);
#endregion
#region
/// <summary>
/// 按 ID 查询套餐。
/// </summary>
/// <param name="packageId">套餐 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>套餐实体,未找到返回 null。</returns>
Task<TenantPackage?> FindPackageByIdAsync(long packageId, CancellationToken cancellationToken = default);
#endregion
#region
/// <summary>
/// 更新订阅。
/// </summary>
/// <param name="subscription">订阅实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task UpdateAsync(TenantSubscription subscription, CancellationToken cancellationToken = default);
#endregion
#region
/// <summary>
/// 添加订阅变更历史。
/// </summary>
/// <param name="history">历史记录实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task AddHistoryAsync(TenantSubscriptionHistory history, CancellationToken cancellationToken = default);
/// <summary>
/// 获取订阅变更历史(含套餐名称)。
/// </summary>
/// <param name="subscriptionId">订阅 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>历史记录列表。</returns>
Task<IReadOnlyList<SubscriptionHistoryWithPackageNames>> GetHistoryAsync(
long subscriptionId,
CancellationToken cancellationToken = default);
#endregion
#region 使
/// <summary>
/// 获取租户配额使用情况。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>配额使用列表。</returns>
Task<IReadOnlyList<TenantQuotaUsage>> GetQuotaUsagesAsync(
long tenantId,
CancellationToken cancellationToken = default);
#endregion
#region
/// <summary>
/// 添加租户通知。
/// </summary>
/// <param name="notification">通知实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task AddNotificationAsync(TenantNotification notification, CancellationToken cancellationToken = default);
#endregion
#region
/// <summary>
/// 添加操作日志。
/// </summary>
/// <param name="log">日志实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task AddOperationLogAsync(OperationLog log, CancellationToken cancellationToken = default);
#endregion
/// <summary>
/// 保存变更。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}
#region
/// <summary>
/// 订阅查询过滤条件。
/// </summary>
public record SubscriptionSearchFilter
{
/// <summary>
/// 订阅状态。
/// </summary>
public SubscriptionStatus? Status { get; init; }
/// <summary>
/// 套餐 ID。
/// </summary>
public long? TenantPackageId { get; init; }
/// <summary>
/// 租户 ID。
/// </summary>
public long? TenantId { get; init; }
/// <summary>
/// 租户关键词(名称或编码)。
/// </summary>
public string? TenantKeyword { get; init; }
/// <summary>
/// 即将到期天数。
/// </summary>
public int? ExpiringWithinDays { get; init; }
/// <summary>
/// 自动续费状态。
/// </summary>
public bool? AutoRenew { get; init; }
/// <summary>
/// 页码(从 1 开始)。
/// </summary>
public int Page { get; init; } = 1;
/// <summary>
/// 每页数量。
/// </summary>
public int PageSize { get; init; } = 20;
}
/// <summary>
/// 订阅及关联信息。
/// </summary>
public record SubscriptionWithRelations
{
/// <summary>
/// 订阅实体。
/// </summary>
public required TenantSubscription Subscription { get; init; }
/// <summary>
/// 租户名称。
/// </summary>
public required string TenantName { get; init; }
/// <summary>
/// 租户编码。
/// </summary>
public required string TenantCode { get; init; }
/// <summary>
/// 套餐名称。
/// </summary>
public required string PackageName { get; init; }
/// <summary>
/// 排期套餐名称(可选)。
/// </summary>
public string? ScheduledPackageName { get; init; }
}
/// <summary>
/// 订阅详情信息。
/// </summary>
public record SubscriptionDetailInfo
{
/// <summary>
/// 订阅实体。
/// </summary>
public required TenantSubscription Subscription { get; init; }
/// <summary>
/// 租户名称。
/// </summary>
public required string TenantName { get; init; }
/// <summary>
/// 租户编码。
/// </summary>
public required string TenantCode { get; init; }
/// <summary>
/// 当前套餐。
/// </summary>
public TenantPackage? Package { get; init; }
/// <summary>
/// 排期套餐。
/// </summary>
public TenantPackage? ScheduledPackage { get; init; }
}
/// <summary>
/// 订阅与租户信息。
/// </summary>
public record SubscriptionWithTenant
{
/// <summary>
/// 订阅实体。
/// </summary>
public required TenantSubscription Subscription { get; init; }
/// <summary>
/// 租户实体。
/// </summary>
public required Tenant Tenant { get; init; }
}
/// <summary>
/// 自动续费候选订阅信息。
/// </summary>
public sealed record AutoRenewalCandidate
{
/// <summary>
/// 订阅实体。
/// </summary>
public required TenantSubscription Subscription { get; init; }
/// <summary>
/// 当前套餐实体。
/// </summary>
public required TenantPackage Package { get; init; }
}
/// <summary>
/// 续费提醒候选订阅信息。
/// </summary>
public sealed record RenewalReminderCandidate
{
/// <summary>
/// 订阅实体。
/// </summary>
public required TenantSubscription Subscription { get; init; }
/// <summary>
/// 租户实体。
/// </summary>
public required Tenant Tenant { get; init; }
/// <summary>
/// 当前套餐实体。
/// </summary>
public required TenantPackage Package { get; init; }
}
/// <summary>
/// 订阅历史(含套餐名称)。
/// </summary>
public record SubscriptionHistoryWithPackageNames
{
/// <summary>
/// 历史记录实体。
/// </summary>
public required TenantSubscriptionHistory History { get; init; }
/// <summary>
/// 原套餐名称。
/// </summary>
public required string FromPackageName { get; init; }
/// <summary>
/// 目标套餐名称。
/// </summary>
public required string ToPackageName { get; init; }
}
#endregion

View File

@@ -1,53 +0,0 @@
using TakeoutSaaS.Domain.Tenants.Entities;
namespace TakeoutSaaS.Domain.Tenants.Repositories;
/// <summary>
/// 公告已读仓储。
/// </summary>
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);
/// <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);
/// <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);
/// <summary>
/// 新增已读记录。
/// </summary>
/// <param name="record">已读实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddAsync(TenantAnnouncementRead record, CancellationToken cancellationToken = default);
/// <summary>
/// 保存变更。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,97 +0,0 @@
using TakeoutSaaS.Domain.Tenants.Entities;
using TakeoutSaaS.Domain.Tenants.Enums;
namespace TakeoutSaaS.Domain.Tenants.Repositories;
/// <summary>
/// 租户公告仓储。
/// </summary>
public interface ITenantAnnouncementRepository
{
/// <summary>
/// 查询公告列表,按类型、状态与生效时间筛选。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="keyword">关键词(标题/内容)。</param>
/// <param name="status">公告状态。</param>
/// <param name="type">公告类型。</param>
/// <param name="isActive">启用状态。</param>
/// <param name="effectiveFrom">生效开始时间筛选。</param>
/// <param name="effectiveTo">生效结束时间筛选。</param>
/// <param name="effectiveAt">生效时间点,为空不限制。</param>
/// <param name="orderByPriority">是否按优先级降序和生效时间降序排序,默认 false。</param>
/// <param name="limit">限制返回数量,为空不限制。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>公告集合。</returns>
Task<IReadOnlyList<TenantAnnouncement>> SearchAsync(
long tenantId,
string? keyword,
AnnouncementStatus? status,
TenantAnnouncementType? type,
bool? isActive,
DateTime? effectiveFrom,
DateTime? effectiveTo,
DateTime? effectiveAt,
bool orderByPriority = false,
int? limit = null,
CancellationToken cancellationToken = default);
/// <summary>
/// 查询未读公告。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="userId">用户 ID。</param>
/// <param name="status">公告状态。</param>
/// <param name="isActive">启用状态。</param>
/// <param name="effectiveAt">生效时间点,为空不限制。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>未读公告集合。</returns>
Task<IReadOnlyList<TenantAnnouncement>> SearchUnreadAsync(
long tenantId,
long? userId,
AnnouncementStatus? status,
bool? isActive,
DateTime? effectiveAt,
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);
/// <summary>
/// 新增公告。
/// </summary>
/// <param name="announcement">公告实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task AddAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default);
/// <summary>
/// 更新公告。
/// </summary>
/// <param name="announcement">公告实体。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task UpdateAsync(TenantAnnouncement announcement, CancellationToken cancellationToken = default);
/// <summary>
/// 删除公告。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="announcementId">公告 ID。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task DeleteAsync(long tenantId, long announcementId, CancellationToken cancellationToken = default);
/// <summary>
/// 保存变更。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>异步任务。</returns>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,23 +0,0 @@
using TakeoutSaaS.Domain.Tenants.Entities;
namespace TakeoutSaaS.Domain.Tenants.Repositories;
/// <summary>
/// 租户配额使用历史仓储。
/// </summary>
public interface ITenantQuotaUsageHistoryRepository
{
/// <summary>
/// 新增历史记录。
/// </summary>
/// <param name="history">历史记录实体。</param>
/// <param name="cancellationToken">取消标记。</param>
Task AddAsync(TenantQuotaUsageHistory history, CancellationToken cancellationToken = default);
/// <summary>
/// 持久化。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
Task SaveChangesAsync(CancellationToken cancellationToken = default);
}

View File

@@ -1,64 +0,0 @@
using TakeoutSaaS.Domain.Tenants.Entities;
namespace TakeoutSaaS.Domain.Tenants.Services;
/// <summary>
/// 账单领域服务接口。
/// 负责处理账单生成、账单编号生成、逾期处理等跨实体的业务逻辑。
/// </summary>
public interface IBillingDomainService
{
/// <summary>
/// 根据订阅信息生成账单。
/// </summary>
/// <param name="subscription">租户订阅信息。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>生成的账单实体。</returns>
Task<TenantBillingStatement> GenerateSubscriptionBillingAsync(
TenantSubscription subscription,
CancellationToken cancellationToken = default);
/// <summary>
/// 根据配额包购买信息生成账单。
/// </summary>
/// <param name="tenantId">租户 ID。</param>
/// <param name="quotaPackage">配额包信息。</param>
/// <param name="quantity">购买数量。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>生成的账单实体。</returns>
Task<TenantBillingStatement> GenerateQuotaPurchaseBillingAsync(
long tenantId,
QuotaPackage quotaPackage,
int quantity,
CancellationToken cancellationToken = default);
/// <summary>
/// 生成唯一的账单编号。
/// 格式示例BIL-20251217-000001
/// </summary>
/// <returns>账单编号。</returns>
string GenerateStatementNo();
/// <summary>
/// 处理逾期账单(批量标记逾期状态)。
/// </summary>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>处理的账单数量。</returns>
Task<int> ProcessOverdueBillingsAsync(CancellationToken cancellationToken = default);
/// <summary>
/// 计算账单总金额(含折扣和税费)。
/// </summary>
/// <param name="baseAmount">基础金额。</param>
/// <param name="discountAmount">折扣金额。</param>
/// <param name="taxAmount">税费金额。</param>
/// <returns>总金额。</returns>
decimal CalculateTotalAmount(decimal baseAmount, decimal discountAmount, decimal taxAmount);
/// <summary>
/// 验证账单状态是否可以进行支付操作。
/// </summary>
/// <param name="billing">账单实体。</param>
/// <returns>是否可以支付。</returns>
bool CanProcessPayment(TenantBillingStatement billing);
}

View File

@@ -1,33 +0,0 @@
using TakeoutSaaS.Domain.Tenants.Entities;
namespace TakeoutSaaS.Domain.Tenants.Services;
/// <summary>
/// 账单导出服务接口。
/// </summary>
public interface IBillingExportService
{
/// <summary>
/// 导出为 ExcelXLSX
/// </summary>
/// <param name="billings">账单数据。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>文件字节数组。</returns>
Task<byte[]> ExportToExcelAsync(IReadOnlyList<TenantBillingStatement> billings, CancellationToken cancellationToken = default);
/// <summary>
/// 导出为 PDF。
/// </summary>
/// <param name="billings">账单数据。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>文件字节数组。</returns>
Task<byte[]> ExportToPdfAsync(IReadOnlyList<TenantBillingStatement> billings, CancellationToken cancellationToken = default);
/// <summary>
/// 导出为 CSV。
/// </summary>
/// <param name="billings">账单数据。</param>
/// <param name="cancellationToken">取消标记。</param>
/// <returns>文件字节数组。</returns>
Task<byte[]> ExportToCsvAsync(IReadOnlyList<TenantBillingStatement> billings, CancellationToken cancellationToken = default);
}