feat: 扩展领域模型与配置

This commit is contained in:
贺爱泽
2025-12-01 13:26:05 +08:00
parent a08804658b
commit 5ddad07658
148 changed files with 8519 additions and 2 deletions

13
.config/dotnet-tools.json Normal file
View File

@@ -0,0 +1,13 @@
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "10.0.0",
"commands": [
"dotnet-ef"
],
"rollForward": false
}
}
}

View File

@@ -198,6 +198,32 @@ dotnet ef database update
dotnet run
```
### 2.7 EF Core 迁移基线
现已内置 `dotnet-ef` 本地工具与设计时 DbContext 工厂,可直接在命令行生成/更新数据库。运行前可通过环境变量 `TAKEOUTSAAS_APP_CONNECTION``TAKEOUTSAAS_IDENTITY_CONNECTION` 覆盖默认连接串(默认指向本地 PostgreSQL
```powershell
# 业务主库TakeoutAppDbContext含租户/商户/门店/商品/订单等)
dotnet tool run dotnet-ef database update `
--project src/Infrastructure/TakeoutSaaS.Infrastructure/TakeoutSaaS.Infrastructure.csproj `
--startup-project src/Infrastructure/TakeoutSaaS.Infrastructure/TakeoutSaaS.Infrastructure.csproj `
--context TakeoutSaaS.Infrastructure.App.Persistence.TakeoutAppDbContext
# 身份库IdentityDbContext
dotnet tool run dotnet-ef database update `
--project src/Infrastructure/TakeoutSaaS.Infrastructure/TakeoutSaaS.Infrastructure.csproj `
--startup-project src/Infrastructure/TakeoutSaaS.Infrastructure/TakeoutSaaS.Infrastructure.csproj `
--context TakeoutSaaS.Infrastructure.Identity.Persistence.IdentityDbContext
# 业务/字典库DictionaryDbContext归属 AppDatabase
dotnet tool run dotnet-ef database update `
--project src/Infrastructure/TakeoutSaaS.Infrastructure/TakeoutSaaS.Infrastructure.csproj `
--startup-project src/Infrastructure/TakeoutSaaS.Infrastructure/TakeoutSaaS.Infrastructure.csproj `
--context TakeoutSaaS.Infrastructure.Dictionary.Persistence.DictionaryDbContext
```
> Hangfire 使用 Scheduler.ConnectionString 指向的数据库,首次启动服务会自动建表;只需提前创建空数据库并授予账号权限。
## 3. Docker部署
### 3.1 创建Dockerfile

View File

@@ -134,7 +134,7 @@
"PrefetchCount": 20
},
"Scheduler": {
"ConnectionString": "Host=120.53.222.17;Port=5432;Database=takeout_saas_scheduler;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
"ConnectionString": "Host=120.53.222.17;Port=5432;Database=takeout_saas_hangfire;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
"WorkerCount": 5,
"DashboardEnabled": false,
"DashboardPath": "/hangfire"

View File

@@ -134,7 +134,7 @@
"PrefetchCount": 20
},
"Scheduler": {
"ConnectionString": "Host=120.53.222.17;Port=5432;Database=takeout_saas_scheduler;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
"ConnectionString": "Host=120.53.222.17;Port=5432;Database=takeout_saas_hangfire;Username=app_user;Password=MsuMshk112233;Pooling=true;Minimum Pool Size=5;Maximum Pool Size=50",
"WorkerCount": 5,
"DashboardEnabled": false,
"DashboardPath": "/hangfire"

View File

@@ -0,0 +1,35 @@
using TakeoutSaaS.Domain.Analytics.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Analytics.Entities;
/// <summary>
/// 指标告警规则。
/// </summary>
public sealed class MetricAlertRule : MultiTenantEntityBase
{
/// <summary>
/// 关联指标。
/// </summary>
public Guid MetricDefinitionId { get; set; }
/// <summary>
/// 触发条件 JSON。
/// </summary>
public string ConditionJson { get; set; } = string.Empty;
/// <summary>
/// 告警级别。
/// </summary>
public MetricAlertSeverity Severity { get; set; } = MetricAlertSeverity.Warning;
/// <summary>
/// 通知渠道。
/// </summary>
public string NotificationChannels { get; set; } = "email";
/// <summary>
/// 是否启用。
/// </summary>
public bool Enabled { get; set; } = true;
}

View File

@@ -0,0 +1,34 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Analytics.Entities;
/// <summary>
/// 指标定义,描述可观测的数据点。
/// </summary>
public sealed class MetricDefinition : MultiTenantEntityBase
{
/// <summary>
/// 指标编码。
/// </summary>
public string Code { get; set; } = string.Empty;
/// <summary>
/// 指标名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 说明。
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 维度描述 JSON。
/// </summary>
public string? DimensionsJson { get; set; }
/// <summary>
/// 默认聚合方式。
/// </summary>
public string DefaultAggregation { get; set; } = "sum";
}

View File

@@ -0,0 +1,34 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Analytics.Entities;
/// <summary>
/// 指标快照,用于大盘展示。
/// </summary>
public sealed class MetricSnapshot : MultiTenantEntityBase
{
/// <summary>
/// 指标定义 ID。
/// </summary>
public Guid MetricDefinitionId { get; set; }
/// <summary>
/// 维度键JSON
/// </summary>
public string DimensionKey { get; set; } = string.Empty;
/// <summary>
/// 统计时间窗口开始。
/// </summary>
public DateTime WindowStart { get; set; }
/// <summary>
/// 统计时间窗口结束。
/// </summary>
public DateTime WindowEnd { get; set; }
/// <summary>
/// 数值。
/// </summary>
public decimal Value { get; set; }
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.Analytics.Enums;
/// <summary>
/// 指标告警严重程度。
/// </summary>
public enum MetricAlertSeverity
{
/// <summary>
/// 信息提示。
/// </summary>
Info = 0,
/// <summary>
/// 告警。
/// </summary>
Warning = 1,
/// <summary>
/// 严重。
/// </summary>
Critical = 2
}

View File

@@ -0,0 +1,50 @@
using TakeoutSaaS.Domain.Coupons.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Coupons.Entities;
/// <summary>
/// 用户领取的券。
/// </summary>
public sealed class Coupon : MultiTenantEntityBase
{
/// <summary>
/// 模板标识。
/// </summary>
public Guid CouponTemplateId { get; set; }
/// <summary>
/// 券码或序列号。
/// </summary>
public string Code { get; set; } = string.Empty;
/// <summary>
/// 归属用户。
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// 订单 ID已使用时记录
/// </summary>
public Guid? OrderId { get; set; }
/// <summary>
/// 状态。
/// </summary>
public CouponStatus Status { get; set; } = CouponStatus.Available;
/// <summary>
/// 发放时间。
/// </summary>
public DateTime IssuedAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// 使用时间。
/// </summary>
public DateTime? UsedAt { get; set; }
/// <summary>
/// 到期时间。
/// </summary>
public DateTime ExpireAt { get; set; }
}

View File

@@ -0,0 +1,90 @@
using TakeoutSaaS.Domain.Coupons.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Coupons.Entities;
/// <summary>
/// 优惠券模板。
/// </summary>
public sealed class CouponTemplate : MultiTenantEntityBase
{
/// <summary>
/// 模板名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 券类型。
/// </summary>
public CouponType CouponType { get; set; } = CouponType.AmountOff;
/// <summary>
/// 面值或折扣额度。
/// </summary>
public decimal Value { get; set; }
/// <summary>
/// 折扣上限(针对折扣券)。
/// </summary>
public decimal? DiscountCap { get; set; }
/// <summary>
/// 最低消费门槛。
/// </summary>
public decimal? MinimumSpend { get; set; }
/// <summary>
/// 可用开始时间。
/// </summary>
public DateTime? ValidFrom { get; set; }
/// <summary>
/// 可用结束时间。
/// </summary>
public DateTime? ValidTo { get; set; }
/// <summary>
/// 有效天数(相对发放时间)。
/// </summary>
public int? RelativeValidDays { get; set; }
/// <summary>
/// 总发放数量上限。
/// </summary>
public int? TotalQuantity { get; set; }
/// <summary>
/// 已领取数量。
/// </summary>
public int ClaimedQuantity { get; set; }
/// <summary>
/// 适用门店 ID 集合JSON
/// </summary>
public string? StoreScopeJson { get; set; }
/// <summary>
/// 适用品类或商品范围JSON
/// </summary>
public string? ProductScopeJson { get; set; }
/// <summary>
/// 发放渠道JSON
/// </summary>
public string? ChannelsJson { get; set; }
/// <summary>
/// 是否允许叠加其他优惠。
/// </summary>
public bool AllowStack { get; set; }
/// <summary>
/// 状态。
/// </summary>
public CouponTemplateStatus Status { get; set; } = CouponTemplateStatus.Draft;
/// <summary>
/// 备注。
/// </summary>
public string? Description { get; set; }
}

View File

@@ -0,0 +1,55 @@
using TakeoutSaaS.Domain.Coupons.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Coupons.Entities;
/// <summary>
/// 营销活动配置。
/// </summary>
public sealed class PromotionCampaign : MultiTenantEntityBase
{
/// <summary>
/// 活动名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 活动类型。
/// </summary>
public PromotionType PromotionType { get; set; } = PromotionType.Coupon;
/// <summary>
/// 活动状态。
/// </summary>
public PromotionStatus Status { get; set; } = PromotionStatus.Draft;
/// <summary>
/// 开始时间。
/// </summary>
public DateTime StartAt { get; set; }
/// <summary>
/// 结束时间。
/// </summary>
public DateTime EndAt { get; set; }
/// <summary>
/// 预算金额。
/// </summary>
public decimal? Budget { get; set; }
/// <summary>
/// 活动规则 JSON。
/// </summary>
public string RulesJson { get; set; } = string.Empty;
/// <summary>
/// 目标人群描述。
/// </summary>
public string? AudienceDescription { get; set; }
/// <summary>
/// 营销素材(如 banner
/// </summary>
public string? BannerUrl { get; set; }
}

View File

@@ -0,0 +1,32 @@
namespace TakeoutSaaS.Domain.Coupons.Enums;
/// <summary>
/// 券使用状态。
/// </summary>
public enum CouponStatus
{
/// <summary>
/// 可使用。
/// </summary>
Available = 0,
/// <summary>
/// 已锁定。
/// </summary>
Locked = 1,
/// <summary>
/// 已使用。
/// </summary>
Redeemed = 2,
/// <summary>
/// 已过期。
/// </summary>
Expired = 3,
/// <summary>
/// 已作废。
/// </summary>
Voided = 4
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.Coupons.Enums;
/// <summary>
/// 券模板状态。
/// </summary>
public enum CouponTemplateStatus
{
/// <summary>
/// 草稿状态。
/// </summary>
Draft = 0,
/// <summary>
/// 已上线可发放。
/// </summary>
Active = 1,
/// <summary>
/// 已下架。
/// </summary>
Archived = 2
}

View File

@@ -0,0 +1,32 @@
namespace TakeoutSaaS.Domain.Coupons.Enums;
/// <summary>
/// 券类型。
/// </summary>
public enum CouponType
{
/// <summary>
/// 满减券。
/// </summary>
AmountOff = 0,
/// <summary>
/// 折扣券。
/// </summary>
Percentage = 1,
/// <summary>
/// 现金券/无门槛券。
/// </summary>
Cash = 2,
/// <summary>
/// 免配送费券。
/// </summary>
DeliveryFee = 3,
/// <summary>
/// 礼品/兑换券。
/// </summary>
Gift = 4
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Coupons.Enums;
/// <summary>
/// 营销活动状态。
/// </summary>
public enum PromotionStatus
{
/// <summary>
/// 草稿。
/// </summary>
Draft = 0,
/// <summary>
/// 进行中。
/// </summary>
Active = 1,
/// <summary>
/// 已结束。
/// </summary>
Completed = 2,
/// <summary>
/// 暂停。
/// </summary>
Paused = 3
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Coupons.Enums;
/// <summary>
/// 营销活动类型。
/// </summary>
public enum PromotionType
{
/// <summary>
/// 优惠券活动。
/// </summary>
Coupon = 0,
/// <summary>
/// 秒杀/限时购。
/// </summary>
FlashSale = 1,
/// <summary>
/// 满减活动。
/// </summary>
FullReduction = 2,
/// <summary>
/// 抽奖活动。
/// </summary>
Lottery = 3
}

View File

@@ -0,0 +1,45 @@
using TakeoutSaaS.Domain.CustomerService.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.CustomerService.Entities;
/// <summary>
/// 会话消息。
/// </summary>
public sealed class ChatMessage : MultiTenantEntityBase
{
/// <summary>
/// 会话标识。
/// </summary>
public Guid ChatSessionId { get; set; }
/// <summary>
/// 发送方类型。
/// </summary>
public MessageSenderType SenderType { get; set; } = MessageSenderType.Customer;
/// <summary>
/// 发送方用户 ID。
/// </summary>
public Guid? SenderUserId { get; set; }
/// <summary>
/// 消息内容。
/// </summary>
public string Content { get; set; } = string.Empty;
/// <summary>
/// 消息类型(文字/图片/语音等)。
/// </summary>
public string ContentType { get; set; } = "text/plain";
/// <summary>
/// 是否已读。
/// </summary>
public bool IsRead { get; set; }
/// <summary>
/// 读取时间。
/// </summary>
public DateTime? ReadAt { get; set; }
}

View File

@@ -0,0 +1,50 @@
using TakeoutSaaS.Domain.CustomerService.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.CustomerService.Entities;
/// <summary>
/// 客服会话。
/// </summary>
public sealed class ChatSession : MultiTenantEntityBase
{
/// <summary>
/// 会话编号。
/// </summary>
public string SessionCode { get; set; } = string.Empty;
/// <summary>
/// 顾客用户 ID。
/// </summary>
public Guid CustomerUserId { get; set; }
/// <summary>
/// 当前客服员工 ID。
/// </summary>
public Guid? AgentUserId { get; set; }
/// <summary>
/// 所属门店(可空为平台)。
/// </summary>
public Guid? StoreId { get; set; }
/// <summary>
/// 会话状态。
/// </summary>
public ChatSessionStatus Status { get; set; } = ChatSessionStatus.Waiting;
/// <summary>
/// 是否机器人接待中。
/// </summary>
public bool IsBotActive { get; set; }
/// <summary>
/// 开始时间。
/// </summary>
public DateTime StartedAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// 结束时间。
/// </summary>
public DateTime? EndedAt { get; set; }
}

View File

@@ -0,0 +1,55 @@
using TakeoutSaaS.Domain.CustomerService.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.CustomerService.Entities;
/// <summary>
/// 客服工单。
/// </summary>
public sealed class SupportTicket : MultiTenantEntityBase
{
/// <summary>
/// 工单编号。
/// </summary>
public string TicketNo { get; set; } = string.Empty;
/// <summary>
/// 客户用户 ID。
/// </summary>
public Guid CustomerUserId { get; set; }
/// <summary>
/// 关联订单(如有)。
/// </summary>
public Guid? OrderId { get; set; }
/// <summary>
/// 工单主题。
/// </summary>
public string Subject { get; set; } = string.Empty;
/// <summary>
/// 工单详情。
/// </summary>
public string Description { get; set; } = string.Empty;
/// <summary>
/// 优先级。
/// </summary>
public TicketPriority Priority { get; set; } = TicketPriority.Normal;
/// <summary>
/// 状态。
/// </summary>
public TicketStatus Status { get; set; } = TicketStatus.Open;
/// <summary>
/// 指派的客服。
/// </summary>
public Guid? AssignedAgentId { get; set; }
/// <summary>
/// 关闭时间。
/// </summary>
public DateTime? ClosedAt { get; set; }
}

View File

@@ -0,0 +1,34 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.CustomerService.Entities;
/// <summary>
/// 工单评论/流转记录。
/// </summary>
public sealed class TicketComment : MultiTenantEntityBase
{
/// <summary>
/// 工单标识。
/// </summary>
public Guid SupportTicketId { get; set; }
/// <summary>
/// 评论人 ID。
/// </summary>
public Guid? AuthorUserId { get; set; }
/// <summary>
/// 评论内容。
/// </summary>
public string Content { get; set; } = string.Empty;
/// <summary>
/// 是否内部备注。
/// </summary>
public bool IsInternal { get; set; }
/// <summary>
/// 附件 JSON。
/// </summary>
public string? AttachmentsJson { get; set; }
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.CustomerService.Enums;
/// <summary>
/// 客服会话状态。
/// </summary>
public enum ChatSessionStatus
{
/// <summary>
/// 等待客服接入。
/// </summary>
Waiting = 0,
/// <summary>
/// 聊天进行中。
/// </summary>
Active = 1,
/// <summary>
/// 已转人工排队。
/// </summary>
Queueing = 2,
/// <summary>
/// 已结束。
/// </summary>
Closed = 3
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.CustomerService.Enums;
/// <summary>
/// 消息发送方类型。
/// </summary>
public enum MessageSenderType
{
/// <summary>
/// 顾客。
/// </summary>
Customer = 0,
/// <summary>
/// 客服人员。
/// </summary>
Agent = 1,
/// <summary>
/// 机器人。
/// </summary>
Bot = 2,
/// <summary>
/// 系统通知。
/// </summary>
System = 3
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.CustomerService.Enums;
/// <summary>
/// 工单优先级。
/// </summary>
public enum TicketPriority
{
/// <summary>
/// 普通。
/// </summary>
Normal = 0,
/// <summary>
/// 高。
/// </summary>
High = 1,
/// <summary>
/// 紧急。
/// </summary>
Urgent = 2
}

View File

@@ -0,0 +1,32 @@
namespace TakeoutSaaS.Domain.CustomerService.Enums;
/// <summary>
/// 工单状态。
/// </summary>
public enum TicketStatus
{
/// <summary>
/// 新建未处理。
/// </summary>
Open = 0,
/// <summary>
/// 处理中。
/// </summary>
InProgress = 1,
/// <summary>
/// 等待客户反馈。
/// </summary>
PendingCustomer = 2,
/// <summary>
/// 已解决。
/// </summary>
Resolved = 3,
/// <summary>
/// 已关闭。
/// </summary>
Closed = 4
}

View File

@@ -0,0 +1,35 @@
using TakeoutSaaS.Domain.Deliveries.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Deliveries.Entities;
/// <summary>
/// 配送状态事件流水。
/// </summary>
public sealed class DeliveryEvent : MultiTenantEntityBase
{
/// <summary>
/// 配送单标识。
/// </summary>
public Guid DeliveryOrderId { get; set; }
/// <summary>
/// 事件类型。
/// </summary>
public DeliveryEventType EventType { get; set; } = DeliveryEventType.Updated;
/// <summary>
/// 事件描述。
/// </summary>
public string Message { get; set; } = string.Empty;
/// <summary>
/// 原始数据 JSON。
/// </summary>
public string? Payload { get; set; }
/// <summary>
/// 发生时间。
/// </summary>
public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
}

View File

@@ -0,0 +1,62 @@
using TakeoutSaaS.Domain.Deliveries.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Deliveries.Entities;
/// <summary>
/// 配送单。
/// </summary>
public sealed class DeliveryOrder : MultiTenantEntityBase
{
public Guid OrderId { get; set; }
/// <summary>
/// 配送服务商。
/// </summary>
public DeliveryProvider Provider { get; set; } = DeliveryProvider.InHouse;
/// <summary>
/// 第三方配送单号。
/// </summary>
public string? ProviderOrderId { get; set; }
/// <summary>
/// 状态。
/// </summary>
public DeliveryStatus Status { get; set; } = DeliveryStatus.Pending;
/// <summary>
/// 配送费。
/// </summary>
public decimal? DeliveryFee { get; set; }
/// <summary>
/// 骑手姓名。
/// </summary>
public string? CourierName { get; set; }
/// <summary>
/// 骑手电话。
/// </summary>
public string? CourierPhone { get; set; }
/// <summary>
/// 下发时间。
/// </summary>
public DateTime? DispatchedAt { get; set; }
/// <summary>
/// 取餐时间。
/// </summary>
public DateTime? PickedUpAt { get; set; }
/// <summary>
/// 完成时间。
/// </summary>
public DateTime? DeliveredAt { get; set; }
/// <summary>
/// 异常原因。
/// </summary>
public string? FailureReason { get; set; }
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.Deliveries.Enums;
/// <summary>
/// 配送事件类型。
/// </summary>
public enum DeliveryEventType
{
/// <summary>
/// 状态更新。
/// </summary>
Updated = 0,
/// <summary>
/// 渠道回调。
/// </summary>
Callback = 1,
/// <summary>
/// 加价或异常通知。
/// </summary>
Exception = 2
}

View File

@@ -0,0 +1,14 @@
namespace TakeoutSaaS.Domain.Deliveries.Enums;
/// <summary>
/// 配送服务商类型。
/// </summary>
public enum DeliveryProvider
{
InHouse = 0,
Dada = 1,
FlashEx = 2,
Meituan = 3,
Eleme = 4,
Shunfeng = 5
}

View File

@@ -0,0 +1,15 @@
namespace TakeoutSaaS.Domain.Deliveries.Enums;
/// <summary>
/// 配送状态。
/// </summary>
public enum DeliveryStatus
{
Pending = 0,
Accepted = 1,
PickingUp = 2,
Delivering = 3,
Completed = 4,
Cancelled = 5,
Failed = 6
}

View File

@@ -0,0 +1,45 @@
using TakeoutSaaS.Domain.Distribution.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Distribution.Entities;
/// <summary>
/// 分销订单记录。
/// </summary>
public sealed class AffiliateOrder : MultiTenantEntityBase
{
/// <summary>
/// 推广人标识。
/// </summary>
public Guid AffiliatePartnerId { get; set; }
/// <summary>
/// 关联订单。
/// </summary>
public Guid OrderId { get; set; }
/// <summary>
/// 用户 ID。
/// </summary>
public Guid BuyerUserId { get; set; }
/// <summary>
/// 订单金额。
/// </summary>
public decimal OrderAmount { get; set; }
/// <summary>
/// 预计佣金。
/// </summary>
public decimal EstimatedCommission { get; set; }
/// <summary>
/// 当前状态。
/// </summary>
public AffiliateOrderStatus Status { get; set; } = AffiliateOrderStatus.Pending;
/// <summary>
/// 结算完成时间。
/// </summary>
public DateTime? SettledAt { get; set; }
}

View File

@@ -0,0 +1,45 @@
using TakeoutSaaS.Domain.Distribution.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Distribution.Entities;
/// <summary>
/// 分销/推广合作伙伴。
/// </summary>
public sealed class AffiliatePartner : MultiTenantEntityBase
{
/// <summary>
/// 用户 ID如绑定平台账号
/// </summary>
public Guid? UserId { get; set; }
/// <summary>
/// 昵称或渠道名称。
/// </summary>
public string DisplayName { get; set; } = string.Empty;
/// <summary>
/// 联系电话。
/// </summary>
public string? Phone { get; set; }
/// <summary>
/// 渠道类型。
/// </summary>
public AffiliateChannelType ChannelType { get; set; } = AffiliateChannelType.Personal;
/// <summary>
/// 分成比例0-1
/// </summary>
public decimal CommissionRate { get; set; }
/// <summary>
/// 当前状态。
/// </summary>
public AffiliateStatus Status { get; set; } = AffiliateStatus.Pending;
/// <summary>
/// 审核备注。
/// </summary>
public string? Remarks { get; set; }
}

View File

@@ -0,0 +1,40 @@
using TakeoutSaaS.Domain.Distribution.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Distribution.Entities;
/// <summary>
/// 佣金结算记录。
/// </summary>
public sealed class AffiliatePayout : MultiTenantEntityBase
{
/// <summary>
/// 合作伙伴标识。
/// </summary>
public Guid AffiliatePartnerId { get; set; }
/// <summary>
/// 结算周期描述。
/// </summary>
public string Period { get; set; } = string.Empty;
/// <summary>
/// 结算金额。
/// </summary>
public decimal Amount { get; set; }
/// <summary>
/// 状态。
/// </summary>
public PayoutStatus Status { get; set; } = PayoutStatus.Pending;
/// <summary>
/// 打款时间。
/// </summary>
public DateTime? PaidAt { get; set; }
/// <summary>
/// 备注。
/// </summary>
public string? Remarks { get; set; }
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Distribution.Enums;
/// <summary>
/// 推广渠道类型。
/// </summary>
public enum AffiliateChannelType
{
/// <summary>
/// 个人。
/// </summary>
Personal = 0,
/// <summary>
/// 自媒体。
/// </summary>
Media = 1,
/// <summary>
/// 门店地推。
/// </summary>
Offline = 2,
/// <summary>
/// 第三方联盟。
/// </summary>
Alliance = 3
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Distribution.Enums;
/// <summary>
/// 分销订单状态。
/// </summary>
public enum AffiliateOrderStatus
{
/// <summary>
/// 待成交通知。
/// </summary>
Pending = 0,
/// <summary>
/// 已完成待结算。
/// </summary>
AwaitingPayout = 1,
/// <summary>
/// 已结算。
/// </summary>
Settled = 2,
/// <summary>
/// 因退款失效。
/// </summary>
Invalidated = 3
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Distribution.Enums;
/// <summary>
/// 合作伙伴状态。
/// </summary>
public enum AffiliateStatus
{
/// <summary>
/// 待审核。
/// </summary>
Pending = 0,
/// <summary>
/// 已激活。
/// </summary>
Active = 1,
/// <summary>
/// 已冻结。
/// </summary>
Suspended = 2,
/// <summary>
/// 已退出。
/// </summary>
Closed = 3
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.Distribution.Enums;
/// <summary>
/// 佣金结算状态。
/// </summary>
public enum PayoutStatus
{
/// <summary>
/// 待打款。
/// </summary>
Pending = 0,
/// <summary>
/// 已打款。
/// </summary>
Paid = 1,
/// <summary>
/// 已驳回。
/// </summary>
Rejected = 2
}

View File

@@ -0,0 +1,45 @@
using TakeoutSaaS.Domain.Engagement.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Engagement.Entities;
/// <summary>
/// 签到活动配置。
/// </summary>
public sealed class CheckInCampaign : MultiTenantEntityBase
{
/// <summary>
/// 活动名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 活动描述。
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 开始日期。
/// </summary>
public DateTime StartDate { get; set; }
/// <summary>
/// 结束日期。
/// </summary>
public DateTime EndDate { get; set; }
/// <summary>
/// 支持补签次数。
/// </summary>
public int AllowMakeupCount { get; set; }
/// <summary>
/// 连签奖励 JSON。
/// </summary>
public string RewardsJson { get; set; } = string.Empty;
/// <summary>
/// 状态。
/// </summary>
public CheckInCampaignStatus Status { get; set; } = CheckInCampaignStatus.Draft;
}

View File

@@ -0,0 +1,34 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Engagement.Entities;
/// <summary>
/// 用户签到记录。
/// </summary>
public sealed class CheckInRecord : MultiTenantEntityBase
{
/// <summary>
/// 活动标识。
/// </summary>
public Guid CheckInCampaignId { get; set; }
/// <summary>
/// 用户标识。
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// 签到日期(本地)。
/// </summary>
public DateTime CheckInDate { get; set; }
/// <summary>
/// 是否补签。
/// </summary>
public bool IsMakeup { get; set; }
/// <summary>
/// 获得奖励 JSON。
/// </summary>
public string RewardJson { get; set; } = string.Empty;
}

View File

@@ -0,0 +1,34 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Engagement.Entities;
/// <summary>
/// 社区评论。
/// </summary>
public sealed class CommunityComment : MultiTenantEntityBase
{
/// <summary>
/// 动态标识。
/// </summary>
public Guid PostId { get; set; }
/// <summary>
/// 评论人。
/// </summary>
public Guid AuthorUserId { get; set; }
/// <summary>
/// 评论内容。
/// </summary>
public string Content { get; set; } = string.Empty;
/// <summary>
/// 父级评论 ID。
/// </summary>
public Guid? ParentId { get; set; }
/// <summary>
/// 状态。
/// </summary>
public bool IsDeleted { get; set; }
}

View File

@@ -0,0 +1,45 @@
using TakeoutSaaS.Domain.Engagement.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Engagement.Entities;
/// <summary>
/// 社区动态。
/// </summary>
public sealed class CommunityPost : MultiTenantEntityBase
{
/// <summary>
/// 作者用户 ID。
/// </summary>
public Guid AuthorUserId { get; set; }
/// <summary>
/// 标题。
/// </summary>
public string? Title { get; set; }
/// <summary>
/// 内容。
/// </summary>
public string Content { get; set; } = string.Empty;
/// <summary>
/// 媒体资源 JSON。
/// </summary>
public string? MediaJson { get; set; }
/// <summary>
/// 状态。
/// </summary>
public PostStatus Status { get; set; } = PostStatus.PendingReview;
/// <summary>
/// 点赞数。
/// </summary>
public int LikeCount { get; set; }
/// <summary>
/// 评论数。
/// </summary>
public int CommentCount { get; set; }
}

View File

@@ -0,0 +1,30 @@
using TakeoutSaaS.Domain.Engagement.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Engagement.Entities;
/// <summary>
/// 社区互动反馈。
/// </summary>
public sealed class CommunityReaction : MultiTenantEntityBase
{
/// <summary>
/// 动态 ID。
/// </summary>
public Guid PostId { get; set; }
/// <summary>
/// 用户 ID。
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// 反应类型。
/// </summary>
public ReactionType ReactionType { get; set; } = ReactionType.Like;
/// <summary>
/// 时间戳。
/// </summary>
public DateTime ReactedAt { get; set; } = DateTime.UtcNow;
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Engagement.Enums;
/// <summary>
/// 签到活动状态。
/// </summary>
public enum CheckInCampaignStatus
{
/// <summary>
/// 草稿。
/// </summary>
Draft = 0,
/// <summary>
/// 进行中。
/// </summary>
Active = 1,
/// <summary>
/// 已结束。
/// </summary>
Completed = 2,
/// <summary>
/// 已停用。
/// </summary>
Disabled = 3
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Engagement.Enums;
/// <summary>
/// 社区动态状态。
/// </summary>
public enum PostStatus
{
/// <summary>
/// 待审核。
/// </summary>
PendingReview = 0,
/// <summary>
/// 已发布。
/// </summary>
Published = 1,
/// <summary>
/// 已屏蔽。
/// </summary>
Blocked = 2,
/// <summary>
/// 已删除。
/// </summary>
Deleted = 3
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.Engagement.Enums;
/// <summary>
/// 互动类型。
/// </summary>
public enum ReactionType
{
/// <summary>
/// 点赞。
/// </summary>
Like = 0,
/// <summary>
/// 收藏。
/// </summary>
Favorite = 1,
/// <summary>
/// 点踩。
/// </summary>
Dislike = 2
}

View File

@@ -0,0 +1,70 @@
using TakeoutSaaS.Domain.GroupBuying.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.GroupBuying.Entities;
/// <summary>
/// 拼单活动。
/// </summary>
public sealed class GroupOrder : MultiTenantEntityBase
{
/// <summary>
/// 门店标识。
/// </summary>
public Guid StoreId { get; set; }
/// <summary>
/// 关联商品或套餐。
/// </summary>
public Guid ProductId { get; set; }
/// <summary>
/// 拼单编号。
/// </summary>
public string GroupOrderNo { get; set; } = string.Empty;
/// <summary>
/// 团长用户 ID。
/// </summary>
public Guid LeaderUserId { get; set; }
/// <summary>
/// 成团需要的人数。
/// </summary>
public int TargetCount { get; set; }
/// <summary>
/// 当前已参与人数。
/// </summary>
public int CurrentCount { get; set; }
/// <summary>
/// 拼团价格。
/// </summary>
public decimal GroupPrice { get; set; }
/// <summary>
/// 开始时间。
/// </summary>
public DateTime StartAt { get; set; }
/// <summary>
/// 结束时间。
/// </summary>
public DateTime EndAt { get; set; }
/// <summary>
/// 拼团状态。
/// </summary>
public GroupOrderStatus Status { get; set; } = GroupOrderStatus.Open;
/// <summary>
/// 成团时间。
/// </summary>
public DateTime? SucceededAt { get; set; }
/// <summary>
/// 取消时间。
/// </summary>
public DateTime? CancelledAt { get; set; }
}

View File

@@ -0,0 +1,35 @@
using TakeoutSaaS.Domain.GroupBuying.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.GroupBuying.Entities;
/// <summary>
/// 拼单参与者。
/// </summary>
public sealed class GroupParticipant : MultiTenantEntityBase
{
/// <summary>
/// 拼单活动标识。
/// </summary>
public Guid GroupOrderId { get; set; }
/// <summary>
/// 对应订单标识。
/// </summary>
public Guid OrderId { get; set; }
/// <summary>
/// 用户标识。
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// 参与状态。
/// </summary>
public GroupParticipantStatus Status { get; set; } = GroupParticipantStatus.Joined;
/// <summary>
/// 参与时间。
/// </summary>
public DateTime JoinedAt { get; set; } = DateTime.UtcNow;
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.GroupBuying.Enums;
/// <summary>
/// 拼单状态。
/// </summary>
public enum GroupOrderStatus
{
/// <summary>
/// 开放中。
/// </summary>
Open = 0,
/// <summary>
/// 已成团。
/// </summary>
Succeeded = 1,
/// <summary>
/// 已取消。
/// </summary>
Cancelled = 2,
/// <summary>
/// 超时失败。
/// </summary>
Failed = 3
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.GroupBuying.Enums;
/// <summary>
/// 拼单参与者状态。
/// </summary>
public enum GroupParticipantStatus
{
/// <summary>
/// 已参团。
/// </summary>
Joined = 0,
/// <summary>
/// 因退款或取消退出。
/// </summary>
Exited = 1,
/// <summary>
/// 团失败待退款。
/// </summary>
PendingRefund = 2
}

View File

@@ -0,0 +1,40 @@
using TakeoutSaaS.Domain.Inventory.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Inventory.Entities;
/// <summary>
/// 库存调整记录。
/// </summary>
public sealed class InventoryAdjustment : MultiTenantEntityBase
{
/// <summary>
/// 对应的库存记录标识。
/// </summary>
public Guid InventoryItemId { get; set; }
/// <summary>
/// 调整类型。
/// </summary>
public InventoryAdjustmentType AdjustmentType { get; set; } = InventoryAdjustmentType.Manual;
/// <summary>
/// 调整数量,正数增加,负数减少。
/// </summary>
public int Quantity { get; set; }
/// <summary>
/// 原因说明。
/// </summary>
public string? Reason { get; set; }
/// <summary>
/// 操作人标识。
/// </summary>
public Guid? OperatorId { get; set; }
/// <summary>
/// 发生时间。
/// </summary>
public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
}

View File

@@ -0,0 +1,44 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Inventory.Entities;
/// <summary>
/// SKU 批次信息。
/// </summary>
public sealed class InventoryBatch : MultiTenantEntityBase
{
/// <summary>
/// 门店标识。
/// </summary>
public Guid StoreId { get; set; }
/// <summary>
/// SKU 标识。
/// </summary>
public Guid ProductSkuId { get; set; }
/// <summary>
/// 批次编号。
/// </summary>
public string BatchNumber { get; set; } = string.Empty;
/// <summary>
/// 生产日期。
/// </summary>
public DateTime? ProductionDate { get; set; }
/// <summary>
/// 过期日期。
/// </summary>
public DateTime? ExpireDate { get; set; }
/// <summary>
/// 入库数量。
/// </summary>
public int Quantity { get; set; }
/// <summary>
/// 剩余数量。
/// </summary>
public int RemainingQuantity { get; set; }
}

View File

@@ -0,0 +1,49 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Inventory.Entities;
/// <summary>
/// SKU 在门店的库存信息。
/// </summary>
public sealed class InventoryItem : MultiTenantEntityBase
{
/// <summary>
/// 门店标识。
/// </summary>
public Guid StoreId { get; set; }
/// <summary>
/// SKU 标识。
/// </summary>
public Guid ProductSkuId { get; set; }
/// <summary>
/// 批次编号,可为空表示混批。
/// </summary>
public string? BatchNumber { get; set; }
/// <summary>
/// 可用库存。
/// </summary>
public int QuantityOnHand { get; set; }
/// <summary>
/// 已锁定库存(订单占用)。
/// </summary>
public int QuantityReserved { get; set; }
/// <summary>
/// 安全库存阈值。
/// </summary>
public int? SafetyStock { get; set; }
/// <summary>
/// 储位或仓位信息。
/// </summary>
public string? Location { get; set; }
/// <summary>
/// 过期日期。
/// </summary>
public DateTime? ExpireDate { get; set; }
}

View File

@@ -0,0 +1,32 @@
namespace TakeoutSaaS.Domain.Inventory.Enums;
/// <summary>
/// 库存调整类型。
/// </summary>
public enum InventoryAdjustmentType
{
/// <summary>
/// 手动盘点调整。
/// </summary>
Manual = 0,
/// <summary>
/// 采购入库。
/// </summary>
Purchase = 1,
/// <summary>
/// 退货回库。
/// </summary>
Return = 2,
/// <summary>
/// 报损。
/// </summary>
Damage = 3,
/// <summary>
/// 过期销毁。
/// </summary>
Expiration = 4
}

View File

@@ -0,0 +1,34 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Membership.Entities;
/// <summary>
/// 成长值变动日志。
/// </summary>
public sealed class MemberGrowthLog : MultiTenantEntityBase
{
/// <summary>
/// 会员标识。
/// </summary>
public Guid MemberId { get; set; }
/// <summary>
/// 变动数量。
/// </summary>
public int ChangeValue { get; set; }
/// <summary>
/// 当前成长值。
/// </summary>
public int CurrentValue { get; set; }
/// <summary>
/// 备注。
/// </summary>
public string? Notes { get; set; }
/// <summary>
/// 发生时间。
/// </summary>
public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
}

View File

@@ -0,0 +1,45 @@
using TakeoutSaaS.Domain.Membership.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Membership.Entities;
/// <summary>
/// 积分变动流水。
/// </summary>
public sealed class MemberPointLedger : MultiTenantEntityBase
{
/// <summary>
/// 会员标识。
/// </summary>
public Guid MemberId { get; set; }
/// <summary>
/// 变动数量,可为负值。
/// </summary>
public int ChangeAmount { get; set; }
/// <summary>
/// 变动后余额。
/// </summary>
public int BalanceAfterChange { get; set; }
/// <summary>
/// 变动原因。
/// </summary>
public PointChangeReason Reason { get; set; } = PointChangeReason.Purchase;
/// <summary>
/// 来源 ID订单、活动等
/// </summary>
public Guid? SourceId { get; set; }
/// <summary>
/// 发生时间。
/// </summary>
public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// 过期时间(如适用)。
/// </summary>
public DateTime? ExpireAt { get; set; }
}

View File

@@ -0,0 +1,60 @@
using TakeoutSaaS.Domain.Membership.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Membership.Entities;
/// <summary>
/// 会员档案。
/// </summary>
public sealed class MemberProfile : MultiTenantEntityBase
{
/// <summary>
/// 用户标识。
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// 手机号。
/// </summary>
public string Mobile { get; set; } = string.Empty;
/// <summary>
/// 昵称。
/// </summary>
public string? Nickname { get; set; }
/// <summary>
/// 头像。
/// </summary>
public string? AvatarUrl { get; set; }
/// <summary>
/// 当前会员等级 ID。
/// </summary>
public Guid? MemberTierId { get; set; }
/// <summary>
/// 会员状态。
/// </summary>
public MemberStatus Status { get; set; } = MemberStatus.Active;
/// <summary>
/// 会员积分余额。
/// </summary>
public int PointsBalance { get; set; }
/// <summary>
/// 成长值/经验值。
/// </summary>
public int GrowthValue { get; set; }
/// <summary>
/// 生日。
/// </summary>
public DateTime? BirthDate { get; set; }
/// <summary>
/// 注册时间。
/// </summary>
public DateTime JoinedAt { get; set; } = DateTime.UtcNow;
}

View File

@@ -0,0 +1,29 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Membership.Entities;
/// <summary>
/// 会员等级定义。
/// </summary>
public sealed class MemberTier : MultiTenantEntityBase
{
/// <summary>
/// 等级名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 所需成长值。
/// </summary>
public int RequiredGrowth { get; set; }
/// <summary>
/// 等级权益JSON
/// </summary>
public string BenefitsJson { get; set; } = string.Empty;
/// <summary>
/// 排序值。
/// </summary>
public int SortOrder { get; set; } = 100;
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.Membership.Enums;
/// <summary>
/// 会员状态。
/// </summary>
public enum MemberStatus
{
/// <summary>
/// 正常。
/// </summary>
Active = 0,
/// <summary>
/// 已冻结。
/// </summary>
Frozen = 1,
/// <summary>
/// 已注销。
/// </summary>
Cancelled = 2
}

View File

@@ -0,0 +1,32 @@
namespace TakeoutSaaS.Domain.Membership.Enums;
/// <summary>
/// 积分变动原因。
/// </summary>
public enum PointChangeReason
{
/// <summary>
/// 正常消费获得。
/// </summary>
Purchase = 0,
/// <summary>
/// 活动奖励。
/// </summary>
Promotion = 1,
/// <summary>
/// 签到或任务。
/// </summary>
Task = 2,
/// <summary>
/// 管理员调整。
/// </summary>
Manual = 3,
/// <summary>
/// 抵扣消费。
/// </summary>
Redeem = 4
}

View File

@@ -0,0 +1,120 @@
using TakeoutSaaS.Domain.Merchants.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Merchants.Entities;
/// <summary>
/// 商户主体信息,承载入驻和资质审核结果。
/// </summary>
public sealed class Merchant : MultiTenantEntityBase
{
/// <summary>
/// 品牌名称(对外展示)。
/// </summary>
public string BrandName { get; set; } = string.Empty;
/// <summary>
/// 品牌简称或别名。
/// </summary>
public string? BrandAlias { get; set; }
/// <summary>
/// 品牌 Logo。
/// </summary>
public string? LogoUrl { get; set; }
/// <summary>
/// 品牌所属品类,如火锅、咖啡等。
/// </summary>
public string? Category { get; set; }
/// <summary>
/// 营业执照号。
/// </summary>
public string? BusinessLicenseNumber { get; set; }
/// <summary>
/// 营业执照扫描件地址。
/// </summary>
public string? BusinessLicenseImageUrl { get; set; }
/// <summary>
/// 税号/统一社会信用代码。
/// </summary>
public string? TaxNumber { get; set; }
/// <summary>
/// 法人或负责人姓名。
/// </summary>
public string? LegalPerson { get; set; }
/// <summary>
/// 联系电话。
/// </summary>
public string ContactPhone { get; set; } = string.Empty;
/// <summary>
/// 联系邮箱。
/// </summary>
public string? ContactEmail { get; set; }
/// <summary>
/// 客服电话。
/// </summary>
public string? ServicePhone { get; set; }
/// <summary>
/// 客服邮箱。
/// </summary>
public string? SupportEmail { get; set; }
/// <summary>
/// 所在省份。
/// </summary>
public string? Province { get; set; }
/// <summary>
/// 所在城市。
/// </summary>
public string? City { get; set; }
/// <summary>
/// 所在区县。
/// </summary>
public string? District { get; set; }
/// <summary>
/// 详细地址。
/// </summary>
public string? Address { get; set; }
/// <summary>
/// 经度信息。
/// </summary>
public double? Longitude { get; set; }
/// <summary>
/// 纬度信息。
/// </summary>
public double? Latitude { get; set; }
/// <summary>
/// 入驻状态。
/// </summary>
public MerchantStatus Status { get; set; } = MerchantStatus.Pending;
/// <summary>
/// 审核备注或驳回原因。
/// </summary>
public string? ReviewRemarks { get; set; }
/// <summary>
/// 入驻时间。
/// </summary>
public DateTime? JoinedAt { get; set; }
/// <summary>
/// 最近一次审核时间。
/// </summary>
public DateTime? LastReviewedAt { get; set; }
}

View File

@@ -0,0 +1,55 @@
using TakeoutSaaS.Domain.Merchants.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Merchants.Entities;
/// <summary>
/// 商户合同记录。
/// </summary>
public sealed class MerchantContract : MultiTenantEntityBase
{
/// <summary>
/// 所属商户标识。
/// </summary>
public Guid MerchantId { get; set; }
/// <summary>
/// 合同编号。
/// </summary>
public string ContractNumber { get; set; } = string.Empty;
/// <summary>
/// 合同状态。
/// </summary>
public ContractStatus Status { get; set; } = ContractStatus.Draft;
/// <summary>
/// 合同开始时间。
/// </summary>
public DateTime StartDate { get; set; }
/// <summary>
/// 合同结束时间。
/// </summary>
public DateTime EndDate { get; set; }
/// <summary>
/// 合同文件存储地址。
/// </summary>
public string FileUrl { get; set; } = string.Empty;
/// <summary>
/// 签署时间。
/// </summary>
public DateTime? SignedAt { get; set; }
/// <summary>
/// 终止时间。
/// </summary>
public DateTime? TerminatedAt { get; set; }
/// <summary>
/// 终止原因。
/// </summary>
public string? TerminationReason { get; set; }
}

View File

@@ -0,0 +1,50 @@
using TakeoutSaaS.Domain.Merchants.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Merchants.Entities;
/// <summary>
/// 商户提交的资质或证照材料。
/// </summary>
public sealed class MerchantDocument : MultiTenantEntityBase
{
/// <summary>
/// 所属商户标识。
/// </summary>
public Guid MerchantId { get; set; }
/// <summary>
/// 证照类型。
/// </summary>
public MerchantDocumentType DocumentType { get; set; } = MerchantDocumentType.BusinessLicense;
/// <summary>
/// 审核状态。
/// </summary>
public MerchantDocumentStatus Status { get; set; } = MerchantDocumentStatus.Pending;
/// <summary>
/// 证照文件链接。
/// </summary>
public string FileUrl { get; set; } = string.Empty;
/// <summary>
/// 证照编号。
/// </summary>
public string? DocumentNumber { get; set; }
/// <summary>
/// 签发日期。
/// </summary>
public DateTime? IssuedAt { get; set; }
/// <summary>
/// 到期日期。
/// </summary>
public DateTime? ExpiresAt { get; set; }
/// <summary>
/// 审核备注或驳回原因。
/// </summary>
public string? Remarks { get; set; }
}

View File

@@ -0,0 +1,55 @@
using TakeoutSaaS.Domain.Merchants.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Merchants.Entities;
/// <summary>
/// 商户员工账号,支持门店维度分配。
/// </summary>
public sealed class MerchantStaff : MultiTenantEntityBase
{
/// <summary>
/// 所属商户标识。
/// </summary>
public Guid MerchantId { get; set; }
/// <summary>
/// 可选的关联门店 ID。
/// </summary>
public Guid? StoreId { get; set; }
/// <summary>
/// 员工姓名。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 手机号。
/// </summary>
public string Phone { get; set; } = string.Empty;
/// <summary>
/// 邮箱地址。
/// </summary>
public string? Email { get; set; }
/// <summary>
/// 登录账号 ID指向统一身份体系
/// </summary>
public Guid? IdentityUserId { get; set; }
/// <summary>
/// 员工角色类型。
/// </summary>
public StaffRoleType RoleType { get; set; } = StaffRoleType.FrontDesk;
/// <summary>
/// 员工状态。
/// </summary>
public StaffStatus Status { get; set; } = StaffStatus.Active;
/// <summary>
/// 自定义权限JSON
/// </summary>
public string? PermissionsJson { get; set; }
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Merchants.Enums;
/// <summary>
/// 商户合同状态。
/// </summary>
public enum ContractStatus
{
/// <summary>
/// 草拟中。
/// </summary>
Draft = 0,
/// <summary>
/// 已生效。
/// </summary>
Active = 1,
/// <summary>
/// 已到期。
/// </summary>
Expired = 2,
/// <summary>
/// 已解除。
/// </summary>
Terminated = 3
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Merchants.Enums;
/// <summary>
/// 证照审核状态。
/// </summary>
public enum MerchantDocumentStatus
{
/// <summary>
/// 等待审核。
/// </summary>
Pending = 0,
/// <summary>
/// 审核通过。
/// </summary>
Approved = 1,
/// <summary>
/// 审核驳回。
/// </summary>
Rejected = 2,
/// <summary>
/// 已过期待更新。
/// </summary>
Expired = 3
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Merchants.Enums;
/// <summary>
/// 商户证照类型。
/// </summary>
public enum MerchantDocumentType
{
/// <summary>
/// 营业执照。
/// </summary>
BusinessLicense = 0,
/// <summary>
/// 餐饮服务许可证。
/// </summary>
CateringPermit = 1,
/// <summary>
/// 税务登记证。
/// </summary>
TaxCertificate = 2,
/// <summary>
/// 其他补充资质。
/// </summary>
Other = 99
}

View File

@@ -0,0 +1,12 @@
namespace TakeoutSaaS.Domain.Merchants.Enums;
/// <summary>
/// 商户入驻状态。
/// </summary>
public enum MerchantStatus
{
Pending = 0,
Approved = 1,
Rejected = 2,
Frozen = 3
}

View File

@@ -0,0 +1,32 @@
namespace TakeoutSaaS.Domain.Merchants.Enums;
/// <summary>
/// 商户员工角色。
/// </summary>
public enum StaffRoleType
{
/// <summary>
/// 管理员。
/// </summary>
Admin = 0,
/// <summary>
/// 前台收银。
/// </summary>
FrontDesk = 1,
/// <summary>
/// 后厨制作。
/// </summary>
Kitchen = 2,
/// <summary>
/// 配送骑手。
/// </summary>
Courier = 3,
/// <summary>
/// 运营人员。
/// </summary>
Operator = 4
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.Merchants.Enums;
/// <summary>
/// 员工账号状态。
/// </summary>
public enum StaffStatus
{
/// <summary>
/// 正常在职。
/// </summary>
Active = 0,
/// <summary>
/// 停用。
/// </summary>
Disabled = 1,
/// <summary>
/// 已离职。
/// </summary>
Resigned = 2
}

View File

@@ -0,0 +1,39 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Navigation.Entities;
/// <summary>
/// 地图 POI 信息,用于门店定位和推荐。
/// </summary>
public sealed class MapLocation : MultiTenantEntityBase
{
/// <summary>
/// 关联门店 ID可空表示独立 POI。
/// </summary>
public Guid? StoreId { get; set; }
/// <summary>
/// 名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 地址。
/// </summary>
public string Address { get; set; } = string.Empty;
/// <summary>
/// 经度。
/// </summary>
public double Longitude { get; set; }
/// <summary>
/// 纬度。
/// </summary>
public double Latitude { get; set; }
/// <summary>
/// 打车/导航落点描述。
/// </summary>
public string? Landmark { get; set; }
}

View File

@@ -0,0 +1,35 @@
using TakeoutSaaS.Domain.Navigation.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Navigation.Entities;
/// <summary>
/// 用户发起的导航请求日志。
/// </summary>
public sealed class NavigationRequest : MultiTenantEntityBase
{
/// <summary>
/// 用户 ID。
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// 门店 ID。
/// </summary>
public Guid StoreId { get; set; }
/// <summary>
/// 来源通道小程序、H5 等)。
/// </summary>
public NavigationChannel Channel { get; set; } = NavigationChannel.MiniProgram;
/// <summary>
/// 跳转的地图应用。
/// </summary>
public NavigationTargetApp TargetApp { get; set; } = NavigationTargetApp.WechatMap;
/// <summary>
/// 请求时间。
/// </summary>
public DateTime RequestedAt { get; set; } = DateTime.UtcNow;
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.Navigation.Enums;
/// <summary>
/// 导航请求来源渠道。
/// </summary>
public enum NavigationChannel
{
/// <summary>
/// 小程序。
/// </summary>
MiniProgram = 0,
/// <summary>
/// H5/公众号。
/// </summary>
Web = 1,
/// <summary>
/// App。
/// </summary>
MobileApp = 2
}

View File

@@ -0,0 +1,32 @@
namespace TakeoutSaaS.Domain.Navigation.Enums;
/// <summary>
/// 导航目标应用。
/// </summary>
public enum NavigationTargetApp
{
/// <summary>
/// 微信地图。
/// </summary>
WechatMap = 0,
/// <summary>
/// 腾讯地图。
/// </summary>
Tencent = 1,
/// <summary>
/// 高德。
/// </summary>
Amap = 2,
/// <summary>
/// 百度地图。
/// </summary>
Baidu = 3,
/// <summary>
/// Apple Map。
/// </summary>
Apple = 4
}

View File

@@ -0,0 +1,55 @@
using TakeoutSaaS.Domain.Ordering.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Ordering.Entities;
/// <summary>
/// 购物车条目。
/// </summary>
public sealed class CartItem : MultiTenantEntityBase
{
/// <summary>
/// 所属购物车标识。
/// </summary>
public Guid ShoppingCartId { get; set; }
/// <summary>
/// 商品或 SKU 标识。
/// </summary>
public Guid ProductId { get; set; }
/// <summary>
/// SKU 标识。
/// </summary>
public Guid? ProductSkuId { get; set; }
/// <summary>
/// 商品名称快照。
/// </summary>
public string ProductName { get; set; } = string.Empty;
/// <summary>
/// 单价快照。
/// </summary>
public decimal UnitPrice { get; set; }
/// <summary>
/// 数量。
/// </summary>
public int Quantity { get; set; }
/// <summary>
/// 自定义备注(口味要求)。
/// </summary>
public string? Remark { get; set; }
/// <summary>
/// 状态。
/// </summary>
public CartItemStatus Status { get; set; } = CartItemStatus.Normal;
/// <summary>
/// 扩展 JSON规格、加料选项等
/// </summary>
public string? AttributesJson { get; set; }
}

View File

@@ -0,0 +1,29 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Ordering.Entities;
/// <summary>
/// 购物车条目的加料/附加项。
/// </summary>
public sealed class CartItemAddon : MultiTenantEntityBase
{
/// <summary>
/// 所属购物车条目。
/// </summary>
public Guid CartItemId { get; set; }
/// <summary>
/// 选项名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 附加价格。
/// </summary>
public decimal ExtraPrice { get; set; }
/// <summary>
/// 选项 ID可对应 ProductAddonOption
/// </summary>
public Guid? OptionId { get; set; }
}

View File

@@ -0,0 +1,40 @@
using TakeoutSaaS.Domain.Ordering.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Ordering.Entities;
/// <summary>
/// 结账会话,记录校验上下文。
/// </summary>
public sealed class CheckoutSession : MultiTenantEntityBase
{
/// <summary>
/// 用户标识。
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// 门店标识。
/// </summary>
public Guid StoreId { get; set; }
/// <summary>
/// 会话 Token。
/// </summary>
public string SessionToken { get; set; } = string.Empty;
/// <summary>
/// 会话状态。
/// </summary>
public CheckoutSessionStatus Status { get; set; } = CheckoutSessionStatus.Pending;
/// <summary>
/// 校验结果明细 JSON。
/// </summary>
public string ValidationResultJson { get; set; } = string.Empty;
/// <summary>
/// 过期时间UTC
/// </summary>
public DateTime ExpiresAt { get; set; }
}

View File

@@ -0,0 +1,40 @@
using TakeoutSaaS.Domain.Ordering.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Ordering.Entities;
/// <summary>
/// 用户购物车,按租户/门店隔离。
/// </summary>
public sealed class ShoppingCart : MultiTenantEntityBase
{
/// <summary>
/// 用户标识。
/// </summary>
public Guid UserId { get; set; }
/// <summary>
/// 门店标识。
/// </summary>
public Guid StoreId { get; set; }
/// <summary>
/// 购物车状态,包含正常/锁定。
/// </summary>
public ShoppingCartStatus Status { get; set; } = ShoppingCartStatus.Active;
/// <summary>
/// 桌码或场景标识(扫码点餐)。
/// </summary>
public string? TableContext { get; set; }
/// <summary>
/// 履约方式(堂食/自提/配送)缓存。
/// </summary>
public string? DeliveryPreference { get; set; }
/// <summary>
/// 最近一次修改时间UTC
/// </summary>
public DateTime LastModifiedAt { get; set; } = DateTime.UtcNow;
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.Ordering.Enums;
/// <summary>
/// 购物车条目状态。
/// </summary>
public enum CartItemStatus
{
/// <summary>
/// 正常可结算。
/// </summary>
Normal = 0,
/// <summary>
/// 不可售(售罄或下架)。
/// </summary>
Unavailable = 1,
/// <summary>
/// 已被删除。
/// </summary>
Removed = 2
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Ordering.Enums;
/// <summary>
/// 结账会话状态。
/// </summary>
public enum CheckoutSessionStatus
{
/// <summary>
/// 等待用户提交或支付。
/// </summary>
Pending = 0,
/// <summary>
/// 校验失败。
/// </summary>
Failed = 1,
/// <summary>
/// 已用于创建订单。
/// </summary>
Completed = 2,
/// <summary>
/// 超时作废。
/// </summary>
Expired = 3
}

View File

@@ -0,0 +1,22 @@
namespace TakeoutSaaS.Domain.Ordering.Enums;
/// <summary>
/// 购物车状态。
/// </summary>
public enum ShoppingCartStatus
{
/// <summary>
/// 可正常使用。
/// </summary>
Active = 0,
/// <summary>
/// 已锁定(进行结账中)。
/// </summary>
Locked = 1,
/// <summary>
/// 已清空或失效。
/// </summary>
Cleared = 2
}

View File

@@ -0,0 +1,111 @@
using TakeoutSaaS.Domain.Orders.Enums;
using TakeoutSaaS.Domain.Payments.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Orders.Entities;
/// <summary>
/// 交易订单。
/// </summary>
public sealed class Order : MultiTenantEntityBase
{
/// <summary>
/// 订单号。
/// </summary>
public string OrderNo { get; set; } = string.Empty;
/// <summary>
/// 门店。
/// </summary>
public Guid StoreId { get; set; }
/// <summary>
/// 下单渠道。
/// </summary>
public OrderChannel Channel { get; set; } = OrderChannel.MiniProgram;
/// <summary>
/// 履约类型。
/// </summary>
public DeliveryType DeliveryType { get; set; } = DeliveryType.DineIn;
/// <summary>
/// 当前状态。
/// </summary>
public OrderStatus Status { get; set; } = OrderStatus.PendingPayment;
/// <summary>
/// 支付状态。
/// </summary>
public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Unpaid;
/// <summary>
/// 顾客姓名。
/// </summary>
public string? CustomerName { get; set; }
/// <summary>
/// 顾客手机号。
/// </summary>
public string? CustomerPhone { get; set; }
/// <summary>
/// 就餐桌号。
/// </summary>
public string? TableNo { get; set; }
/// <summary>
/// 排队号(如有)。
/// </summary>
public string? QueueNumber { get; set; }
/// <summary>
/// 预约 ID。
/// </summary>
public Guid? ReservationId { get; set; }
/// <summary>
/// 商品总额。
/// </summary>
public decimal ItemsAmount { get; set; }
/// <summary>
/// 优惠金额。
/// </summary>
public decimal DiscountAmount { get; set; }
/// <summary>
/// 应付金额。
/// </summary>
public decimal PayableAmount { get; set; }
/// <summary>
/// 实付金额。
/// </summary>
public decimal PaidAmount { get; set; }
/// <summary>
/// 支付时间。
/// </summary>
public DateTime? PaidAt { get; set; }
/// <summary>
/// 完成时间。
/// </summary>
public DateTime? FinishedAt { get; set; }
/// <summary>
/// 取消时间。
/// </summary>
public DateTime? CancelledAt { get; set; }
/// <summary>
/// 取消原因。
/// </summary>
public string? CancelReason { get; set; }
/// <summary>
/// 备注。
/// </summary>
public string? Remark { get; set; }
}

View File

@@ -0,0 +1,59 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Orders.Entities;
/// <summary>
/// 订单明细。
/// </summary>
public sealed class OrderItem : MultiTenantEntityBase
{
/// <summary>
/// 订单 ID。
/// </summary>
public Guid OrderId { get; set; }
/// <summary>
/// 商品 ID。
/// </summary>
public Guid ProductId { get; set; }
/// <summary>
/// 商品名称。
/// </summary>
public string ProductName { get; set; } = string.Empty;
/// <summary>
/// SKU/规格描述。
/// </summary>
public string? SkuName { get; set; }
/// <summary>
/// 单位。
/// </summary>
public string? Unit { get; set; }
/// <summary>
/// 数量。
/// </summary>
public int Quantity { get; set; }
/// <summary>
/// 单价。
/// </summary>
public decimal UnitPrice { get; set; }
/// <summary>
/// 折扣金额。
/// </summary>
public decimal DiscountAmount { get; set; }
/// <summary>
/// 小计。
/// </summary>
public decimal SubTotal { get; set; }
/// <summary>
/// 自定义属性 JSON。
/// </summary>
public string? AttributesJson { get; set; }
}

View File

@@ -0,0 +1,35 @@
using TakeoutSaaS.Domain.Orders.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Orders.Entities;
/// <summary>
/// 订单状态流转记录。
/// </summary>
public sealed class OrderStatusHistory : MultiTenantEntityBase
{
/// <summary>
/// 订单标识。
/// </summary>
public Guid OrderId { get; set; }
/// <summary>
/// 变更后的状态。
/// </summary>
public OrderStatus Status { get; set; }
/// <summary>
/// 操作人标识(可为空表示系统)。
/// </summary>
public Guid? OperatorId { get; set; }
/// <summary>
/// 备注信息。
/// </summary>
public string? Notes { get; set; }
/// <summary>
/// 发生时间。
/// </summary>
public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
}

View File

@@ -0,0 +1,50 @@
using TakeoutSaaS.Domain.Orders.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Orders.Entities;
/// <summary>
/// 售后/退款申请。
/// </summary>
public sealed class RefundRequest : MultiTenantEntityBase
{
/// <summary>
/// 关联订单标识。
/// </summary>
public Guid OrderId { get; set; }
/// <summary>
/// 退款单号。
/// </summary>
public string RefundNo { get; set; } = string.Empty;
/// <summary>
/// 申请金额。
/// </summary>
public decimal Amount { get; set; }
/// <summary>
/// 申请原因。
/// </summary>
public string Reason { get; set; } = string.Empty;
/// <summary>
/// 退款状态。
/// </summary>
public RefundStatus Status { get; set; } = RefundStatus.Pending;
/// <summary>
/// 用户提交时间。
/// </summary>
public DateTime RequestedAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// 审核完成时间。
/// </summary>
public DateTime? ProcessedAt { get; set; }
/// <summary>
/// 审核备注。
/// </summary>
public string? ReviewNotes { get; set; }
}

View File

@@ -0,0 +1,11 @@
namespace TakeoutSaaS.Domain.Orders.Enums;
/// <summary>
/// 履约/交付方式。
/// </summary>
public enum DeliveryType
{
DineIn = 0,
Pickup = 1,
Delivery = 2
}

View File

@@ -0,0 +1,14 @@
namespace TakeoutSaaS.Domain.Orders.Enums;
/// <summary>
/// 下单渠道。
/// </summary>
public enum OrderChannel
{
Unknown = 0,
MiniProgram = 1,
ScanToOrder = 2,
StaffConsole = 3,
PhoneReservation = 4,
ThirdPartyDelivery = 5
}

View File

@@ -0,0 +1,14 @@
namespace TakeoutSaaS.Domain.Orders.Enums;
/// <summary>
/// 订单状态。
/// </summary>
public enum OrderStatus
{
PendingPayment = 0,
AwaitingPreparation = 1,
InProgress = 2,
Ready = 3,
Completed = 4,
Cancelled = 5
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Orders.Enums;
/// <summary>
/// 退款申请状态。
/// </summary>
public enum RefundStatus
{
/// <summary>
/// 等待审核。
/// </summary>
Pending = 0,
/// <summary>
/// 审核通过,待原路退款。
/// </summary>
Approved = 1,
/// <summary>
/// 已拒绝。
/// </summary>
Rejected = 2,
/// <summary>
/// 已完成退款。
/// </summary>
Refunded = 3
}

View File

@@ -0,0 +1,55 @@
using TakeoutSaaS.Domain.Payments.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Payments.Entities;
/// <summary>
/// 支付流水。
/// </summary>
public sealed class PaymentRecord : MultiTenantEntityBase
{
/// <summary>
/// 关联订单。
/// </summary>
public Guid OrderId { get; set; }
/// <summary>
/// 支付方式。
/// </summary>
public PaymentMethod Method { get; set; } = PaymentMethod.Unknown;
/// <summary>
/// 支付状态。
/// </summary>
public PaymentStatus Status { get; set; } = PaymentStatus.Unpaid;
/// <summary>
/// 支付金额。
/// </summary>
public decimal Amount { get; set; }
/// <summary>
/// 平台交易号。
/// </summary>
public string? TradeNo { get; set; }
/// <summary>
/// 第三方渠道单号。
/// </summary>
public string? ChannelTransactionId { get; set; }
/// <summary>
/// 支付完成时间。
/// </summary>
public DateTime? PaidAt { get; set; }
/// <summary>
/// 错误/备注。
/// </summary>
public string? Remark { get; set; }
/// <summary>
/// 原始回调内容。
/// </summary>
public string? Payload { get; set; }
}

View File

@@ -0,0 +1,50 @@
using TakeoutSaaS.Domain.Payments.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Payments.Entities;
/// <summary>
/// 支付渠道退款流水。
/// </summary>
public sealed class PaymentRefundRecord : MultiTenantEntityBase
{
/// <summary>
/// 原支付记录标识。
/// </summary>
public Guid PaymentRecordId { get; set; }
/// <summary>
/// 关联订单标识。
/// </summary>
public Guid OrderId { get; set; }
/// <summary>
/// 退款金额。
/// </summary>
public decimal Amount { get; set; }
/// <summary>
/// 渠道退款流水号。
/// </summary>
public string? ChannelRefundId { get; set; }
/// <summary>
/// 退款状态。
/// </summary>
public PaymentRefundStatus Status { get; set; } = PaymentRefundStatus.Pending;
/// <summary>
/// 退款请求时间。
/// </summary>
public DateTime RequestedAt { get; set; } = DateTime.UtcNow;
/// <summary>
/// 完成时间。
/// </summary>
public DateTime? CompletedAt { get; set; }
/// <summary>
/// 渠道返回的原始数据 JSON。
/// </summary>
public string? Payload { get; set; }
}

View File

@@ -0,0 +1,14 @@
namespace TakeoutSaaS.Domain.Payments.Enums;
/// <summary>
/// 支付方式。
/// </summary>
public enum PaymentMethod
{
Unknown = 0,
WeChatPay = 1,
Alipay = 2,
Cash = 3,
Card = 4,
Balance = 5
}

View File

@@ -0,0 +1,27 @@
namespace TakeoutSaaS.Domain.Payments.Enums;
/// <summary>
/// 支付退款状态。
/// </summary>
public enum PaymentRefundStatus
{
/// <summary>
/// 已提交至渠道。
/// </summary>
Pending = 0,
/// <summary>
/// 退款成功。
/// </summary>
Succeeded = 1,
/// <summary>
/// 退款失败。
/// </summary>
Failed = 2,
/// <summary>
/// 渠道处理中。
/// </summary>
Processing = 3
}

View File

@@ -0,0 +1,13 @@
namespace TakeoutSaaS.Domain.Payments.Enums;
/// <summary>
/// 支付记录状态。
/// </summary>
public enum PaymentStatus
{
Unpaid = 0,
Paying = 1,
Paid = 2,
Failed = 3,
Refunded = 4
}

View File

@@ -0,0 +1,100 @@
using TakeoutSaaS.Domain.Products.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Products.Entities;
/// <summary>
/// 商品SPU信息。
/// </summary>
public sealed class Product : MultiTenantEntityBase
{
/// <summary>
/// 所属门店。
/// </summary>
public Guid StoreId { get; set; }
/// <summary>
/// 所属分类。
/// </summary>
public Guid CategoryId { get; set; }
/// <summary>
/// 商品编码。
/// </summary>
public string SpuCode { get; set; } = string.Empty;
/// <summary>
/// 商品名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 副标题/卖点。
/// </summary>
public string? Subtitle { get; set; }
/// <summary>
/// 售卖单位(份/杯等)。
/// </summary>
public string? Unit { get; set; }
/// <summary>
/// 现价。
/// </summary>
public decimal Price { get; set; }
/// <summary>
/// 原价。
/// </summary>
public decimal? OriginalPrice { get; set; }
/// <summary>
/// 库存数量(可选)。
/// </summary>
public int? StockQuantity { get; set; }
/// <summary>
/// 最大每单限购。
/// </summary>
public int? MaxQuantityPerOrder { get; set; }
/// <summary>
/// 商品状态。
/// </summary>
public ProductStatus Status { get; set; } = ProductStatus.Draft;
/// <summary>
/// 主图。
/// </summary>
public string? CoverImage { get; set; }
/// <summary>
/// Gallery 图片逗号分隔。
/// </summary>
public string? GalleryImages { get; set; }
/// <summary>
/// 商品描述。
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 支持堂食。
/// </summary>
public bool EnableDineIn { get; set; } = true;
/// <summary>
/// 支持自提。
/// </summary>
public bool EnablePickup { get; set; } = true;
/// <summary>
/// 支持配送。
/// </summary>
public bool EnableDelivery { get; set; } = true;
/// <summary>
/// 是否热门推荐。
/// </summary>
public bool IsFeatured { get; set; }
}

View File

@@ -0,0 +1,45 @@
using TakeoutSaaS.Domain.Products.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Products.Entities;
/// <summary>
/// 加料/做法分组。
/// </summary>
public sealed class ProductAddonGroup : MultiTenantEntityBase
{
/// <summary>
/// 所属商品。
/// </summary>
public Guid ProductId { get; set; }
/// <summary>
/// 分组名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 选择类型。
/// </summary>
public AddonSelectionType SelectionType { get; set; } = AddonSelectionType.Single;
/// <summary>
/// 最小选择数量。
/// </summary>
public int? MinSelect { get; set; }
/// <summary>
/// 最大选择数量。
/// </summary>
public int? MaxSelect { get; set; }
/// <summary>
/// 是否必选。
/// </summary>
public bool IsRequired { get; set; }
/// <summary>
/// 排序值。
/// </summary>
public int SortOrder { get; set; } = 100;
}

View File

@@ -0,0 +1,34 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Products.Entities;
/// <summary>
/// 加料选项。
/// </summary>
public sealed class ProductAddonOption : MultiTenantEntityBase
{
/// <summary>
/// 所属加料分组。
/// </summary>
public Guid AddonGroupId { get; set; }
/// <summary>
/// 选项名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 附加价格。
/// </summary>
public decimal? ExtraPrice { get; set; }
/// <summary>
/// 是否默认选项。
/// </summary>
public bool IsDefault { get; set; }
/// <summary>
/// 排序。
/// </summary>
public int SortOrder { get; set; } = 100;
}

View File

@@ -0,0 +1,35 @@
using TakeoutSaaS.Domain.Products.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Products.Entities;
/// <summary>
/// 商品规格/属性分组。
/// </summary>
public sealed class ProductAttributeGroup : MultiTenantEntityBase
{
/// <summary>
/// 关联门店,可为空表示所有门店共享。
/// </summary>
public Guid? StoreId { get; set; }
/// <summary>
/// 分组名称,例如“辣度”“份量”。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 选择类型(单选/多选)。
/// </summary>
public AttributeSelectionType SelectionType { get; set; } = AttributeSelectionType.Single;
/// <summary>
/// 是否必选。
/// </summary>
public bool IsRequired { get; set; }
/// <summary>
/// 显示排序。
/// </summary>
public int SortOrder { get; set; } = 100;
}

View File

@@ -0,0 +1,34 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Products.Entities;
/// <summary>
/// 商品规格选项。
/// </summary>
public sealed class ProductAttributeOption : MultiTenantEntityBase
{
/// <summary>
/// 所属规格组。
/// </summary>
public Guid AttributeGroupId { get; set; }
/// <summary>
/// 选项名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 附加价格。
/// </summary>
public decimal? ExtraPrice { get; set; }
/// <summary>
/// 排序。
/// </summary>
public int SortOrder { get; set; } = 100;
/// <summary>
/// 是否默认选中。
/// </summary>
public bool IsDefault { get; set; }
}

View File

@@ -0,0 +1,34 @@
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Products.Entities;
/// <summary>
/// 商品分类。
/// </summary>
public sealed class ProductCategory : MultiTenantEntityBase
{
/// <summary>
/// 所属门店。
/// </summary>
public Guid StoreId { get; set; }
/// <summary>
/// 分类名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 分类描述。
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 排序值。
/// </summary>
public int SortOrder { get; set; } = 100;
/// <summary>
/// 是否启用。
/// </summary>
public bool IsEnabled { get; set; } = true;
}

View File

@@ -0,0 +1,35 @@
using TakeoutSaaS.Domain.Products.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Products.Entities;
/// <summary>
/// 商品媒资素材。
/// </summary>
public sealed class ProductMediaAsset : MultiTenantEntityBase
{
/// <summary>
/// 商品标识。
/// </summary>
public Guid ProductId { get; set; }
/// <summary>
/// 媒体类型。
/// </summary>
public MediaAssetType MediaType { get; set; } = MediaAssetType.Image;
/// <summary>
/// 媒资链接。
/// </summary>
public string Url { get; set; } = string.Empty;
/// <summary>
/// 描述或标题。
/// </summary>
public string? Caption { get; set; }
/// <summary>
/// 排序。
/// </summary>
public int SortOrder { get; set; } = 100;
}

View File

@@ -0,0 +1,45 @@
using TakeoutSaaS.Domain.Products.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Products.Entities;
/// <summary>
/// 商品价格策略,支持会员价/时段价等。
/// </summary>
public sealed class ProductPricingRule : MultiTenantEntityBase
{
/// <summary>
/// 所属商品。
/// </summary>
public Guid ProductId { get; set; }
/// <summary>
/// 策略类型。
/// </summary>
public PricingRuleType RuleType { get; set; } = PricingRuleType.Member;
/// <summary>
/// 条件描述JSON如会员等级、渠道等。
/// </summary>
public string ConditionsJson { get; set; } = string.Empty;
/// <summary>
/// 特殊价格。
/// </summary>
public decimal Price { get; set; }
/// <summary>
/// 生效开始时间。
/// </summary>
public DateTime? StartTime { get; set; }
/// <summary>
/// 生效结束时间。
/// </summary>
public DateTime? EndTime { get; set; }
/// <summary>
/// 生效星期JSON 数组)。
/// </summary>
public string? WeekdaysJson { get; set; }
}

Some files were not shown because too many files have changed in this diff Show More