feat:商户管理
This commit is contained in:
17
src/Domain/TakeoutSaaS.Domain/Common/Enums/OperatingMode.cs
Normal file
17
src/Domain/TakeoutSaaS.Domain/Common/Enums/OperatingMode.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
namespace TakeoutSaaS.Domain.Common.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 经营模式。
|
||||
/// </summary>
|
||||
public enum OperatingMode
|
||||
{
|
||||
/// <summary>
|
||||
/// 同一主体。
|
||||
/// </summary>
|
||||
SameEntity = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 不同主体。
|
||||
/// </summary>
|
||||
DifferentEntity = 2
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using TakeoutSaaS.Domain.Common.Enums;
|
||||
using TakeoutSaaS.Domain.Merchants.Enums;
|
||||
using TakeoutSaaS.Shared.Abstractions.Entities;
|
||||
|
||||
@@ -103,6 +104,31 @@ public sealed class Merchant : MultiTenantEntityBase
|
||||
/// </summary>
|
||||
public MerchantStatus Status { get; set; } = MerchantStatus.Pending;
|
||||
|
||||
/// <summary>
|
||||
/// 经营模式(同一主体/不同主体)。
|
||||
/// </summary>
|
||||
public OperatingMode? OperatingMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否冻结业务。
|
||||
/// </summary>
|
||||
public bool IsFrozen { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 冻结原因。
|
||||
/// </summary>
|
||||
public string? FrozenReason { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 冻结时间。
|
||||
/// </summary>
|
||||
public DateTime? FrozenAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 最近一次审核人。
|
||||
/// </summary>
|
||||
public long? LastReviewedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 审核备注或驳回原因。
|
||||
/// </summary>
|
||||
@@ -117,4 +143,39 @@ public sealed class Merchant : MultiTenantEntityBase
|
||||
/// 最近一次审核时间。
|
||||
/// </summary>
|
||||
public DateTime? LastReviewedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 审核通过人。
|
||||
/// </summary>
|
||||
public long? ApprovedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 审核通过时间。
|
||||
/// </summary>
|
||||
public DateTime? ApprovedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前领取人。
|
||||
/// </summary>
|
||||
public long? ClaimedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前领取人姓名。
|
||||
/// </summary>
|
||||
public string? ClaimedByName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 领取时间。
|
||||
/// </summary>
|
||||
public DateTime? ClaimedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 领取过期时间。
|
||||
/// </summary>
|
||||
public DateTime? ClaimExpiresAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 并发控制版本。
|
||||
/// </summary>
|
||||
public byte[] RowVersion { get; set; } = Array.Empty<byte>();
|
||||
}
|
||||
|
||||
@@ -37,4 +37,9 @@ public sealed class MerchantAuditLog : MultiTenantEntityBase
|
||||
/// 操作人名称。
|
||||
/// </summary>
|
||||
public string? OperatorName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 操作 IP。
|
||||
/// </summary>
|
||||
public string? IpAddress { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using TakeoutSaaS.Shared.Abstractions.Entities;
|
||||
|
||||
namespace TakeoutSaaS.Domain.Merchants.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// 商户变更日志。
|
||||
/// </summary>
|
||||
public sealed class MerchantChangeLog : MultiTenantEntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 商户标识。
|
||||
/// </summary>
|
||||
public long MerchantId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 变更字段名。
|
||||
/// </summary>
|
||||
public string FieldName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 变更前值。
|
||||
/// </summary>
|
||||
public string? OldValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 变更后值。
|
||||
/// </summary>
|
||||
public string? NewValue { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 变更类型。
|
||||
/// </summary>
|
||||
public string ChangeType { get; set; } = "Update";
|
||||
|
||||
/// <summary>
|
||||
/// 变更人 ID。
|
||||
/// </summary>
|
||||
public long? ChangedBy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 变更人名称。
|
||||
/// </summary>
|
||||
public string? ChangedByName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 变更原因。
|
||||
/// </summary>
|
||||
public string? ChangeReason { get; set; }
|
||||
}
|
||||
@@ -33,5 +33,40 @@ public enum MerchantAuditAction
|
||||
/// <summary>
|
||||
/// 商户审核结果。
|
||||
/// </summary>
|
||||
MerchantReviewed = 5
|
||||
MerchantReviewed = 5,
|
||||
|
||||
/// <summary>
|
||||
/// 领取审核。
|
||||
/// </summary>
|
||||
ReviewClaimed = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 释放审核。
|
||||
/// </summary>
|
||||
ReviewReleased = 7,
|
||||
|
||||
/// <summary>
|
||||
/// 审核通过。
|
||||
/// </summary>
|
||||
ReviewApproved = 8,
|
||||
|
||||
/// <summary>
|
||||
/// 审核驳回。
|
||||
/// </summary>
|
||||
ReviewRejected = 9,
|
||||
|
||||
/// <summary>
|
||||
/// 撤销审核。
|
||||
/// </summary>
|
||||
ReviewRevoked = 10,
|
||||
|
||||
/// <summary>
|
||||
/// 关键信息变更进入待审核。
|
||||
/// </summary>
|
||||
ReviewPendingReApproval = 11,
|
||||
|
||||
/// <summary>
|
||||
/// 强制接管审核。
|
||||
/// </summary>
|
||||
ReviewForceClaimed = 12
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using TakeoutSaaS.Domain.Common.Enums;
|
||||
using TakeoutSaaS.Domain.Merchants.Entities;
|
||||
using TakeoutSaaS.Domain.Merchants.Enums;
|
||||
|
||||
@@ -17,6 +18,22 @@ public interface IMerchantRepository
|
||||
/// <returns>商户实体或 null。</returns>
|
||||
Task<Merchant?> FindByIdAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 依据标识获取商户(忽略租户过滤)。
|
||||
/// </summary>
|
||||
/// <param name="merchantId">商户 ID。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>商户实体或 null。</returns>
|
||||
Task<Merchant?> FindByIdAsync(long merchantId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 依据租户标识获取商户(忽略租户过滤)。
|
||||
/// </summary>
|
||||
/// <param name="tenantId">租户 ID。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>商户实体或 null。</returns>
|
||||
Task<Merchant?> FindByTenantIdAsync(long tenantId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 按状态筛选商户列表。
|
||||
/// </summary>
|
||||
@@ -26,6 +43,22 @@ public interface IMerchantRepository
|
||||
/// <returns>商户集合。</returns>
|
||||
Task<IReadOnlyList<Merchant>> SearchAsync(long tenantId, MerchantStatus? status, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 按条件筛选商户列表(支持跨租户)。
|
||||
/// </summary>
|
||||
/// <param name="tenantId">租户 ID,为 null 时查询全部租户。</param>
|
||||
/// <param name="status">状态过滤。</param>
|
||||
/// <param name="operatingMode">经营模式过滤。</param>
|
||||
/// <param name="keyword">关键词过滤。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>商户集合。</returns>
|
||||
Task<IReadOnlyList<Merchant>> SearchAsync(
|
||||
long? tenantId,
|
||||
MerchantStatus? status,
|
||||
OperatingMode? operatingMode,
|
||||
string? keyword,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定商户的员工列表。
|
||||
/// </summary>
|
||||
@@ -168,6 +201,14 @@ public interface IMerchantRepository
|
||||
/// <returns>异步任务。</returns>
|
||||
Task AddAuditLogAsync(MerchantAuditLog log, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 记录变更日志。
|
||||
/// </summary>
|
||||
/// <param name="log">变更日志实体。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>异步任务。</returns>
|
||||
Task AddChangeLogAsync(MerchantChangeLog log, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 获取审核日志。
|
||||
/// </summary>
|
||||
@@ -176,4 +217,18 @@ public interface IMerchantRepository
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>审核日志列表。</returns>
|
||||
Task<IReadOnlyList<MerchantAuditLog>> GetAuditLogsAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 获取变更日志。
|
||||
/// </summary>
|
||||
/// <param name="merchantId">商户 ID。</param>
|
||||
/// <param name="tenantId">租户 ID。</param>
|
||||
/// <param name="fieldName">字段过滤。</param>
|
||||
/// <param name="cancellationToken">取消标记。</param>
|
||||
/// <returns>变更日志列表。</returns>
|
||||
Task<IReadOnlyList<MerchantChangeLog>> GetChangeLogsAsync(
|
||||
long merchantId,
|
||||
long tenantId,
|
||||
string? fieldName = null,
|
||||
CancellationToken cancellationToken = default);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
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);
|
||||
}
|
||||
@@ -33,6 +33,26 @@ public sealed class Store : MultiTenantEntityBase
|
||||
/// </summary>
|
||||
public string? ManagerName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门店营业执照号(主体不一致模式使用)。
|
||||
/// </summary>
|
||||
public string? BusinessLicenseNumber { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门店法人(主体不一致模式使用)。
|
||||
/// </summary>
|
||||
public string? LegalRepresentative { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门店注册地址(主体不一致模式使用)。
|
||||
/// </summary>
|
||||
public string? RegisteredAddress { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门店营业执照图片地址(主体不一致模式使用)。
|
||||
/// </summary>
|
||||
public string? BusinessLicenseImageUrl { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 门店当前运营状态。
|
||||
/// </summary>
|
||||
|
||||
@@ -13,11 +13,21 @@ public interface IStoreRepository
|
||||
/// </summary>
|
||||
Task<Store?> FindByIdAsync(long storeId, long tenantId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定商户的门店列表。
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<Store>> GetByMerchantIdAsync(long merchantId, long tenantId, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 按租户筛选门店列表。
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<Store>> SearchAsync(long tenantId, StoreStatus? status, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定商户集合的门店数量。
|
||||
/// </summary>
|
||||
Task<Dictionary<long, int>> GetStoreCountsAsync(long? tenantId, IReadOnlyCollection<long> merchantIds, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 获取门店营业时段。
|
||||
/// </summary>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using TakeoutSaaS.Domain.Common.Enums;
|
||||
using TakeoutSaaS.Domain.Tenants.Enums;
|
||||
using TakeoutSaaS.Shared.Abstractions.Entities;
|
||||
|
||||
@@ -93,6 +94,11 @@ public sealed class Tenant : AuditableEntityBase
|
||||
/// </summary>
|
||||
public TenantStatus Status { get; set; } = TenantStatus.PendingReview;
|
||||
|
||||
/// <summary>
|
||||
/// 经营模式(同一主体/不同主体)。
|
||||
/// </summary>
|
||||
public OperatingMode? OperatingMode { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 服务生效时间(UTC)。
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user