diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json
new file mode 100644
index 0000000..0d6d304
--- /dev/null
+++ b/.config/dotnet-tools.json
@@ -0,0 +1,13 @@
+{
+ "version": 1,
+ "isRoot": true,
+ "tools": {
+ "dotnet-ef": {
+ "version": "10.0.0",
+ "commands": [
+ "dotnet-ef"
+ ],
+ "rollForward": false
+ }
+ }
+}
\ No newline at end of file
diff --git a/Document/05_部署运维.md b/Document/05_部署运维.md
index 1ff6392..449ab67 100644
--- a/Document/05_部署运维.md
+++ b/Document/05_部署运维.md
@@ -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
diff --git a/src/Api/TakeoutSaaS.AdminApi/appsettings.Development.json b/src/Api/TakeoutSaaS.AdminApi/appsettings.Development.json
index f015bba..d858ad3 100644
--- a/src/Api/TakeoutSaaS.AdminApi/appsettings.Development.json
+++ b/src/Api/TakeoutSaaS.AdminApi/appsettings.Development.json
@@ -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"
diff --git a/src/Api/TakeoutSaaS.AdminApi/appsettings.Production.json b/src/Api/TakeoutSaaS.AdminApi/appsettings.Production.json
index f015bba..d858ad3 100644
--- a/src/Api/TakeoutSaaS.AdminApi/appsettings.Production.json
+++ b/src/Api/TakeoutSaaS.AdminApi/appsettings.Production.json
@@ -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"
diff --git a/src/Domain/TakeoutSaaS.Domain/Analytics/Entities/MetricAlertRule.cs b/src/Domain/TakeoutSaaS.Domain/Analytics/Entities/MetricAlertRule.cs
new file mode 100644
index 0000000..694dfca
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Analytics/Entities/MetricAlertRule.cs
@@ -0,0 +1,35 @@
+using TakeoutSaaS.Domain.Analytics.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Analytics.Entities;
+
+///
+/// 指标告警规则。
+///
+public sealed class MetricAlertRule : MultiTenantEntityBase
+{
+ ///
+ /// 关联指标。
+ ///
+ public Guid MetricDefinitionId { get; set; }
+
+ ///
+ /// 触发条件 JSON。
+ ///
+ public string ConditionJson { get; set; } = string.Empty;
+
+ ///
+ /// 告警级别。
+ ///
+ public MetricAlertSeverity Severity { get; set; } = MetricAlertSeverity.Warning;
+
+ ///
+ /// 通知渠道。
+ ///
+ public string NotificationChannels { get; set; } = "email";
+
+ ///
+ /// 是否启用。
+ ///
+ public bool Enabled { get; set; } = true;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Analytics/Entities/MetricDefinition.cs b/src/Domain/TakeoutSaaS.Domain/Analytics/Entities/MetricDefinition.cs
new file mode 100644
index 0000000..1180216
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Analytics/Entities/MetricDefinition.cs
@@ -0,0 +1,34 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Analytics.Entities;
+
+///
+/// 指标定义,描述可观测的数据点。
+///
+public sealed class MetricDefinition : MultiTenantEntityBase
+{
+ ///
+ /// 指标编码。
+ ///
+ public string Code { get; set; } = string.Empty;
+
+ ///
+ /// 指标名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 说明。
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// 维度描述 JSON。
+ ///
+ public string? DimensionsJson { get; set; }
+
+ ///
+ /// 默认聚合方式。
+ ///
+ public string DefaultAggregation { get; set; } = "sum";
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Analytics/Entities/MetricSnapshot.cs b/src/Domain/TakeoutSaaS.Domain/Analytics/Entities/MetricSnapshot.cs
new file mode 100644
index 0000000..cb0e726
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Analytics/Entities/MetricSnapshot.cs
@@ -0,0 +1,34 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Analytics.Entities;
+
+///
+/// 指标快照,用于大盘展示。
+///
+public sealed class MetricSnapshot : MultiTenantEntityBase
+{
+ ///
+ /// 指标定义 ID。
+ ///
+ public Guid MetricDefinitionId { get; set; }
+
+ ///
+ /// 维度键(JSON)。
+ ///
+ public string DimensionKey { get; set; } = string.Empty;
+
+ ///
+ /// 统计时间窗口开始。
+ ///
+ public DateTime WindowStart { get; set; }
+
+ ///
+ /// 统计时间窗口结束。
+ ///
+ public DateTime WindowEnd { get; set; }
+
+ ///
+ /// 数值。
+ ///
+ public decimal Value { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Analytics/Enums/MetricAlertSeverity.cs b/src/Domain/TakeoutSaaS.Domain/Analytics/Enums/MetricAlertSeverity.cs
new file mode 100644
index 0000000..a1e79eb
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Analytics/Enums/MetricAlertSeverity.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Analytics.Enums;
+
+///
+/// 指标告警严重程度。
+///
+public enum MetricAlertSeverity
+{
+ ///
+ /// 信息提示。
+ ///
+ Info = 0,
+
+ ///
+ /// 告警。
+ ///
+ Warning = 1,
+
+ ///
+ /// 严重。
+ ///
+ Critical = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Coupons/Entities/Coupon.cs b/src/Domain/TakeoutSaaS.Domain/Coupons/Entities/Coupon.cs
new file mode 100644
index 0000000..c327f0b
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Coupons/Entities/Coupon.cs
@@ -0,0 +1,50 @@
+using TakeoutSaaS.Domain.Coupons.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Coupons.Entities;
+
+///
+/// 用户领取的券。
+///
+public sealed class Coupon : MultiTenantEntityBase
+{
+ ///
+ /// 模板标识。
+ ///
+ public Guid CouponTemplateId { get; set; }
+
+ ///
+ /// 券码或序列号。
+ ///
+ public string Code { get; set; } = string.Empty;
+
+ ///
+ /// 归属用户。
+ ///
+ public Guid UserId { get; set; }
+
+ ///
+ /// 订单 ID(已使用时记录)。
+ ///
+ public Guid? OrderId { get; set; }
+
+ ///
+ /// 状态。
+ ///
+ public CouponStatus Status { get; set; } = CouponStatus.Available;
+
+ ///
+ /// 发放时间。
+ ///
+ public DateTime IssuedAt { get; set; } = DateTime.UtcNow;
+
+ ///
+ /// 使用时间。
+ ///
+ public DateTime? UsedAt { get; set; }
+
+ ///
+ /// 到期时间。
+ ///
+ public DateTime ExpireAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Coupons/Entities/CouponTemplate.cs b/src/Domain/TakeoutSaaS.Domain/Coupons/Entities/CouponTemplate.cs
new file mode 100644
index 0000000..8f795a6
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Coupons/Entities/CouponTemplate.cs
@@ -0,0 +1,90 @@
+using TakeoutSaaS.Domain.Coupons.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Coupons.Entities;
+
+///
+/// 优惠券模板。
+///
+public sealed class CouponTemplate : MultiTenantEntityBase
+{
+ ///
+ /// 模板名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 券类型。
+ ///
+ public CouponType CouponType { get; set; } = CouponType.AmountOff;
+
+ ///
+ /// 面值或折扣额度。
+ ///
+ public decimal Value { get; set; }
+
+ ///
+ /// 折扣上限(针对折扣券)。
+ ///
+ public decimal? DiscountCap { get; set; }
+
+ ///
+ /// 最低消费门槛。
+ ///
+ public decimal? MinimumSpend { get; set; }
+
+ ///
+ /// 可用开始时间。
+ ///
+ public DateTime? ValidFrom { get; set; }
+
+ ///
+ /// 可用结束时间。
+ ///
+ public DateTime? ValidTo { get; set; }
+
+ ///
+ /// 有效天数(相对发放时间)。
+ ///
+ public int? RelativeValidDays { get; set; }
+
+ ///
+ /// 总发放数量上限。
+ ///
+ public int? TotalQuantity { get; set; }
+
+ ///
+ /// 已领取数量。
+ ///
+ public int ClaimedQuantity { get; set; }
+
+ ///
+ /// 适用门店 ID 集合(JSON)。
+ ///
+ public string? StoreScopeJson { get; set; }
+
+ ///
+ /// 适用品类或商品范围(JSON)。
+ ///
+ public string? ProductScopeJson { get; set; }
+
+ ///
+ /// 发放渠道(JSON)。
+ ///
+ public string? ChannelsJson { get; set; }
+
+ ///
+ /// 是否允许叠加其他优惠。
+ ///
+ public bool AllowStack { get; set; }
+
+ ///
+ /// 状态。
+ ///
+ public CouponTemplateStatus Status { get; set; } = CouponTemplateStatus.Draft;
+
+ ///
+ /// 备注。
+ ///
+ public string? Description { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Coupons/Entities/PromotionCampaign.cs b/src/Domain/TakeoutSaaS.Domain/Coupons/Entities/PromotionCampaign.cs
new file mode 100644
index 0000000..8cab151
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Coupons/Entities/PromotionCampaign.cs
@@ -0,0 +1,55 @@
+using TakeoutSaaS.Domain.Coupons.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Coupons.Entities;
+
+///
+/// 营销活动配置。
+///
+public sealed class PromotionCampaign : MultiTenantEntityBase
+{
+ ///
+ /// 活动名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 活动类型。
+ ///
+ public PromotionType PromotionType { get; set; } = PromotionType.Coupon;
+
+ ///
+ /// 活动状态。
+ ///
+ public PromotionStatus Status { get; set; } = PromotionStatus.Draft;
+
+ ///
+ /// 开始时间。
+ ///
+ public DateTime StartAt { get; set; }
+
+ ///
+ /// 结束时间。
+ ///
+ public DateTime EndAt { get; set; }
+
+ ///
+ /// 预算金额。
+ ///
+ public decimal? Budget { get; set; }
+
+ ///
+ /// 活动规则 JSON。
+ ///
+ public string RulesJson { get; set; } = string.Empty;
+
+ ///
+ /// 目标人群描述。
+ ///
+ public string? AudienceDescription { get; set; }
+
+ ///
+ /// 营销素材(如 banner)。
+ ///
+ public string? BannerUrl { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/CouponStatus.cs b/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/CouponStatus.cs
new file mode 100644
index 0000000..7897089
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/CouponStatus.cs
@@ -0,0 +1,32 @@
+namespace TakeoutSaaS.Domain.Coupons.Enums;
+
+///
+/// 券使用状态。
+///
+public enum CouponStatus
+{
+ ///
+ /// 可使用。
+ ///
+ Available = 0,
+
+ ///
+ /// 已锁定。
+ ///
+ Locked = 1,
+
+ ///
+ /// 已使用。
+ ///
+ Redeemed = 2,
+
+ ///
+ /// 已过期。
+ ///
+ Expired = 3,
+
+ ///
+ /// 已作废。
+ ///
+ Voided = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/CouponTemplateStatus.cs b/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/CouponTemplateStatus.cs
new file mode 100644
index 0000000..d5aefd5
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/CouponTemplateStatus.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Coupons.Enums;
+
+///
+/// 券模板状态。
+///
+public enum CouponTemplateStatus
+{
+ ///
+ /// 草稿状态。
+ ///
+ Draft = 0,
+
+ ///
+ /// 已上线可发放。
+ ///
+ Active = 1,
+
+ ///
+ /// 已下架。
+ ///
+ Archived = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/CouponType.cs b/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/CouponType.cs
new file mode 100644
index 0000000..8206bd2
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/CouponType.cs
@@ -0,0 +1,32 @@
+namespace TakeoutSaaS.Domain.Coupons.Enums;
+
+///
+/// 券类型。
+///
+public enum CouponType
+{
+ ///
+ /// 满减券。
+ ///
+ AmountOff = 0,
+
+ ///
+ /// 折扣券。
+ ///
+ Percentage = 1,
+
+ ///
+ /// 现金券/无门槛券。
+ ///
+ Cash = 2,
+
+ ///
+ /// 免配送费券。
+ ///
+ DeliveryFee = 3,
+
+ ///
+ /// 礼品/兑换券。
+ ///
+ Gift = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/PromotionStatus.cs b/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/PromotionStatus.cs
new file mode 100644
index 0000000..2b12ee1
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/PromotionStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Coupons.Enums;
+
+///
+/// 营销活动状态。
+///
+public enum PromotionStatus
+{
+ ///
+ /// 草稿。
+ ///
+ Draft = 0,
+
+ ///
+ /// 进行中。
+ ///
+ Active = 1,
+
+ ///
+ /// 已结束。
+ ///
+ Completed = 2,
+
+ ///
+ /// 暂停。
+ ///
+ Paused = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/PromotionType.cs b/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/PromotionType.cs
new file mode 100644
index 0000000..e30893d
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Coupons/Enums/PromotionType.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Coupons.Enums;
+
+///
+/// 营销活动类型。
+///
+public enum PromotionType
+{
+ ///
+ /// 优惠券活动。
+ ///
+ Coupon = 0,
+
+ ///
+ /// 秒杀/限时购。
+ ///
+ FlashSale = 1,
+
+ ///
+ /// 满减活动。
+ ///
+ FullReduction = 2,
+
+ ///
+ /// 抽奖活动。
+ ///
+ Lottery = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/ChatMessage.cs b/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/ChatMessage.cs
new file mode 100644
index 0000000..56799b5
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/ChatMessage.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.CustomerService.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.CustomerService.Entities;
+
+///
+/// 会话消息。
+///
+public sealed class ChatMessage : MultiTenantEntityBase
+{
+ ///
+ /// 会话标识。
+ ///
+ public Guid ChatSessionId { get; set; }
+
+ ///
+ /// 发送方类型。
+ ///
+ public MessageSenderType SenderType { get; set; } = MessageSenderType.Customer;
+
+ ///
+ /// 发送方用户 ID。
+ ///
+ public Guid? SenderUserId { get; set; }
+
+ ///
+ /// 消息内容。
+ ///
+ public string Content { get; set; } = string.Empty;
+
+ ///
+ /// 消息类型(文字/图片/语音等)。
+ ///
+ public string ContentType { get; set; } = "text/plain";
+
+ ///
+ /// 是否已读。
+ ///
+ public bool IsRead { get; set; }
+
+ ///
+ /// 读取时间。
+ ///
+ public DateTime? ReadAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/ChatSession.cs b/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/ChatSession.cs
new file mode 100644
index 0000000..d2528ea
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/ChatSession.cs
@@ -0,0 +1,50 @@
+using TakeoutSaaS.Domain.CustomerService.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.CustomerService.Entities;
+
+///
+/// 客服会话。
+///
+public sealed class ChatSession : MultiTenantEntityBase
+{
+ ///
+ /// 会话编号。
+ ///
+ public string SessionCode { get; set; } = string.Empty;
+
+ ///
+ /// 顾客用户 ID。
+ ///
+ public Guid CustomerUserId { get; set; }
+
+ ///
+ /// 当前客服员工 ID。
+ ///
+ public Guid? AgentUserId { get; set; }
+
+ ///
+ /// 所属门店(可空为平台)。
+ ///
+ public Guid? StoreId { get; set; }
+
+ ///
+ /// 会话状态。
+ ///
+ public ChatSessionStatus Status { get; set; } = ChatSessionStatus.Waiting;
+
+ ///
+ /// 是否机器人接待中。
+ ///
+ public bool IsBotActive { get; set; }
+
+ ///
+ /// 开始时间。
+ ///
+ public DateTime StartedAt { get; set; } = DateTime.UtcNow;
+
+ ///
+ /// 结束时间。
+ ///
+ public DateTime? EndedAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/SupportTicket.cs b/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/SupportTicket.cs
new file mode 100644
index 0000000..931727d
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/SupportTicket.cs
@@ -0,0 +1,55 @@
+using TakeoutSaaS.Domain.CustomerService.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.CustomerService.Entities;
+
+///
+/// 客服工单。
+///
+public sealed class SupportTicket : MultiTenantEntityBase
+{
+ ///
+ /// 工单编号。
+ ///
+ public string TicketNo { get; set; } = string.Empty;
+
+ ///
+ /// 客户用户 ID。
+ ///
+ public Guid CustomerUserId { get; set; }
+
+ ///
+ /// 关联订单(如有)。
+ ///
+ public Guid? OrderId { get; set; }
+
+ ///
+ /// 工单主题。
+ ///
+ public string Subject { get; set; } = string.Empty;
+
+ ///
+ /// 工单详情。
+ ///
+ public string Description { get; set; } = string.Empty;
+
+ ///
+ /// 优先级。
+ ///
+ public TicketPriority Priority { get; set; } = TicketPriority.Normal;
+
+ ///
+ /// 状态。
+ ///
+ public TicketStatus Status { get; set; } = TicketStatus.Open;
+
+ ///
+ /// 指派的客服。
+ ///
+ public Guid? AssignedAgentId { get; set; }
+
+ ///
+ /// 关闭时间。
+ ///
+ public DateTime? ClosedAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/TicketComment.cs b/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/TicketComment.cs
new file mode 100644
index 0000000..f6abba6
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/CustomerService/Entities/TicketComment.cs
@@ -0,0 +1,34 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.CustomerService.Entities;
+
+///
+/// 工单评论/流转记录。
+///
+public sealed class TicketComment : MultiTenantEntityBase
+{
+ ///
+ /// 工单标识。
+ ///
+ public Guid SupportTicketId { get; set; }
+
+ ///
+ /// 评论人 ID。
+ ///
+ public Guid? AuthorUserId { get; set; }
+
+ ///
+ /// 评论内容。
+ ///
+ public string Content { get; set; } = string.Empty;
+
+ ///
+ /// 是否内部备注。
+ ///
+ public bool IsInternal { get; set; }
+
+ ///
+ /// 附件 JSON。
+ ///
+ public string? AttachmentsJson { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/ChatSessionStatus.cs b/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/ChatSessionStatus.cs
new file mode 100644
index 0000000..e774652
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/ChatSessionStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.CustomerService.Enums;
+
+///
+/// 客服会话状态。
+///
+public enum ChatSessionStatus
+{
+ ///
+ /// 等待客服接入。
+ ///
+ Waiting = 0,
+
+ ///
+ /// 聊天进行中。
+ ///
+ Active = 1,
+
+ ///
+ /// 已转人工排队。
+ ///
+ Queueing = 2,
+
+ ///
+ /// 已结束。
+ ///
+ Closed = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/MessageSenderType.cs b/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/MessageSenderType.cs
new file mode 100644
index 0000000..826c923
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/MessageSenderType.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.CustomerService.Enums;
+
+///
+/// 消息发送方类型。
+///
+public enum MessageSenderType
+{
+ ///
+ /// 顾客。
+ ///
+ Customer = 0,
+
+ ///
+ /// 客服人员。
+ ///
+ Agent = 1,
+
+ ///
+ /// 机器人。
+ ///
+ Bot = 2,
+
+ ///
+ /// 系统通知。
+ ///
+ System = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/TicketPriority.cs b/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/TicketPriority.cs
new file mode 100644
index 0000000..e875355
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/TicketPriority.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.CustomerService.Enums;
+
+///
+/// 工单优先级。
+///
+public enum TicketPriority
+{
+ ///
+ /// 普通。
+ ///
+ Normal = 0,
+
+ ///
+ /// 高。
+ ///
+ High = 1,
+
+ ///
+ /// 紧急。
+ ///
+ Urgent = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/TicketStatus.cs b/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/TicketStatus.cs
new file mode 100644
index 0000000..40d6311
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/CustomerService/Enums/TicketStatus.cs
@@ -0,0 +1,32 @@
+namespace TakeoutSaaS.Domain.CustomerService.Enums;
+
+///
+/// 工单状态。
+///
+public enum TicketStatus
+{
+ ///
+ /// 新建未处理。
+ ///
+ Open = 0,
+
+ ///
+ /// 处理中。
+ ///
+ InProgress = 1,
+
+ ///
+ /// 等待客户反馈。
+ ///
+ PendingCustomer = 2,
+
+ ///
+ /// 已解决。
+ ///
+ Resolved = 3,
+
+ ///
+ /// 已关闭。
+ ///
+ Closed = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Deliveries/Entities/DeliveryEvent.cs b/src/Domain/TakeoutSaaS.Domain/Deliveries/Entities/DeliveryEvent.cs
new file mode 100644
index 0000000..771f564
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Deliveries/Entities/DeliveryEvent.cs
@@ -0,0 +1,35 @@
+using TakeoutSaaS.Domain.Deliveries.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Deliveries.Entities;
+
+///
+/// 配送状态事件流水。
+///
+public sealed class DeliveryEvent : MultiTenantEntityBase
+{
+ ///
+ /// 配送单标识。
+ ///
+ public Guid DeliveryOrderId { get; set; }
+
+ ///
+ /// 事件类型。
+ ///
+ public DeliveryEventType EventType { get; set; } = DeliveryEventType.Updated;
+
+ ///
+ /// 事件描述。
+ ///
+ public string Message { get; set; } = string.Empty;
+
+ ///
+ /// 原始数据 JSON。
+ ///
+ public string? Payload { get; set; }
+
+ ///
+ /// 发生时间。
+ ///
+ public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Deliveries/Entities/DeliveryOrder.cs b/src/Domain/TakeoutSaaS.Domain/Deliveries/Entities/DeliveryOrder.cs
new file mode 100644
index 0000000..31dbfc1
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Deliveries/Entities/DeliveryOrder.cs
@@ -0,0 +1,62 @@
+using TakeoutSaaS.Domain.Deliveries.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Deliveries.Entities;
+
+///
+/// 配送单。
+///
+public sealed class DeliveryOrder : MultiTenantEntityBase
+{
+ public Guid OrderId { get; set; }
+
+ ///
+ /// 配送服务商。
+ ///
+ public DeliveryProvider Provider { get; set; } = DeliveryProvider.InHouse;
+
+ ///
+ /// 第三方配送单号。
+ ///
+ public string? ProviderOrderId { get; set; }
+
+ ///
+ /// 状态。
+ ///
+ public DeliveryStatus Status { get; set; } = DeliveryStatus.Pending;
+
+ ///
+ /// 配送费。
+ ///
+ public decimal? DeliveryFee { get; set; }
+
+ ///
+ /// 骑手姓名。
+ ///
+ public string? CourierName { get; set; }
+
+ ///
+ /// 骑手电话。
+ ///
+ public string? CourierPhone { get; set; }
+
+ ///
+ /// 下发时间。
+ ///
+ public DateTime? DispatchedAt { get; set; }
+
+ ///
+ /// 取餐时间。
+ ///
+ public DateTime? PickedUpAt { get; set; }
+
+ ///
+ /// 完成时间。
+ ///
+ public DateTime? DeliveredAt { get; set; }
+
+ ///
+ /// 异常原因。
+ ///
+ public string? FailureReason { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Deliveries/Enums/DeliveryEventType.cs b/src/Domain/TakeoutSaaS.Domain/Deliveries/Enums/DeliveryEventType.cs
new file mode 100644
index 0000000..ce1914d
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Deliveries/Enums/DeliveryEventType.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Deliveries.Enums;
+
+///
+/// 配送事件类型。
+///
+public enum DeliveryEventType
+{
+ ///
+ /// 状态更新。
+ ///
+ Updated = 0,
+
+ ///
+ /// 渠道回调。
+ ///
+ Callback = 1,
+
+ ///
+ /// 加价或异常通知。
+ ///
+ Exception = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Deliveries/Enums/DeliveryProvider.cs b/src/Domain/TakeoutSaaS.Domain/Deliveries/Enums/DeliveryProvider.cs
new file mode 100644
index 0000000..70cff85
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Deliveries/Enums/DeliveryProvider.cs
@@ -0,0 +1,14 @@
+namespace TakeoutSaaS.Domain.Deliveries.Enums;
+
+///
+/// 配送服务商类型。
+///
+public enum DeliveryProvider
+{
+ InHouse = 0,
+ Dada = 1,
+ FlashEx = 2,
+ Meituan = 3,
+ Eleme = 4,
+ Shunfeng = 5
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Deliveries/Enums/DeliveryStatus.cs b/src/Domain/TakeoutSaaS.Domain/Deliveries/Enums/DeliveryStatus.cs
new file mode 100644
index 0000000..7f6aaef
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Deliveries/Enums/DeliveryStatus.cs
@@ -0,0 +1,15 @@
+namespace TakeoutSaaS.Domain.Deliveries.Enums;
+
+///
+/// 配送状态。
+///
+public enum DeliveryStatus
+{
+ Pending = 0,
+ Accepted = 1,
+ PickingUp = 2,
+ Delivering = 3,
+ Completed = 4,
+ Cancelled = 5,
+ Failed = 6
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Distribution/Entities/AffiliateOrder.cs b/src/Domain/TakeoutSaaS.Domain/Distribution/Entities/AffiliateOrder.cs
new file mode 100644
index 0000000..0b1bb24
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Distribution/Entities/AffiliateOrder.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Distribution.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Distribution.Entities;
+
+///
+/// 分销订单记录。
+///
+public sealed class AffiliateOrder : MultiTenantEntityBase
+{
+ ///
+ /// 推广人标识。
+ ///
+ public Guid AffiliatePartnerId { get; set; }
+
+ ///
+ /// 关联订单。
+ ///
+ public Guid OrderId { get; set; }
+
+ ///
+ /// 用户 ID。
+ ///
+ public Guid BuyerUserId { get; set; }
+
+ ///
+ /// 订单金额。
+ ///
+ public decimal OrderAmount { get; set; }
+
+ ///
+ /// 预计佣金。
+ ///
+ public decimal EstimatedCommission { get; set; }
+
+ ///
+ /// 当前状态。
+ ///
+ public AffiliateOrderStatus Status { get; set; } = AffiliateOrderStatus.Pending;
+
+ ///
+ /// 结算完成时间。
+ ///
+ public DateTime? SettledAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Distribution/Entities/AffiliatePartner.cs b/src/Domain/TakeoutSaaS.Domain/Distribution/Entities/AffiliatePartner.cs
new file mode 100644
index 0000000..d9ceaa1
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Distribution/Entities/AffiliatePartner.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Distribution.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Distribution.Entities;
+
+///
+/// 分销/推广合作伙伴。
+///
+public sealed class AffiliatePartner : MultiTenantEntityBase
+{
+ ///
+ /// 用户 ID(如绑定平台账号)。
+ ///
+ public Guid? UserId { get; set; }
+
+ ///
+ /// 昵称或渠道名称。
+ ///
+ public string DisplayName { get; set; } = string.Empty;
+
+ ///
+ /// 联系电话。
+ ///
+ public string? Phone { get; set; }
+
+ ///
+ /// 渠道类型。
+ ///
+ public AffiliateChannelType ChannelType { get; set; } = AffiliateChannelType.Personal;
+
+ ///
+ /// 分成比例(0-1)。
+ ///
+ public decimal CommissionRate { get; set; }
+
+ ///
+ /// 当前状态。
+ ///
+ public AffiliateStatus Status { get; set; } = AffiliateStatus.Pending;
+
+ ///
+ /// 审核备注。
+ ///
+ public string? Remarks { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Distribution/Entities/AffiliatePayout.cs b/src/Domain/TakeoutSaaS.Domain/Distribution/Entities/AffiliatePayout.cs
new file mode 100644
index 0000000..774c4e4
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Distribution/Entities/AffiliatePayout.cs
@@ -0,0 +1,40 @@
+using TakeoutSaaS.Domain.Distribution.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Distribution.Entities;
+
+///
+/// 佣金结算记录。
+///
+public sealed class AffiliatePayout : MultiTenantEntityBase
+{
+ ///
+ /// 合作伙伴标识。
+ ///
+ public Guid AffiliatePartnerId { get; set; }
+
+ ///
+ /// 结算周期描述。
+ ///
+ public string Period { get; set; } = string.Empty;
+
+ ///
+ /// 结算金额。
+ ///
+ public decimal Amount { get; set; }
+
+ ///
+ /// 状态。
+ ///
+ public PayoutStatus Status { get; set; } = PayoutStatus.Pending;
+
+ ///
+ /// 打款时间。
+ ///
+ public DateTime? PaidAt { get; set; }
+
+ ///
+ /// 备注。
+ ///
+ public string? Remarks { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/AffiliateChannelType.cs b/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/AffiliateChannelType.cs
new file mode 100644
index 0000000..963bd98
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/AffiliateChannelType.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Distribution.Enums;
+
+///
+/// 推广渠道类型。
+///
+public enum AffiliateChannelType
+{
+ ///
+ /// 个人。
+ ///
+ Personal = 0,
+
+ ///
+ /// 自媒体。
+ ///
+ Media = 1,
+
+ ///
+ /// 门店地推。
+ ///
+ Offline = 2,
+
+ ///
+ /// 第三方联盟。
+ ///
+ Alliance = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/AffiliateOrderStatus.cs b/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/AffiliateOrderStatus.cs
new file mode 100644
index 0000000..a28f953
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/AffiliateOrderStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Distribution.Enums;
+
+///
+/// 分销订单状态。
+///
+public enum AffiliateOrderStatus
+{
+ ///
+ /// 待成交通知。
+ ///
+ Pending = 0,
+
+ ///
+ /// 已完成待结算。
+ ///
+ AwaitingPayout = 1,
+
+ ///
+ /// 已结算。
+ ///
+ Settled = 2,
+
+ ///
+ /// 因退款失效。
+ ///
+ Invalidated = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/AffiliateStatus.cs b/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/AffiliateStatus.cs
new file mode 100644
index 0000000..7e25a50
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/AffiliateStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Distribution.Enums;
+
+///
+/// 合作伙伴状态。
+///
+public enum AffiliateStatus
+{
+ ///
+ /// 待审核。
+ ///
+ Pending = 0,
+
+ ///
+ /// 已激活。
+ ///
+ Active = 1,
+
+ ///
+ /// 已冻结。
+ ///
+ Suspended = 2,
+
+ ///
+ /// 已退出。
+ ///
+ Closed = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/PayoutStatus.cs b/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/PayoutStatus.cs
new file mode 100644
index 0000000..0f96e3d
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Distribution/Enums/PayoutStatus.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Distribution.Enums;
+
+///
+/// 佣金结算状态。
+///
+public enum PayoutStatus
+{
+ ///
+ /// 待打款。
+ ///
+ Pending = 0,
+
+ ///
+ /// 已打款。
+ ///
+ Paid = 1,
+
+ ///
+ /// 已驳回。
+ ///
+ Rejected = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CheckInCampaign.cs b/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CheckInCampaign.cs
new file mode 100644
index 0000000..1e279d5
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CheckInCampaign.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Engagement.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Engagement.Entities;
+
+///
+/// 签到活动配置。
+///
+public sealed class CheckInCampaign : MultiTenantEntityBase
+{
+ ///
+ /// 活动名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 活动描述。
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// 开始日期。
+ ///
+ public DateTime StartDate { get; set; }
+
+ ///
+ /// 结束日期。
+ ///
+ public DateTime EndDate { get; set; }
+
+ ///
+ /// 支持补签次数。
+ ///
+ public int AllowMakeupCount { get; set; }
+
+ ///
+ /// 连签奖励 JSON。
+ ///
+ public string RewardsJson { get; set; } = string.Empty;
+
+ ///
+ /// 状态。
+ ///
+ public CheckInCampaignStatus Status { get; set; } = CheckInCampaignStatus.Draft;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CheckInRecord.cs b/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CheckInRecord.cs
new file mode 100644
index 0000000..9f41172
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CheckInRecord.cs
@@ -0,0 +1,34 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Engagement.Entities;
+
+///
+/// 用户签到记录。
+///
+public sealed class CheckInRecord : MultiTenantEntityBase
+{
+ ///
+ /// 活动标识。
+ ///
+ public Guid CheckInCampaignId { get; set; }
+
+ ///
+ /// 用户标识。
+ ///
+ public Guid UserId { get; set; }
+
+ ///
+ /// 签到日期(本地)。
+ ///
+ public DateTime CheckInDate { get; set; }
+
+ ///
+ /// 是否补签。
+ ///
+ public bool IsMakeup { get; set; }
+
+ ///
+ /// 获得奖励 JSON。
+ ///
+ public string RewardJson { get; set; } = string.Empty;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CommunityComment.cs b/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CommunityComment.cs
new file mode 100644
index 0000000..3888bfd
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CommunityComment.cs
@@ -0,0 +1,34 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Engagement.Entities;
+
+///
+/// 社区评论。
+///
+public sealed class CommunityComment : MultiTenantEntityBase
+{
+ ///
+ /// 动态标识。
+ ///
+ public Guid PostId { get; set; }
+
+ ///
+ /// 评论人。
+ ///
+ public Guid AuthorUserId { get; set; }
+
+ ///
+ /// 评论内容。
+ ///
+ public string Content { get; set; } = string.Empty;
+
+ ///
+ /// 父级评论 ID。
+ ///
+ public Guid? ParentId { get; set; }
+
+ ///
+ /// 状态。
+ ///
+ public bool IsDeleted { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CommunityPost.cs b/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CommunityPost.cs
new file mode 100644
index 0000000..73c7e21
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CommunityPost.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Engagement.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Engagement.Entities;
+
+///
+/// 社区动态。
+///
+public sealed class CommunityPost : MultiTenantEntityBase
+{
+ ///
+ /// 作者用户 ID。
+ ///
+ public Guid AuthorUserId { get; set; }
+
+ ///
+ /// 标题。
+ ///
+ public string? Title { get; set; }
+
+ ///
+ /// 内容。
+ ///
+ public string Content { get; set; } = string.Empty;
+
+ ///
+ /// 媒体资源 JSON。
+ ///
+ public string? MediaJson { get; set; }
+
+ ///
+ /// 状态。
+ ///
+ public PostStatus Status { get; set; } = PostStatus.PendingReview;
+
+ ///
+ /// 点赞数。
+ ///
+ public int LikeCount { get; set; }
+
+ ///
+ /// 评论数。
+ ///
+ public int CommentCount { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CommunityReaction.cs b/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CommunityReaction.cs
new file mode 100644
index 0000000..b7d5c19
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Engagement/Entities/CommunityReaction.cs
@@ -0,0 +1,30 @@
+using TakeoutSaaS.Domain.Engagement.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Engagement.Entities;
+
+///
+/// 社区互动反馈。
+///
+public sealed class CommunityReaction : MultiTenantEntityBase
+{
+ ///
+ /// 动态 ID。
+ ///
+ public Guid PostId { get; set; }
+
+ ///
+ /// 用户 ID。
+ ///
+ public Guid UserId { get; set; }
+
+ ///
+ /// 反应类型。
+ ///
+ public ReactionType ReactionType { get; set; } = ReactionType.Like;
+
+ ///
+ /// 时间戳。
+ ///
+ public DateTime ReactedAt { get; set; } = DateTime.UtcNow;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Engagement/Enums/CheckInCampaignStatus.cs b/src/Domain/TakeoutSaaS.Domain/Engagement/Enums/CheckInCampaignStatus.cs
new file mode 100644
index 0000000..57a3f0c
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Engagement/Enums/CheckInCampaignStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Engagement.Enums;
+
+///
+/// 签到活动状态。
+///
+public enum CheckInCampaignStatus
+{
+ ///
+ /// 草稿。
+ ///
+ Draft = 0,
+
+ ///
+ /// 进行中。
+ ///
+ Active = 1,
+
+ ///
+ /// 已结束。
+ ///
+ Completed = 2,
+
+ ///
+ /// 已停用。
+ ///
+ Disabled = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Engagement/Enums/PostStatus.cs b/src/Domain/TakeoutSaaS.Domain/Engagement/Enums/PostStatus.cs
new file mode 100644
index 0000000..9ce168b
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Engagement/Enums/PostStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Engagement.Enums;
+
+///
+/// 社区动态状态。
+///
+public enum PostStatus
+{
+ ///
+ /// 待审核。
+ ///
+ PendingReview = 0,
+
+ ///
+ /// 已发布。
+ ///
+ Published = 1,
+
+ ///
+ /// 已屏蔽。
+ ///
+ Blocked = 2,
+
+ ///
+ /// 已删除。
+ ///
+ Deleted = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Engagement/Enums/ReactionType.cs b/src/Domain/TakeoutSaaS.Domain/Engagement/Enums/ReactionType.cs
new file mode 100644
index 0000000..7328bf7
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Engagement/Enums/ReactionType.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Engagement.Enums;
+
+///
+/// 互动类型。
+///
+public enum ReactionType
+{
+ ///
+ /// 点赞。
+ ///
+ Like = 0,
+
+ ///
+ /// 收藏。
+ ///
+ Favorite = 1,
+
+ ///
+ /// 点踩。
+ ///
+ Dislike = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/GroupBuying/Entities/GroupOrder.cs b/src/Domain/TakeoutSaaS.Domain/GroupBuying/Entities/GroupOrder.cs
new file mode 100644
index 0000000..e5412de
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/GroupBuying/Entities/GroupOrder.cs
@@ -0,0 +1,70 @@
+using TakeoutSaaS.Domain.GroupBuying.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.GroupBuying.Entities;
+
+///
+/// 拼单活动。
+///
+public sealed class GroupOrder : MultiTenantEntityBase
+{
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 关联商品或套餐。
+ ///
+ public Guid ProductId { get; set; }
+
+ ///
+ /// 拼单编号。
+ ///
+ public string GroupOrderNo { get; set; } = string.Empty;
+
+ ///
+ /// 团长用户 ID。
+ ///
+ public Guid LeaderUserId { get; set; }
+
+ ///
+ /// 成团需要的人数。
+ ///
+ public int TargetCount { get; set; }
+
+ ///
+ /// 当前已参与人数。
+ ///
+ public int CurrentCount { get; set; }
+
+ ///
+ /// 拼团价格。
+ ///
+ public decimal GroupPrice { get; set; }
+
+ ///
+ /// 开始时间。
+ ///
+ public DateTime StartAt { get; set; }
+
+ ///
+ /// 结束时间。
+ ///
+ public DateTime EndAt { get; set; }
+
+ ///
+ /// 拼团状态。
+ ///
+ public GroupOrderStatus Status { get; set; } = GroupOrderStatus.Open;
+
+ ///
+ /// 成团时间。
+ ///
+ public DateTime? SucceededAt { get; set; }
+
+ ///
+ /// 取消时间。
+ ///
+ public DateTime? CancelledAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/GroupBuying/Entities/GroupParticipant.cs b/src/Domain/TakeoutSaaS.Domain/GroupBuying/Entities/GroupParticipant.cs
new file mode 100644
index 0000000..61e169a
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/GroupBuying/Entities/GroupParticipant.cs
@@ -0,0 +1,35 @@
+using TakeoutSaaS.Domain.GroupBuying.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.GroupBuying.Entities;
+
+///
+/// 拼单参与者。
+///
+public sealed class GroupParticipant : MultiTenantEntityBase
+{
+ ///
+ /// 拼单活动标识。
+ ///
+ public Guid GroupOrderId { get; set; }
+
+ ///
+ /// 对应订单标识。
+ ///
+ public Guid OrderId { get; set; }
+
+ ///
+ /// 用户标识。
+ ///
+ public Guid UserId { get; set; }
+
+ ///
+ /// 参与状态。
+ ///
+ public GroupParticipantStatus Status { get; set; } = GroupParticipantStatus.Joined;
+
+ ///
+ /// 参与时间。
+ ///
+ public DateTime JoinedAt { get; set; } = DateTime.UtcNow;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/GroupBuying/Enums/GroupOrderStatus.cs b/src/Domain/TakeoutSaaS.Domain/GroupBuying/Enums/GroupOrderStatus.cs
new file mode 100644
index 0000000..b5969fd
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/GroupBuying/Enums/GroupOrderStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.GroupBuying.Enums;
+
+///
+/// 拼单状态。
+///
+public enum GroupOrderStatus
+{
+ ///
+ /// 开放中。
+ ///
+ Open = 0,
+
+ ///
+ /// 已成团。
+ ///
+ Succeeded = 1,
+
+ ///
+ /// 已取消。
+ ///
+ Cancelled = 2,
+
+ ///
+ /// 超时失败。
+ ///
+ Failed = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/GroupBuying/Enums/GroupParticipantStatus.cs b/src/Domain/TakeoutSaaS.Domain/GroupBuying/Enums/GroupParticipantStatus.cs
new file mode 100644
index 0000000..7b5f807
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/GroupBuying/Enums/GroupParticipantStatus.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.GroupBuying.Enums;
+
+///
+/// 拼单参与者状态。
+///
+public enum GroupParticipantStatus
+{
+ ///
+ /// 已参团。
+ ///
+ Joined = 0,
+
+ ///
+ /// 因退款或取消退出。
+ ///
+ Exited = 1,
+
+ ///
+ /// 团失败待退款。
+ ///
+ PendingRefund = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Inventory/Entities/InventoryAdjustment.cs b/src/Domain/TakeoutSaaS.Domain/Inventory/Entities/InventoryAdjustment.cs
new file mode 100644
index 0000000..36b7d59
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Inventory/Entities/InventoryAdjustment.cs
@@ -0,0 +1,40 @@
+using TakeoutSaaS.Domain.Inventory.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Inventory.Entities;
+
+///
+/// 库存调整记录。
+///
+public sealed class InventoryAdjustment : MultiTenantEntityBase
+{
+ ///
+ /// 对应的库存记录标识。
+ ///
+ public Guid InventoryItemId { get; set; }
+
+ ///
+ /// 调整类型。
+ ///
+ public InventoryAdjustmentType AdjustmentType { get; set; } = InventoryAdjustmentType.Manual;
+
+ ///
+ /// 调整数量,正数增加,负数减少。
+ ///
+ public int Quantity { get; set; }
+
+ ///
+ /// 原因说明。
+ ///
+ public string? Reason { get; set; }
+
+ ///
+ /// 操作人标识。
+ ///
+ public Guid? OperatorId { get; set; }
+
+ ///
+ /// 发生时间。
+ ///
+ public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Inventory/Entities/InventoryBatch.cs b/src/Domain/TakeoutSaaS.Domain/Inventory/Entities/InventoryBatch.cs
new file mode 100644
index 0000000..8a764b3
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Inventory/Entities/InventoryBatch.cs
@@ -0,0 +1,44 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Inventory.Entities;
+
+///
+/// SKU 批次信息。
+///
+public sealed class InventoryBatch : MultiTenantEntityBase
+{
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// SKU 标识。
+ ///
+ public Guid ProductSkuId { get; set; }
+
+ ///
+ /// 批次编号。
+ ///
+ public string BatchNumber { get; set; } = string.Empty;
+
+ ///
+ /// 生产日期。
+ ///
+ public DateTime? ProductionDate { get; set; }
+
+ ///
+ /// 过期日期。
+ ///
+ public DateTime? ExpireDate { get; set; }
+
+ ///
+ /// 入库数量。
+ ///
+ public int Quantity { get; set; }
+
+ ///
+ /// 剩余数量。
+ ///
+ public int RemainingQuantity { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Inventory/Entities/InventoryItem.cs b/src/Domain/TakeoutSaaS.Domain/Inventory/Entities/InventoryItem.cs
new file mode 100644
index 0000000..6432253
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Inventory/Entities/InventoryItem.cs
@@ -0,0 +1,49 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Inventory.Entities;
+
+///
+/// SKU 在门店的库存信息。
+///
+public sealed class InventoryItem : MultiTenantEntityBase
+{
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// SKU 标识。
+ ///
+ public Guid ProductSkuId { get; set; }
+
+ ///
+ /// 批次编号,可为空表示混批。
+ ///
+ public string? BatchNumber { get; set; }
+
+ ///
+ /// 可用库存。
+ ///
+ public int QuantityOnHand { get; set; }
+
+ ///
+ /// 已锁定库存(订单占用)。
+ ///
+ public int QuantityReserved { get; set; }
+
+ ///
+ /// 安全库存阈值。
+ ///
+ public int? SafetyStock { get; set; }
+
+ ///
+ /// 储位或仓位信息。
+ ///
+ public string? Location { get; set; }
+
+ ///
+ /// 过期日期。
+ ///
+ public DateTime? ExpireDate { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Inventory/Enums/InventoryAdjustmentType.cs b/src/Domain/TakeoutSaaS.Domain/Inventory/Enums/InventoryAdjustmentType.cs
new file mode 100644
index 0000000..58e0913
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Inventory/Enums/InventoryAdjustmentType.cs
@@ -0,0 +1,32 @@
+namespace TakeoutSaaS.Domain.Inventory.Enums;
+
+///
+/// 库存调整类型。
+///
+public enum InventoryAdjustmentType
+{
+ ///
+ /// 手动盘点调整。
+ ///
+ Manual = 0,
+
+ ///
+ /// 采购入库。
+ ///
+ Purchase = 1,
+
+ ///
+ /// 退货回库。
+ ///
+ Return = 2,
+
+ ///
+ /// 报损。
+ ///
+ Damage = 3,
+
+ ///
+ /// 过期销毁。
+ ///
+ Expiration = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberGrowthLog.cs b/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberGrowthLog.cs
new file mode 100644
index 0000000..b06f23f
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberGrowthLog.cs
@@ -0,0 +1,34 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Membership.Entities;
+
+///
+/// 成长值变动日志。
+///
+public sealed class MemberGrowthLog : MultiTenantEntityBase
+{
+ ///
+ /// 会员标识。
+ ///
+ public Guid MemberId { get; set; }
+
+ ///
+ /// 变动数量。
+ ///
+ public int ChangeValue { get; set; }
+
+ ///
+ /// 当前成长值。
+ ///
+ public int CurrentValue { get; set; }
+
+ ///
+ /// 备注。
+ ///
+ public string? Notes { get; set; }
+
+ ///
+ /// 发生时间。
+ ///
+ public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberPointLedger.cs b/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberPointLedger.cs
new file mode 100644
index 0000000..07c4fbe
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberPointLedger.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Membership.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Membership.Entities;
+
+///
+/// 积分变动流水。
+///
+public sealed class MemberPointLedger : MultiTenantEntityBase
+{
+ ///
+ /// 会员标识。
+ ///
+ public Guid MemberId { get; set; }
+
+ ///
+ /// 变动数量,可为负值。
+ ///
+ public int ChangeAmount { get; set; }
+
+ ///
+ /// 变动后余额。
+ ///
+ public int BalanceAfterChange { get; set; }
+
+ ///
+ /// 变动原因。
+ ///
+ public PointChangeReason Reason { get; set; } = PointChangeReason.Purchase;
+
+ ///
+ /// 来源 ID(订单、活动等)。
+ ///
+ public Guid? SourceId { get; set; }
+
+ ///
+ /// 发生时间。
+ ///
+ public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
+
+ ///
+ /// 过期时间(如适用)。
+ ///
+ public DateTime? ExpireAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberProfile.cs b/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberProfile.cs
new file mode 100644
index 0000000..7378ccd
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberProfile.cs
@@ -0,0 +1,60 @@
+using TakeoutSaaS.Domain.Membership.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Membership.Entities;
+
+///
+/// 会员档案。
+///
+public sealed class MemberProfile : MultiTenantEntityBase
+{
+ ///
+ /// 用户标识。
+ ///
+ public Guid UserId { get; set; }
+
+ ///
+ /// 手机号。
+ ///
+ public string Mobile { get; set; } = string.Empty;
+
+ ///
+ /// 昵称。
+ ///
+ public string? Nickname { get; set; }
+
+ ///
+ /// 头像。
+ ///
+ public string? AvatarUrl { get; set; }
+
+ ///
+ /// 当前会员等级 ID。
+ ///
+ public Guid? MemberTierId { get; set; }
+
+ ///
+ /// 会员状态。
+ ///
+ public MemberStatus Status { get; set; } = MemberStatus.Active;
+
+ ///
+ /// 会员积分余额。
+ ///
+ public int PointsBalance { get; set; }
+
+ ///
+ /// 成长值/经验值。
+ ///
+ public int GrowthValue { get; set; }
+
+ ///
+ /// 生日。
+ ///
+ public DateTime? BirthDate { get; set; }
+
+ ///
+ /// 注册时间。
+ ///
+ public DateTime JoinedAt { get; set; } = DateTime.UtcNow;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberTier.cs b/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberTier.cs
new file mode 100644
index 0000000..bd40724
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Membership/Entities/MemberTier.cs
@@ -0,0 +1,29 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Membership.Entities;
+
+///
+/// 会员等级定义。
+///
+public sealed class MemberTier : MultiTenantEntityBase
+{
+ ///
+ /// 等级名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 所需成长值。
+ ///
+ public int RequiredGrowth { get; set; }
+
+ ///
+ /// 等级权益(JSON)。
+ ///
+ public string BenefitsJson { get; set; } = string.Empty;
+
+ ///
+ /// 排序值。
+ ///
+ public int SortOrder { get; set; } = 100;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Membership/Enums/MemberStatus.cs b/src/Domain/TakeoutSaaS.Domain/Membership/Enums/MemberStatus.cs
new file mode 100644
index 0000000..5383e3a
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Membership/Enums/MemberStatus.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Membership.Enums;
+
+///
+/// 会员状态。
+///
+public enum MemberStatus
+{
+ ///
+ /// 正常。
+ ///
+ Active = 0,
+
+ ///
+ /// 已冻结。
+ ///
+ Frozen = 1,
+
+ ///
+ /// 已注销。
+ ///
+ Cancelled = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Membership/Enums/PointChangeReason.cs b/src/Domain/TakeoutSaaS.Domain/Membership/Enums/PointChangeReason.cs
new file mode 100644
index 0000000..61579b2
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Membership/Enums/PointChangeReason.cs
@@ -0,0 +1,32 @@
+namespace TakeoutSaaS.Domain.Membership.Enums;
+
+///
+/// 积分变动原因。
+///
+public enum PointChangeReason
+{
+ ///
+ /// 正常消费获得。
+ ///
+ Purchase = 0,
+
+ ///
+ /// 活动奖励。
+ ///
+ Promotion = 1,
+
+ ///
+ /// 签到或任务。
+ ///
+ Task = 2,
+
+ ///
+ /// 管理员调整。
+ ///
+ Manual = 3,
+
+ ///
+ /// 抵扣消费。
+ ///
+ Redeem = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/Merchant.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/Merchant.cs
new file mode 100644
index 0000000..d05ae41
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/Merchant.cs
@@ -0,0 +1,120 @@
+using TakeoutSaaS.Domain.Merchants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Merchants.Entities;
+
+///
+/// 商户主体信息,承载入驻和资质审核结果。
+///
+public sealed class Merchant : MultiTenantEntityBase
+{
+ ///
+ /// 品牌名称(对外展示)。
+ ///
+ public string BrandName { get; set; } = string.Empty;
+
+ ///
+ /// 品牌简称或别名。
+ ///
+ public string? BrandAlias { get; set; }
+
+ ///
+ /// 品牌 Logo。
+ ///
+ public string? LogoUrl { get; set; }
+
+ ///
+ /// 品牌所属品类,如火锅、咖啡等。
+ ///
+ public string? Category { get; set; }
+
+ ///
+ /// 营业执照号。
+ ///
+ public string? BusinessLicenseNumber { get; set; }
+
+ ///
+ /// 营业执照扫描件地址。
+ ///
+ public string? BusinessLicenseImageUrl { get; set; }
+
+ ///
+ /// 税号/统一社会信用代码。
+ ///
+ public string? TaxNumber { get; set; }
+
+ ///
+ /// 法人或负责人姓名。
+ ///
+ public string? LegalPerson { get; set; }
+
+ ///
+ /// 联系电话。
+ ///
+ public string ContactPhone { get; set; } = string.Empty;
+
+ ///
+ /// 联系邮箱。
+ ///
+ public string? ContactEmail { get; set; }
+
+ ///
+ /// 客服电话。
+ ///
+ public string? ServicePhone { get; set; }
+
+ ///
+ /// 客服邮箱。
+ ///
+ public string? SupportEmail { get; set; }
+
+ ///
+ /// 所在省份。
+ ///
+ public string? Province { get; set; }
+
+ ///
+ /// 所在城市。
+ ///
+ public string? City { get; set; }
+
+ ///
+ /// 所在区县。
+ ///
+ public string? District { get; set; }
+
+ ///
+ /// 详细地址。
+ ///
+ public string? Address { get; set; }
+
+ ///
+ /// 经度信息。
+ ///
+ public double? Longitude { get; set; }
+
+ ///
+ /// 纬度信息。
+ ///
+ public double? Latitude { get; set; }
+
+ ///
+ /// 入驻状态。
+ ///
+ public MerchantStatus Status { get; set; } = MerchantStatus.Pending;
+
+ ///
+ /// 审核备注或驳回原因。
+ ///
+ public string? ReviewRemarks { get; set; }
+
+ ///
+ /// 入驻时间。
+ ///
+ public DateTime? JoinedAt { get; set; }
+
+ ///
+ /// 最近一次审核时间。
+ ///
+ public DateTime? LastReviewedAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/MerchantContract.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/MerchantContract.cs
new file mode 100644
index 0000000..e8a21bb
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/MerchantContract.cs
@@ -0,0 +1,55 @@
+using TakeoutSaaS.Domain.Merchants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Merchants.Entities;
+
+///
+/// 商户合同记录。
+///
+public sealed class MerchantContract : MultiTenantEntityBase
+{
+ ///
+ /// 所属商户标识。
+ ///
+ public Guid MerchantId { get; set; }
+
+ ///
+ /// 合同编号。
+ ///
+ public string ContractNumber { get; set; } = string.Empty;
+
+ ///
+ /// 合同状态。
+ ///
+ public ContractStatus Status { get; set; } = ContractStatus.Draft;
+
+ ///
+ /// 合同开始时间。
+ ///
+ public DateTime StartDate { get; set; }
+
+ ///
+ /// 合同结束时间。
+ ///
+ public DateTime EndDate { get; set; }
+
+ ///
+ /// 合同文件存储地址。
+ ///
+ public string FileUrl { get; set; } = string.Empty;
+
+ ///
+ /// 签署时间。
+ ///
+ public DateTime? SignedAt { get; set; }
+
+ ///
+ /// 终止时间。
+ ///
+ public DateTime? TerminatedAt { get; set; }
+
+ ///
+ /// 终止原因。
+ ///
+ public string? TerminationReason { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/MerchantDocument.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/MerchantDocument.cs
new file mode 100644
index 0000000..572f718
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/MerchantDocument.cs
@@ -0,0 +1,50 @@
+using TakeoutSaaS.Domain.Merchants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Merchants.Entities;
+
+///
+/// 商户提交的资质或证照材料。
+///
+public sealed class MerchantDocument : MultiTenantEntityBase
+{
+ ///
+ /// 所属商户标识。
+ ///
+ public Guid MerchantId { get; set; }
+
+ ///
+ /// 证照类型。
+ ///
+ public MerchantDocumentType DocumentType { get; set; } = MerchantDocumentType.BusinessLicense;
+
+ ///
+ /// 审核状态。
+ ///
+ public MerchantDocumentStatus Status { get; set; } = MerchantDocumentStatus.Pending;
+
+ ///
+ /// 证照文件链接。
+ ///
+ public string FileUrl { get; set; } = string.Empty;
+
+ ///
+ /// 证照编号。
+ ///
+ public string? DocumentNumber { get; set; }
+
+ ///
+ /// 签发日期。
+ ///
+ public DateTime? IssuedAt { get; set; }
+
+ ///
+ /// 到期日期。
+ ///
+ public DateTime? ExpiresAt { get; set; }
+
+ ///
+ /// 审核备注或驳回原因。
+ ///
+ public string? Remarks { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/MerchantStaff.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/MerchantStaff.cs
new file mode 100644
index 0000000..273054a
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Merchants/Entities/MerchantStaff.cs
@@ -0,0 +1,55 @@
+using TakeoutSaaS.Domain.Merchants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Merchants.Entities;
+
+///
+/// 商户员工账号,支持门店维度分配。
+///
+public sealed class MerchantStaff : MultiTenantEntityBase
+{
+ ///
+ /// 所属商户标识。
+ ///
+ public Guid MerchantId { get; set; }
+
+ ///
+ /// 可选的关联门店 ID。
+ ///
+ public Guid? StoreId { get; set; }
+
+ ///
+ /// 员工姓名。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 手机号。
+ ///
+ public string Phone { get; set; } = string.Empty;
+
+ ///
+ /// 邮箱地址。
+ ///
+ public string? Email { get; set; }
+
+ ///
+ /// 登录账号 ID(指向统一身份体系)。
+ ///
+ public Guid? IdentityUserId { get; set; }
+
+ ///
+ /// 员工角色类型。
+ ///
+ public StaffRoleType RoleType { get; set; } = StaffRoleType.FrontDesk;
+
+ ///
+ /// 员工状态。
+ ///
+ public StaffStatus Status { get; set; } = StaffStatus.Active;
+
+ ///
+ /// 自定义权限(JSON)。
+ ///
+ public string? PermissionsJson { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/ContractStatus.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/ContractStatus.cs
new file mode 100644
index 0000000..c38ebff
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/ContractStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Merchants.Enums;
+
+///
+/// 商户合同状态。
+///
+public enum ContractStatus
+{
+ ///
+ /// 草拟中。
+ ///
+ Draft = 0,
+
+ ///
+ /// 已生效。
+ ///
+ Active = 1,
+
+ ///
+ /// 已到期。
+ ///
+ Expired = 2,
+
+ ///
+ /// 已解除。
+ ///
+ Terminated = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/MerchantDocumentStatus.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/MerchantDocumentStatus.cs
new file mode 100644
index 0000000..9d1bf46
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/MerchantDocumentStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Merchants.Enums;
+
+///
+/// 证照审核状态。
+///
+public enum MerchantDocumentStatus
+{
+ ///
+ /// 等待审核。
+ ///
+ Pending = 0,
+
+ ///
+ /// 审核通过。
+ ///
+ Approved = 1,
+
+ ///
+ /// 审核驳回。
+ ///
+ Rejected = 2,
+
+ ///
+ /// 已过期待更新。
+ ///
+ Expired = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/MerchantDocumentType.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/MerchantDocumentType.cs
new file mode 100644
index 0000000..0dffa2d
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/MerchantDocumentType.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Merchants.Enums;
+
+///
+/// 商户证照类型。
+///
+public enum MerchantDocumentType
+{
+ ///
+ /// 营业执照。
+ ///
+ BusinessLicense = 0,
+
+ ///
+ /// 餐饮服务许可证。
+ ///
+ CateringPermit = 1,
+
+ ///
+ /// 税务登记证。
+ ///
+ TaxCertificate = 2,
+
+ ///
+ /// 其他补充资质。
+ ///
+ Other = 99
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/MerchantStatus.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/MerchantStatus.cs
new file mode 100644
index 0000000..6ed8097
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/MerchantStatus.cs
@@ -0,0 +1,12 @@
+namespace TakeoutSaaS.Domain.Merchants.Enums;
+
+///
+/// 商户入驻状态。
+///
+public enum MerchantStatus
+{
+ Pending = 0,
+ Approved = 1,
+ Rejected = 2,
+ Frozen = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/StaffRoleType.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/StaffRoleType.cs
new file mode 100644
index 0000000..c5b3d33
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/StaffRoleType.cs
@@ -0,0 +1,32 @@
+namespace TakeoutSaaS.Domain.Merchants.Enums;
+
+///
+/// 商户员工角色。
+///
+public enum StaffRoleType
+{
+ ///
+ /// 管理员。
+ ///
+ Admin = 0,
+
+ ///
+ /// 前台收银。
+ ///
+ FrontDesk = 1,
+
+ ///
+ /// 后厨制作。
+ ///
+ Kitchen = 2,
+
+ ///
+ /// 配送骑手。
+ ///
+ Courier = 3,
+
+ ///
+ /// 运营人员。
+ ///
+ Operator = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/StaffStatus.cs b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/StaffStatus.cs
new file mode 100644
index 0000000..20ab741
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Merchants/Enums/StaffStatus.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Merchants.Enums;
+
+///
+/// 员工账号状态。
+///
+public enum StaffStatus
+{
+ ///
+ /// 正常在职。
+ ///
+ Active = 0,
+
+ ///
+ /// 停用。
+ ///
+ Disabled = 1,
+
+ ///
+ /// 已离职。
+ ///
+ Resigned = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Navigation/Entities/MapLocation.cs b/src/Domain/TakeoutSaaS.Domain/Navigation/Entities/MapLocation.cs
new file mode 100644
index 0000000..74d9e14
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Navigation/Entities/MapLocation.cs
@@ -0,0 +1,39 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Navigation.Entities;
+
+///
+/// 地图 POI 信息,用于门店定位和推荐。
+///
+public sealed class MapLocation : MultiTenantEntityBase
+{
+ ///
+ /// 关联门店 ID,可空表示独立 POI。
+ ///
+ public Guid? StoreId { get; set; }
+
+ ///
+ /// 名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 地址。
+ ///
+ public string Address { get; set; } = string.Empty;
+
+ ///
+ /// 经度。
+ ///
+ public double Longitude { get; set; }
+
+ ///
+ /// 纬度。
+ ///
+ public double Latitude { get; set; }
+
+ ///
+ /// 打车/导航落点描述。
+ ///
+ public string? Landmark { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Navigation/Entities/NavigationRequest.cs b/src/Domain/TakeoutSaaS.Domain/Navigation/Entities/NavigationRequest.cs
new file mode 100644
index 0000000..284f1a5
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Navigation/Entities/NavigationRequest.cs
@@ -0,0 +1,35 @@
+using TakeoutSaaS.Domain.Navigation.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Navigation.Entities;
+
+///
+/// 用户发起的导航请求日志。
+///
+public sealed class NavigationRequest : MultiTenantEntityBase
+{
+ ///
+ /// 用户 ID。
+ ///
+ public Guid UserId { get; set; }
+
+ ///
+ /// 门店 ID。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 来源通道(小程序、H5 等)。
+ ///
+ public NavigationChannel Channel { get; set; } = NavigationChannel.MiniProgram;
+
+ ///
+ /// 跳转的地图应用。
+ ///
+ public NavigationTargetApp TargetApp { get; set; } = NavigationTargetApp.WechatMap;
+
+ ///
+ /// 请求时间。
+ ///
+ public DateTime RequestedAt { get; set; } = DateTime.UtcNow;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Navigation/Enums/NavigationChannel.cs b/src/Domain/TakeoutSaaS.Domain/Navigation/Enums/NavigationChannel.cs
new file mode 100644
index 0000000..ed60c26
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Navigation/Enums/NavigationChannel.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Navigation.Enums;
+
+///
+/// 导航请求来源渠道。
+///
+public enum NavigationChannel
+{
+ ///
+ /// 小程序。
+ ///
+ MiniProgram = 0,
+
+ ///
+ /// H5/公众号。
+ ///
+ Web = 1,
+
+ ///
+ /// App。
+ ///
+ MobileApp = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Navigation/Enums/NavigationTargetApp.cs b/src/Domain/TakeoutSaaS.Domain/Navigation/Enums/NavigationTargetApp.cs
new file mode 100644
index 0000000..7e9d834
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Navigation/Enums/NavigationTargetApp.cs
@@ -0,0 +1,32 @@
+namespace TakeoutSaaS.Domain.Navigation.Enums;
+
+///
+/// 导航目标应用。
+///
+public enum NavigationTargetApp
+{
+ ///
+ /// 微信地图。
+ ///
+ WechatMap = 0,
+
+ ///
+ /// 腾讯地图。
+ ///
+ Tencent = 1,
+
+ ///
+ /// 高德。
+ ///
+ Amap = 2,
+
+ ///
+ /// 百度地图。
+ ///
+ Baidu = 3,
+
+ ///
+ /// Apple Map。
+ ///
+ Apple = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/CartItem.cs b/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/CartItem.cs
new file mode 100644
index 0000000..d19d659
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/CartItem.cs
@@ -0,0 +1,55 @@
+using TakeoutSaaS.Domain.Ordering.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Ordering.Entities;
+
+///
+/// 购物车条目。
+///
+public sealed class CartItem : MultiTenantEntityBase
+{
+ ///
+ /// 所属购物车标识。
+ ///
+ public Guid ShoppingCartId { get; set; }
+
+ ///
+ /// 商品或 SKU 标识。
+ ///
+ public Guid ProductId { get; set; }
+
+ ///
+ /// SKU 标识。
+ ///
+ public Guid? ProductSkuId { get; set; }
+
+ ///
+ /// 商品名称快照。
+ ///
+ public string ProductName { get; set; } = string.Empty;
+
+ ///
+ /// 单价快照。
+ ///
+ public decimal UnitPrice { get; set; }
+
+ ///
+ /// 数量。
+ ///
+ public int Quantity { get; set; }
+
+ ///
+ /// 自定义备注(口味要求)。
+ ///
+ public string? Remark { get; set; }
+
+ ///
+ /// 状态。
+ ///
+ public CartItemStatus Status { get; set; } = CartItemStatus.Normal;
+
+ ///
+ /// 扩展 JSON(规格、加料选项等)。
+ ///
+ public string? AttributesJson { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/CartItemAddon.cs b/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/CartItemAddon.cs
new file mode 100644
index 0000000..eb99a0d
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/CartItemAddon.cs
@@ -0,0 +1,29 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Ordering.Entities;
+
+///
+/// 购物车条目的加料/附加项。
+///
+public sealed class CartItemAddon : MultiTenantEntityBase
+{
+ ///
+ /// 所属购物车条目。
+ ///
+ public Guid CartItemId { get; set; }
+
+ ///
+ /// 选项名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 附加价格。
+ ///
+ public decimal ExtraPrice { get; set; }
+
+ ///
+ /// 选项 ID(可对应 ProductAddonOption)。
+ ///
+ public Guid? OptionId { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/CheckoutSession.cs b/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/CheckoutSession.cs
new file mode 100644
index 0000000..a3beb7a
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/CheckoutSession.cs
@@ -0,0 +1,40 @@
+using TakeoutSaaS.Domain.Ordering.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Ordering.Entities;
+
+///
+/// 结账会话,记录校验上下文。
+///
+public sealed class CheckoutSession : MultiTenantEntityBase
+{
+ ///
+ /// 用户标识。
+ ///
+ public Guid UserId { get; set; }
+
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 会话 Token。
+ ///
+ public string SessionToken { get; set; } = string.Empty;
+
+ ///
+ /// 会话状态。
+ ///
+ public CheckoutSessionStatus Status { get; set; } = CheckoutSessionStatus.Pending;
+
+ ///
+ /// 校验结果明细 JSON。
+ ///
+ public string ValidationResultJson { get; set; } = string.Empty;
+
+ ///
+ /// 过期时间(UTC)。
+ ///
+ public DateTime ExpiresAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/ShoppingCart.cs b/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/ShoppingCart.cs
new file mode 100644
index 0000000..7928c1e
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Ordering/Entities/ShoppingCart.cs
@@ -0,0 +1,40 @@
+using TakeoutSaaS.Domain.Ordering.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Ordering.Entities;
+
+///
+/// 用户购物车,按租户/门店隔离。
+///
+public sealed class ShoppingCart : MultiTenantEntityBase
+{
+ ///
+ /// 用户标识。
+ ///
+ public Guid UserId { get; set; }
+
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 购物车状态,包含正常/锁定。
+ ///
+ public ShoppingCartStatus Status { get; set; } = ShoppingCartStatus.Active;
+
+ ///
+ /// 桌码或场景标识(扫码点餐)。
+ ///
+ public string? TableContext { get; set; }
+
+ ///
+ /// 履约方式(堂食/自提/配送)缓存。
+ ///
+ public string? DeliveryPreference { get; set; }
+
+ ///
+ /// 最近一次修改时间(UTC)。
+ ///
+ public DateTime LastModifiedAt { get; set; } = DateTime.UtcNow;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Ordering/Enums/CartItemStatus.cs b/src/Domain/TakeoutSaaS.Domain/Ordering/Enums/CartItemStatus.cs
new file mode 100644
index 0000000..f717b97
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Ordering/Enums/CartItemStatus.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Ordering.Enums;
+
+///
+/// 购物车条目状态。
+///
+public enum CartItemStatus
+{
+ ///
+ /// 正常可结算。
+ ///
+ Normal = 0,
+
+ ///
+ /// 不可售(售罄或下架)。
+ ///
+ Unavailable = 1,
+
+ ///
+ /// 已被删除。
+ ///
+ Removed = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Ordering/Enums/CheckoutSessionStatus.cs b/src/Domain/TakeoutSaaS.Domain/Ordering/Enums/CheckoutSessionStatus.cs
new file mode 100644
index 0000000..fbb71c8
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Ordering/Enums/CheckoutSessionStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Ordering.Enums;
+
+///
+/// 结账会话状态。
+///
+public enum CheckoutSessionStatus
+{
+ ///
+ /// 等待用户提交或支付。
+ ///
+ Pending = 0,
+
+ ///
+ /// 校验失败。
+ ///
+ Failed = 1,
+
+ ///
+ /// 已用于创建订单。
+ ///
+ Completed = 2,
+
+ ///
+ /// 超时作废。
+ ///
+ Expired = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Ordering/Enums/ShoppingCartStatus.cs b/src/Domain/TakeoutSaaS.Domain/Ordering/Enums/ShoppingCartStatus.cs
new file mode 100644
index 0000000..88d16af
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Ordering/Enums/ShoppingCartStatus.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Ordering.Enums;
+
+///
+/// 购物车状态。
+///
+public enum ShoppingCartStatus
+{
+ ///
+ /// 可正常使用。
+ ///
+ Active = 0,
+
+ ///
+ /// 已锁定(进行结账中)。
+ ///
+ Locked = 1,
+
+ ///
+ /// 已清空或失效。
+ ///
+ Cleared = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Orders/Entities/Order.cs b/src/Domain/TakeoutSaaS.Domain/Orders/Entities/Order.cs
new file mode 100644
index 0000000..9a1c295
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Orders/Entities/Order.cs
@@ -0,0 +1,111 @@
+using TakeoutSaaS.Domain.Orders.Enums;
+using TakeoutSaaS.Domain.Payments.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Orders.Entities;
+
+///
+/// 交易订单。
+///
+public sealed class Order : MultiTenantEntityBase
+{
+ ///
+ /// 订单号。
+ ///
+ public string OrderNo { get; set; } = string.Empty;
+
+ ///
+ /// 门店。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 下单渠道。
+ ///
+ public OrderChannel Channel { get; set; } = OrderChannel.MiniProgram;
+
+ ///
+ /// 履约类型。
+ ///
+ public DeliveryType DeliveryType { get; set; } = DeliveryType.DineIn;
+
+ ///
+ /// 当前状态。
+ ///
+ public OrderStatus Status { get; set; } = OrderStatus.PendingPayment;
+
+ ///
+ /// 支付状态。
+ ///
+ public PaymentStatus PaymentStatus { get; set; } = PaymentStatus.Unpaid;
+
+ ///
+ /// 顾客姓名。
+ ///
+ public string? CustomerName { get; set; }
+
+ ///
+ /// 顾客手机号。
+ ///
+ public string? CustomerPhone { get; set; }
+
+ ///
+ /// 就餐桌号。
+ ///
+ public string? TableNo { get; set; }
+
+ ///
+ /// 排队号(如有)。
+ ///
+ public string? QueueNumber { get; set; }
+
+ ///
+ /// 预约 ID。
+ ///
+ public Guid? ReservationId { get; set; }
+
+ ///
+ /// 商品总额。
+ ///
+ public decimal ItemsAmount { get; set; }
+
+ ///
+ /// 优惠金额。
+ ///
+ public decimal DiscountAmount { get; set; }
+
+ ///
+ /// 应付金额。
+ ///
+ public decimal PayableAmount { get; set; }
+
+ ///
+ /// 实付金额。
+ ///
+ public decimal PaidAmount { get; set; }
+
+ ///
+ /// 支付时间。
+ ///
+ public DateTime? PaidAt { get; set; }
+
+ ///
+ /// 完成时间。
+ ///
+ public DateTime? FinishedAt { get; set; }
+
+ ///
+ /// 取消时间。
+ ///
+ public DateTime? CancelledAt { get; set; }
+
+ ///
+ /// 取消原因。
+ ///
+ public string? CancelReason { get; set; }
+
+ ///
+ /// 备注。
+ ///
+ public string? Remark { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Orders/Entities/OrderItem.cs b/src/Domain/TakeoutSaaS.Domain/Orders/Entities/OrderItem.cs
new file mode 100644
index 0000000..83681ca
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Orders/Entities/OrderItem.cs
@@ -0,0 +1,59 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Orders.Entities;
+
+///
+/// 订单明细。
+///
+public sealed class OrderItem : MultiTenantEntityBase
+{
+ ///
+ /// 订单 ID。
+ ///
+ public Guid OrderId { get; set; }
+
+ ///
+ /// 商品 ID。
+ ///
+ public Guid ProductId { get; set; }
+
+ ///
+ /// 商品名称。
+ ///
+ public string ProductName { get; set; } = string.Empty;
+
+ ///
+ /// SKU/规格描述。
+ ///
+ public string? SkuName { get; set; }
+
+ ///
+ /// 单位。
+ ///
+ public string? Unit { get; set; }
+
+ ///
+ /// 数量。
+ ///
+ public int Quantity { get; set; }
+
+ ///
+ /// 单价。
+ ///
+ public decimal UnitPrice { get; set; }
+
+ ///
+ /// 折扣金额。
+ ///
+ public decimal DiscountAmount { get; set; }
+
+ ///
+ /// 小计。
+ ///
+ public decimal SubTotal { get; set; }
+
+ ///
+ /// 自定义属性 JSON。
+ ///
+ public string? AttributesJson { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Orders/Entities/OrderStatusHistory.cs b/src/Domain/TakeoutSaaS.Domain/Orders/Entities/OrderStatusHistory.cs
new file mode 100644
index 0000000..26823f2
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Orders/Entities/OrderStatusHistory.cs
@@ -0,0 +1,35 @@
+using TakeoutSaaS.Domain.Orders.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Orders.Entities;
+
+///
+/// 订单状态流转记录。
+///
+public sealed class OrderStatusHistory : MultiTenantEntityBase
+{
+ ///
+ /// 订单标识。
+ ///
+ public Guid OrderId { get; set; }
+
+ ///
+ /// 变更后的状态。
+ ///
+ public OrderStatus Status { get; set; }
+
+ ///
+ /// 操作人标识(可为空表示系统)。
+ ///
+ public Guid? OperatorId { get; set; }
+
+ ///
+ /// 备注信息。
+ ///
+ public string? Notes { get; set; }
+
+ ///
+ /// 发生时间。
+ ///
+ public DateTime OccurredAt { get; set; } = DateTime.UtcNow;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Orders/Entities/RefundRequest.cs b/src/Domain/TakeoutSaaS.Domain/Orders/Entities/RefundRequest.cs
new file mode 100644
index 0000000..d18d4ab
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Orders/Entities/RefundRequest.cs
@@ -0,0 +1,50 @@
+using TakeoutSaaS.Domain.Orders.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Orders.Entities;
+
+///
+/// 售后/退款申请。
+///
+public sealed class RefundRequest : MultiTenantEntityBase
+{
+ ///
+ /// 关联订单标识。
+ ///
+ public Guid OrderId { get; set; }
+
+ ///
+ /// 退款单号。
+ ///
+ public string RefundNo { get; set; } = string.Empty;
+
+ ///
+ /// 申请金额。
+ ///
+ public decimal Amount { get; set; }
+
+ ///
+ /// 申请原因。
+ ///
+ public string Reason { get; set; } = string.Empty;
+
+ ///
+ /// 退款状态。
+ ///
+ public RefundStatus Status { get; set; } = RefundStatus.Pending;
+
+ ///
+ /// 用户提交时间。
+ ///
+ public DateTime RequestedAt { get; set; } = DateTime.UtcNow;
+
+ ///
+ /// 审核完成时间。
+ ///
+ public DateTime? ProcessedAt { get; set; }
+
+ ///
+ /// 审核备注。
+ ///
+ public string? ReviewNotes { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Orders/Enums/DeliveryType.cs b/src/Domain/TakeoutSaaS.Domain/Orders/Enums/DeliveryType.cs
new file mode 100644
index 0000000..4a7249f
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Orders/Enums/DeliveryType.cs
@@ -0,0 +1,11 @@
+namespace TakeoutSaaS.Domain.Orders.Enums;
+
+///
+/// 履约/交付方式。
+///
+public enum DeliveryType
+{
+ DineIn = 0,
+ Pickup = 1,
+ Delivery = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Orders/Enums/OrderChannel.cs b/src/Domain/TakeoutSaaS.Domain/Orders/Enums/OrderChannel.cs
new file mode 100644
index 0000000..6908ac6
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Orders/Enums/OrderChannel.cs
@@ -0,0 +1,14 @@
+namespace TakeoutSaaS.Domain.Orders.Enums;
+
+///
+/// 下单渠道。
+///
+public enum OrderChannel
+{
+ Unknown = 0,
+ MiniProgram = 1,
+ ScanToOrder = 2,
+ StaffConsole = 3,
+ PhoneReservation = 4,
+ ThirdPartyDelivery = 5
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Orders/Enums/OrderStatus.cs b/src/Domain/TakeoutSaaS.Domain/Orders/Enums/OrderStatus.cs
new file mode 100644
index 0000000..4132e46
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Orders/Enums/OrderStatus.cs
@@ -0,0 +1,14 @@
+namespace TakeoutSaaS.Domain.Orders.Enums;
+
+///
+/// 订单状态。
+///
+public enum OrderStatus
+{
+ PendingPayment = 0,
+ AwaitingPreparation = 1,
+ InProgress = 2,
+ Ready = 3,
+ Completed = 4,
+ Cancelled = 5
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Orders/Enums/RefundStatus.cs b/src/Domain/TakeoutSaaS.Domain/Orders/Enums/RefundStatus.cs
new file mode 100644
index 0000000..3f2dc41
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Orders/Enums/RefundStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Orders.Enums;
+
+///
+/// 退款申请状态。
+///
+public enum RefundStatus
+{
+ ///
+ /// 等待审核。
+ ///
+ Pending = 0,
+
+ ///
+ /// 审核通过,待原路退款。
+ ///
+ Approved = 1,
+
+ ///
+ /// 已拒绝。
+ ///
+ Rejected = 2,
+
+ ///
+ /// 已完成退款。
+ ///
+ Refunded = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Payments/Entities/PaymentRecord.cs b/src/Domain/TakeoutSaaS.Domain/Payments/Entities/PaymentRecord.cs
new file mode 100644
index 0000000..2d0923f
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Payments/Entities/PaymentRecord.cs
@@ -0,0 +1,55 @@
+using TakeoutSaaS.Domain.Payments.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Payments.Entities;
+
+///
+/// 支付流水。
+///
+public sealed class PaymentRecord : MultiTenantEntityBase
+{
+ ///
+ /// 关联订单。
+ ///
+ public Guid OrderId { get; set; }
+
+ ///
+ /// 支付方式。
+ ///
+ public PaymentMethod Method { get; set; } = PaymentMethod.Unknown;
+
+ ///
+ /// 支付状态。
+ ///
+ public PaymentStatus Status { get; set; } = PaymentStatus.Unpaid;
+
+ ///
+ /// 支付金额。
+ ///
+ public decimal Amount { get; set; }
+
+ ///
+ /// 平台交易号。
+ ///
+ public string? TradeNo { get; set; }
+
+ ///
+ /// 第三方渠道单号。
+ ///
+ public string? ChannelTransactionId { get; set; }
+
+ ///
+ /// 支付完成时间。
+ ///
+ public DateTime? PaidAt { get; set; }
+
+ ///
+ /// 错误/备注。
+ ///
+ public string? Remark { get; set; }
+
+ ///
+ /// 原始回调内容。
+ ///
+ public string? Payload { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Payments/Entities/PaymentRefundRecord.cs b/src/Domain/TakeoutSaaS.Domain/Payments/Entities/PaymentRefundRecord.cs
new file mode 100644
index 0000000..9e91973
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Payments/Entities/PaymentRefundRecord.cs
@@ -0,0 +1,50 @@
+using TakeoutSaaS.Domain.Payments.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Payments.Entities;
+
+///
+/// 支付渠道退款流水。
+///
+public sealed class PaymentRefundRecord : MultiTenantEntityBase
+{
+ ///
+ /// 原支付记录标识。
+ ///
+ public Guid PaymentRecordId { get; set; }
+
+ ///
+ /// 关联订单标识。
+ ///
+ public Guid OrderId { get; set; }
+
+ ///
+ /// 退款金额。
+ ///
+ public decimal Amount { get; set; }
+
+ ///
+ /// 渠道退款流水号。
+ ///
+ public string? ChannelRefundId { get; set; }
+
+ ///
+ /// 退款状态。
+ ///
+ public PaymentRefundStatus Status { get; set; } = PaymentRefundStatus.Pending;
+
+ ///
+ /// 退款请求时间。
+ ///
+ public DateTime RequestedAt { get; set; } = DateTime.UtcNow;
+
+ ///
+ /// 完成时间。
+ ///
+ public DateTime? CompletedAt { get; set; }
+
+ ///
+ /// 渠道返回的原始数据 JSON。
+ ///
+ public string? Payload { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Payments/Enums/PaymentMethod.cs b/src/Domain/TakeoutSaaS.Domain/Payments/Enums/PaymentMethod.cs
new file mode 100644
index 0000000..2453be2
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Payments/Enums/PaymentMethod.cs
@@ -0,0 +1,14 @@
+namespace TakeoutSaaS.Domain.Payments.Enums;
+
+///
+/// 支付方式。
+///
+public enum PaymentMethod
+{
+ Unknown = 0,
+ WeChatPay = 1,
+ Alipay = 2,
+ Cash = 3,
+ Card = 4,
+ Balance = 5
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Payments/Enums/PaymentRefundStatus.cs b/src/Domain/TakeoutSaaS.Domain/Payments/Enums/PaymentRefundStatus.cs
new file mode 100644
index 0000000..0ee24db
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Payments/Enums/PaymentRefundStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Payments.Enums;
+
+///
+/// 支付退款状态。
+///
+public enum PaymentRefundStatus
+{
+ ///
+ /// 已提交至渠道。
+ ///
+ Pending = 0,
+
+ ///
+ /// 退款成功。
+ ///
+ Succeeded = 1,
+
+ ///
+ /// 退款失败。
+ ///
+ Failed = 2,
+
+ ///
+ /// 渠道处理中。
+ ///
+ Processing = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Payments/Enums/PaymentStatus.cs b/src/Domain/TakeoutSaaS.Domain/Payments/Enums/PaymentStatus.cs
new file mode 100644
index 0000000..6b5912a
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Payments/Enums/PaymentStatus.cs
@@ -0,0 +1,13 @@
+namespace TakeoutSaaS.Domain.Payments.Enums;
+
+///
+/// 支付记录状态。
+///
+public enum PaymentStatus
+{
+ Unpaid = 0,
+ Paying = 1,
+ Paid = 2,
+ Failed = 3,
+ Refunded = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Entities/Product.cs b/src/Domain/TakeoutSaaS.Domain/Products/Entities/Product.cs
new file mode 100644
index 0000000..c9617e2
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Entities/Product.cs
@@ -0,0 +1,100 @@
+using TakeoutSaaS.Domain.Products.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Products.Entities;
+
+///
+/// 商品(SPU)信息。
+///
+public sealed class Product : MultiTenantEntityBase
+{
+ ///
+ /// 所属门店。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 所属分类。
+ ///
+ public Guid CategoryId { get; set; }
+
+ ///
+ /// 商品编码。
+ ///
+ public string SpuCode { get; set; } = string.Empty;
+
+ ///
+ /// 商品名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 副标题/卖点。
+ ///
+ public string? Subtitle { get; set; }
+
+ ///
+ /// 售卖单位(份/杯等)。
+ ///
+ public string? Unit { get; set; }
+
+ ///
+ /// 现价。
+ ///
+ public decimal Price { get; set; }
+
+ ///
+ /// 原价。
+ ///
+ public decimal? OriginalPrice { get; set; }
+
+ ///
+ /// 库存数量(可选)。
+ ///
+ public int? StockQuantity { get; set; }
+
+ ///
+ /// 最大每单限购。
+ ///
+ public int? MaxQuantityPerOrder { get; set; }
+
+ ///
+ /// 商品状态。
+ ///
+ public ProductStatus Status { get; set; } = ProductStatus.Draft;
+
+ ///
+ /// 主图。
+ ///
+ public string? CoverImage { get; set; }
+
+ ///
+ /// Gallery 图片逗号分隔。
+ ///
+ public string? GalleryImages { get; set; }
+
+ ///
+ /// 商品描述。
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// 支持堂食。
+ ///
+ public bool EnableDineIn { get; set; } = true;
+
+ ///
+ /// 支持自提。
+ ///
+ public bool EnablePickup { get; set; } = true;
+
+ ///
+ /// 支持配送。
+ ///
+ public bool EnableDelivery { get; set; } = true;
+
+ ///
+ /// 是否热门推荐。
+ ///
+ public bool IsFeatured { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAddonGroup.cs b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAddonGroup.cs
new file mode 100644
index 0000000..dfd8dd5
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAddonGroup.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Products.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Products.Entities;
+
+///
+/// 加料/做法分组。
+///
+public sealed class ProductAddonGroup : MultiTenantEntityBase
+{
+ ///
+ /// 所属商品。
+ ///
+ public Guid ProductId { get; set; }
+
+ ///
+ /// 分组名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 选择类型。
+ ///
+ public AddonSelectionType SelectionType { get; set; } = AddonSelectionType.Single;
+
+ ///
+ /// 最小选择数量。
+ ///
+ public int? MinSelect { get; set; }
+
+ ///
+ /// 最大选择数量。
+ ///
+ public int? MaxSelect { get; set; }
+
+ ///
+ /// 是否必选。
+ ///
+ public bool IsRequired { get; set; }
+
+ ///
+ /// 排序值。
+ ///
+ public int SortOrder { get; set; } = 100;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAddonOption.cs b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAddonOption.cs
new file mode 100644
index 0000000..3d27185
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAddonOption.cs
@@ -0,0 +1,34 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Products.Entities;
+
+///
+/// 加料选项。
+///
+public sealed class ProductAddonOption : MultiTenantEntityBase
+{
+ ///
+ /// 所属加料分组。
+ ///
+ public Guid AddonGroupId { get; set; }
+
+ ///
+ /// 选项名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 附加价格。
+ ///
+ public decimal? ExtraPrice { get; set; }
+
+ ///
+ /// 是否默认选项。
+ ///
+ public bool IsDefault { get; set; }
+
+ ///
+ /// 排序。
+ ///
+ public int SortOrder { get; set; } = 100;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAttributeGroup.cs b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAttributeGroup.cs
new file mode 100644
index 0000000..62a9af1
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAttributeGroup.cs
@@ -0,0 +1,35 @@
+using TakeoutSaaS.Domain.Products.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Products.Entities;
+
+///
+/// 商品规格/属性分组。
+///
+public sealed class ProductAttributeGroup : MultiTenantEntityBase
+{
+ ///
+ /// 关联门店,可为空表示所有门店共享。
+ ///
+ public Guid? StoreId { get; set; }
+
+ ///
+ /// 分组名称,例如“辣度”“份量”。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 选择类型(单选/多选)。
+ ///
+ public AttributeSelectionType SelectionType { get; set; } = AttributeSelectionType.Single;
+
+ ///
+ /// 是否必选。
+ ///
+ public bool IsRequired { get; set; }
+
+ ///
+ /// 显示排序。
+ ///
+ public int SortOrder { get; set; } = 100;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAttributeOption.cs b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAttributeOption.cs
new file mode 100644
index 0000000..80332d3
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductAttributeOption.cs
@@ -0,0 +1,34 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Products.Entities;
+
+///
+/// 商品规格选项。
+///
+public sealed class ProductAttributeOption : MultiTenantEntityBase
+{
+ ///
+ /// 所属规格组。
+ ///
+ public Guid AttributeGroupId { get; set; }
+
+ ///
+ /// 选项名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 附加价格。
+ ///
+ public decimal? ExtraPrice { get; set; }
+
+ ///
+ /// 排序。
+ ///
+ public int SortOrder { get; set; } = 100;
+
+ ///
+ /// 是否默认选中。
+ ///
+ public bool IsDefault { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductCategory.cs b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductCategory.cs
new file mode 100644
index 0000000..4d055a2
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductCategory.cs
@@ -0,0 +1,34 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Products.Entities;
+
+///
+/// 商品分类。
+///
+public sealed class ProductCategory : MultiTenantEntityBase
+{
+ ///
+ /// 所属门店。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 分类名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 分类描述。
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// 排序值。
+ ///
+ public int SortOrder { get; set; } = 100;
+
+ ///
+ /// 是否启用。
+ ///
+ public bool IsEnabled { get; set; } = true;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductMediaAsset.cs b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductMediaAsset.cs
new file mode 100644
index 0000000..c07ef44
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductMediaAsset.cs
@@ -0,0 +1,35 @@
+using TakeoutSaaS.Domain.Products.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Products.Entities;
+
+///
+/// 商品媒资素材。
+///
+public sealed class ProductMediaAsset : MultiTenantEntityBase
+{
+ ///
+ /// 商品标识。
+ ///
+ public Guid ProductId { get; set; }
+
+ ///
+ /// 媒体类型。
+ ///
+ public MediaAssetType MediaType { get; set; } = MediaAssetType.Image;
+
+ ///
+ /// 媒资链接。
+ ///
+ public string Url { get; set; } = string.Empty;
+
+ ///
+ /// 描述或标题。
+ ///
+ public string? Caption { get; set; }
+
+ ///
+ /// 排序。
+ ///
+ public int SortOrder { get; set; } = 100;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductPricingRule.cs b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductPricingRule.cs
new file mode 100644
index 0000000..bace92a
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductPricingRule.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Products.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Products.Entities;
+
+///
+/// 商品价格策略,支持会员价/时段价等。
+///
+public sealed class ProductPricingRule : MultiTenantEntityBase
+{
+ ///
+ /// 所属商品。
+ ///
+ public Guid ProductId { get; set; }
+
+ ///
+ /// 策略类型。
+ ///
+ public PricingRuleType RuleType { get; set; } = PricingRuleType.Member;
+
+ ///
+ /// 条件描述(JSON),如会员等级、渠道等。
+ ///
+ public string ConditionsJson { get; set; } = string.Empty;
+
+ ///
+ /// 特殊价格。
+ ///
+ public decimal Price { get; set; }
+
+ ///
+ /// 生效开始时间。
+ ///
+ public DateTime? StartTime { get; set; }
+
+ ///
+ /// 生效结束时间。
+ ///
+ public DateTime? EndTime { get; set; }
+
+ ///
+ /// 生效星期(JSON 数组)。
+ ///
+ public string? WeekdaysJson { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductSku.cs b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductSku.cs
new file mode 100644
index 0000000..1c1e6ce
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Entities/ProductSku.cs
@@ -0,0 +1,49 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Products.Entities;
+
+///
+/// 商品 SKU,记录具体规格组合价格。
+///
+public sealed class ProductSku : MultiTenantEntityBase
+{
+ ///
+ /// 所属商品标识。
+ ///
+ public Guid ProductId { get; set; }
+
+ ///
+ /// SKU 编码。
+ ///
+ public string SkuCode { get; set; } = string.Empty;
+
+ ///
+ /// 条形码。
+ ///
+ public string? Barcode { get; set; }
+
+ ///
+ /// 售价。
+ ///
+ public decimal Price { get; set; }
+
+ ///
+ /// 原价。
+ ///
+ public decimal? OriginalPrice { get; set; }
+
+ ///
+ /// 可售库存。
+ ///
+ public int? StockQuantity { get; set; }
+
+ ///
+ /// 重量(千克)。
+ ///
+ public decimal? Weight { get; set; }
+
+ ///
+ /// 规格属性 JSON(记录选项 ID)。
+ ///
+ public string AttributesJson { get; set; } = string.Empty;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Enums/AddonSelectionType.cs b/src/Domain/TakeoutSaaS.Domain/Products/Enums/AddonSelectionType.cs
new file mode 100644
index 0000000..65bea66
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Enums/AddonSelectionType.cs
@@ -0,0 +1,17 @@
+namespace TakeoutSaaS.Domain.Products.Enums;
+
+///
+/// 加料选择类型。
+///
+public enum AddonSelectionType
+{
+ ///
+ /// 单选。
+ ///
+ Single = 0,
+
+ ///
+ /// 多选。
+ ///
+ Multiple = 1
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Enums/AttributeSelectionType.cs b/src/Domain/TakeoutSaaS.Domain/Products/Enums/AttributeSelectionType.cs
new file mode 100644
index 0000000..9b5f69d
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Enums/AttributeSelectionType.cs
@@ -0,0 +1,17 @@
+namespace TakeoutSaaS.Domain.Products.Enums;
+
+///
+/// 规格/加料的选择方式。
+///
+public enum AttributeSelectionType
+{
+ ///
+ /// 单选。
+ ///
+ Single = 0,
+
+ ///
+ /// 多选。
+ ///
+ Multiple = 1
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Enums/MediaAssetType.cs b/src/Domain/TakeoutSaaS.Domain/Products/Enums/MediaAssetType.cs
new file mode 100644
index 0000000..27a0f2d
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Enums/MediaAssetType.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Products.Enums;
+
+///
+/// 商品媒资类型。
+///
+public enum MediaAssetType
+{
+ ///
+ /// 图片。
+ ///
+ Image = 0,
+
+ ///
+ /// 视频。
+ ///
+ Video = 1,
+
+ ///
+ /// PDF 或说明文档。
+ ///
+ Document = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Enums/PricingRuleType.cs b/src/Domain/TakeoutSaaS.Domain/Products/Enums/PricingRuleType.cs
new file mode 100644
index 0000000..613283a
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Enums/PricingRuleType.cs
@@ -0,0 +1,32 @@
+namespace TakeoutSaaS.Domain.Products.Enums;
+
+///
+/// 价格策略类型。
+///
+public enum PricingRuleType
+{
+ ///
+ /// 会员价格。
+ ///
+ Member = 0,
+
+ ///
+ /// 不同门店价格。
+ ///
+ Store = 1,
+
+ ///
+ /// 时间段价格。
+ ///
+ TimePeriod = 2,
+
+ ///
+ /// 区域价格。
+ ///
+ Region = 3,
+
+ ///
+ /// 活动价格。
+ ///
+ Promotion = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Products/Enums/ProductStatus.cs b/src/Domain/TakeoutSaaS.Domain/Products/Enums/ProductStatus.cs
new file mode 100644
index 0000000..8678fcc
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Products/Enums/ProductStatus.cs
@@ -0,0 +1,12 @@
+namespace TakeoutSaaS.Domain.Products.Enums;
+
+///
+/// 商品状态。
+///
+public enum ProductStatus
+{
+ Draft = 0,
+ OnSale = 1,
+ OffShelf = 2,
+ Archived = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Queues/Entities/QueueTicket.cs b/src/Domain/TakeoutSaaS.Domain/Queues/Entities/QueueTicket.cs
new file mode 100644
index 0000000..f09c94e
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Queues/Entities/QueueTicket.cs
@@ -0,0 +1,52 @@
+using TakeoutSaaS.Domain.Queues.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Queues.Entities;
+
+///
+/// 排队叫号。
+///
+public sealed class QueueTicket : MultiTenantEntityBase
+{
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 排队编号。
+ ///
+ public string TicketNumber { get; set; } = string.Empty;
+
+ ///
+ /// 就餐人数。
+ ///
+ public int PartySize { get; set; }
+
+ ///
+ /// 状态。
+ ///
+ public QueueStatus Status { get; set; } = QueueStatus.Waiting;
+
+ ///
+ /// 预计等待分钟。
+ ///
+ public int? EstimatedWaitMinutes { get; set; }
+
+ ///
+ /// 叫号时间。
+ ///
+ public DateTime? CalledAt { get; set; }
+
+ ///
+ /// 过号时间。
+ ///
+ public DateTime? ExpiredAt { get; set; }
+
+ ///
+ /// 取消时间。
+ ///
+ public DateTime? CancelledAt { get; set; }
+
+ ///
+ /// 备注。
+ ///
+ public string? Remark { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Queues/Enums/QueueStatus.cs b/src/Domain/TakeoutSaaS.Domain/Queues/Enums/QueueStatus.cs
new file mode 100644
index 0000000..f217a70
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Queues/Enums/QueueStatus.cs
@@ -0,0 +1,13 @@
+namespace TakeoutSaaS.Domain.Queues.Enums;
+
+///
+/// 排队状态。
+///
+public enum QueueStatus
+{
+ Waiting = 0,
+ Calling = 1,
+ Completed = 2,
+ Cancelled = 3,
+ Expired = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Reservations/Entities/Reservation.cs b/src/Domain/TakeoutSaaS.Domain/Reservations/Entities/Reservation.cs
new file mode 100644
index 0000000..3214ee3
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Reservations/Entities/Reservation.cs
@@ -0,0 +1,70 @@
+using TakeoutSaaS.Domain.Reservations.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Reservations.Entities;
+
+///
+/// 预约/预订记录。
+///
+public sealed class Reservation : MultiTenantEntityBase
+{
+ ///
+ /// 门店。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 预约号。
+ ///
+ public string ReservationNo { get; set; } = string.Empty;
+
+ ///
+ /// 客户姓名。
+ ///
+ public string CustomerName { get; set; } = string.Empty;
+
+ ///
+ /// 联系电话。
+ ///
+ public string CustomerPhone { get; set; } = string.Empty;
+
+ ///
+ /// 用餐人数。
+ ///
+ public int PeopleCount { get; set; }
+
+ ///
+ /// 预约时间(UTC)。
+ ///
+ public DateTime ReservationTime { get; set; }
+
+ ///
+ /// 状态。
+ ///
+ public ReservationStatus Status { get; set; } = ReservationStatus.Pending;
+
+ ///
+ /// 桌型/标签。
+ ///
+ public string? TablePreference { get; set; }
+
+ ///
+ /// 备注。
+ ///
+ public string? Remark { get; set; }
+
+ ///
+ /// 核销码/到店码。
+ ///
+ public string? CheckInCode { get; set; }
+
+ ///
+ /// 实际签到时间。
+ ///
+ public DateTime? CheckedInAt { get; set; }
+
+ ///
+ /// 取消时间。
+ ///
+ public DateTime? CancelledAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Reservations/Enums/ReservationStatus.cs b/src/Domain/TakeoutSaaS.Domain/Reservations/Enums/ReservationStatus.cs
new file mode 100644
index 0000000..2bf53a3
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Reservations/Enums/ReservationStatus.cs
@@ -0,0 +1,13 @@
+namespace TakeoutSaaS.Domain.Reservations.Enums;
+
+///
+/// 预约状态。
+///
+public enum ReservationStatus
+{
+ Pending = 0,
+ Confirmed = 1,
+ CheckedIn = 2,
+ Cancelled = 3,
+ NoShow = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Entities/Store.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/Store.cs
new file mode 100644
index 0000000..5c82a91
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/Store.cs
@@ -0,0 +1,130 @@
+using TakeoutSaaS.Domain.Stores.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Stores.Entities;
+
+///
+/// 门店信息,承载营业配置与能力。
+///
+public sealed class Store : MultiTenantEntityBase
+{
+ ///
+ /// 所属商户标识。
+ ///
+ public Guid MerchantId { get; set; }
+
+ ///
+ /// 门店编码,便于扫码及外部对接。
+ ///
+ public string Code { get; set; } = string.Empty;
+
+ ///
+ /// 门店名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 联系电话。
+ ///
+ public string? Phone { get; set; }
+
+ ///
+ /// 门店负责人姓名。
+ ///
+ public string? ManagerName { get; set; }
+
+ ///
+ /// 门店当前运营状态。
+ ///
+ public StoreStatus Status { get; set; } = StoreStatus.Closed;
+
+ ///
+ /// 所在国家或地区。
+ ///
+ public string? Country { get; set; }
+
+ ///
+ /// 所在省份。
+ ///
+ public string? Province { get; set; }
+
+ ///
+ /// 所在城市。
+ ///
+ public string? City { get; set; }
+
+ ///
+ /// 区县信息。
+ ///
+ public string? District { get; set; }
+
+ ///
+ /// 详细地址。
+ ///
+ public string? Address { get; set; }
+
+ ///
+ /// 高德/腾讯地图经度。
+ ///
+ public double? Longitude { get; set; }
+
+ ///
+ /// 纬度。
+ ///
+ public double? Latitude { get; set; }
+
+ ///
+ /// 门店描述或公告。
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// 门店营业时段描述(备用字符串)。
+ ///
+ public string? BusinessHours { get; set; }
+
+ ///
+ /// 是否支持堂食。
+ ///
+ public bool SupportsDineIn { get; set; } = true;
+
+ ///
+ /// 是否支持自提。
+ ///
+ public bool SupportsPickup { get; set; } = true;
+
+ ///
+ /// 是否支持配送。
+ ///
+ public bool SupportsDelivery { get; set; } = true;
+
+ ///
+ /// 支持预约。
+ ///
+ public bool SupportsReservation { get; set; }
+
+ ///
+ /// 支持排队叫号。
+ ///
+ public bool SupportsQueueing { get; set; }
+
+ ///
+ /// 默认配送半径(公里)。
+ ///
+ public decimal DeliveryRadiusKm { get; set; } = 3m;
+
+ ///
+ /// 门店公告。
+ ///
+ public string? Announcement { get; set; }
+
+ ///
+ /// 门店标签(逗号分隔)。
+ ///
+ public string? Tags { get; set; }
+
+ ///
+ /// 门店海报。
+ ///
+ public string? CoverImageUrl { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreBusinessHour.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreBusinessHour.cs
new file mode 100644
index 0000000..a85b0d8
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreBusinessHour.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Stores.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Stores.Entities;
+
+///
+/// 门店营业时段配置。
+///
+public sealed class StoreBusinessHour : MultiTenantEntityBase
+{
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 星期几,0 表示周日。
+ ///
+ public DayOfWeek DayOfWeek { get; set; }
+
+ ///
+ /// 时段类型(正常营业、休息、预约等)。
+ ///
+ public BusinessHourType HourType { get; set; } = BusinessHourType.Normal;
+
+ ///
+ /// 开始时间(本地时间)。
+ ///
+ public TimeSpan StartTime { get; set; }
+
+ ///
+ /// 结束时间(本地时间)。
+ ///
+ public TimeSpan EndTime { get; set; }
+
+ ///
+ /// 最大接待容量或单量限制。
+ ///
+ public int? CapacityLimit { get; set; }
+
+ ///
+ /// 备注。
+ ///
+ public string? Notes { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreDeliveryZone.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreDeliveryZone.cs
new file mode 100644
index 0000000..e067e1f
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreDeliveryZone.cs
@@ -0,0 +1,39 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Stores.Entities;
+
+///
+/// 门店配送范围配置。
+///
+public sealed class StoreDeliveryZone : MultiTenantEntityBase
+{
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 区域名称。
+ ///
+ public string ZoneName { get; set; } = string.Empty;
+
+ ///
+ /// GeoJSON 表示的多边形范围。
+ ///
+ public string PolygonGeoJson { get; set; } = string.Empty;
+
+ ///
+ /// 起送价。
+ ///
+ public decimal? MinimumOrderAmount { get; set; }
+
+ ///
+ /// 配送费。
+ ///
+ public decimal? DeliveryFee { get; set; }
+
+ ///
+ /// 预计送达分钟。
+ ///
+ public int? EstimatedMinutes { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreEmployeeShift.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreEmployeeShift.cs
new file mode 100644
index 0000000..a1bc39a
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreEmployeeShift.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Merchants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Stores.Entities;
+
+///
+/// 门店员工排班记录。
+///
+public sealed class StoreEmployeeShift : MultiTenantEntityBase
+{
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 员工标识。
+ ///
+ public Guid StaffId { get; set; }
+
+ ///
+ /// 班次日期。
+ ///
+ public DateTime ShiftDate { get; set; }
+
+ ///
+ /// 开始时间。
+ ///
+ public TimeSpan StartTime { get; set; }
+
+ ///
+ /// 结束时间。
+ ///
+ public TimeSpan EndTime { get; set; }
+
+ ///
+ /// 排班角色。
+ ///
+ public StaffRoleType RoleType { get; set; } = StaffRoleType.FrontDesk;
+
+ ///
+ /// 备注。
+ ///
+ public string? Notes { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreHoliday.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreHoliday.cs
new file mode 100644
index 0000000..c464849
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreHoliday.cs
@@ -0,0 +1,29 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Stores.Entities;
+
+///
+/// 门店休息日或特殊营业日。
+///
+public sealed class StoreHoliday : MultiTenantEntityBase
+{
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 日期。
+ ///
+ public DateTime Date { get; set; }
+
+ ///
+ /// 是否全天闭店。
+ ///
+ public bool IsClosed { get; set; } = true;
+
+ ///
+ /// 说明内容。
+ ///
+ public string? Reason { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreTable.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreTable.cs
new file mode 100644
index 0000000..1b55549
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreTable.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Stores.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Stores.Entities;
+
+///
+/// 桌台信息与二维码绑定。
+///
+public sealed class StoreTable : MultiTenantEntityBase
+{
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 所在区域 ID。
+ ///
+ public Guid? AreaId { get; set; }
+
+ ///
+ /// 桌码。
+ ///
+ public string TableCode { get; set; } = string.Empty;
+
+ ///
+ /// 可容纳人数。
+ ///
+ public int Capacity { get; set; }
+
+ ///
+ /// 桌台标签(堂食、快餐等)。
+ ///
+ public string? Tags { get; set; }
+
+ ///
+ /// 当前桌台状态。
+ ///
+ public StoreTableStatus Status { get; set; } = StoreTableStatus.Idle;
+
+ ///
+ /// 桌码二维码地址。
+ ///
+ public string? QrCodeUrl { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreTableArea.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreTableArea.cs
new file mode 100644
index 0000000..6255266
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Stores/Entities/StoreTableArea.cs
@@ -0,0 +1,24 @@
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Stores.Entities;
+
+///
+/// 门店桌台区域配置。
+///
+public sealed class StoreTableArea : MultiTenantEntityBase
+{
+ ///
+ /// 门店标识。
+ ///
+ public Guid StoreId { get; set; }
+
+ ///
+ /// 区域名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 区域描述。
+ ///
+ public string? Description { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Enums/BusinessHourType.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Enums/BusinessHourType.cs
new file mode 100644
index 0000000..9f545a0
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Stores/Enums/BusinessHourType.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Stores.Enums;
+
+///
+/// 营业时段类型。
+///
+public enum BusinessHourType
+{
+ ///
+ /// 正常营业时段。
+ ///
+ Normal = 0,
+
+ ///
+ /// 预留给预约的时段。
+ ///
+ ReservationOnly = 1,
+
+ ///
+ /// 仅自提或配送的时段。
+ ///
+ PickupOrDelivery = 2,
+
+ ///
+ /// 休息时段。
+ ///
+ Closed = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Enums/StoreStatus.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Enums/StoreStatus.cs
new file mode 100644
index 0000000..df82fb9
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Stores/Enums/StoreStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Stores.Enums;
+
+///
+/// 门店运营状态。
+///
+public enum StoreStatus
+{
+ ///
+ /// 未开业或休眠。
+ ///
+ Closed = 0,
+
+ ///
+ /// 准备营业。
+ ///
+ Preparing = 1,
+
+ ///
+ /// 正常营业中。
+ ///
+ Operating = 2,
+
+ ///
+ /// 暂停营业。
+ ///
+ Suspended = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Stores/Enums/StoreTableStatus.cs b/src/Domain/TakeoutSaaS.Domain/Stores/Enums/StoreTableStatus.cs
new file mode 100644
index 0000000..073b832
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Stores/Enums/StoreTableStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Stores.Enums;
+
+///
+/// 桌台占用状态。
+///
+public enum StoreTableStatus
+{
+ ///
+ /// 空闲可用。
+ ///
+ Idle = 0,
+
+ ///
+ /// 已被占用。
+ ///
+ Occupied = 1,
+
+ ///
+ /// 正在清理。
+ ///
+ Cleaning = 2,
+
+ ///
+ /// 暂停使用。
+ ///
+ Disabled = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/Tenant.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/Tenant.cs
new file mode 100644
index 0000000..fd65958
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/Tenant.cs
@@ -0,0 +1,125 @@
+using TakeoutSaaS.Domain.Tenants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Tenants.Entities;
+
+///
+/// 平台租户信息,描述租户的生命周期与基础资料。
+///
+public sealed class Tenant : AuditableEntityBase
+{
+ ///
+ /// 租户短编码,作为跨系统引用的唯一标识。
+ ///
+ public string Code { get; set; } = string.Empty;
+
+ ///
+ /// 租户全称或品牌名称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 对外展示的简称。
+ ///
+ public string? ShortName { get; set; }
+
+ ///
+ /// 法人或公司主体名称。
+ ///
+ public string? LegalEntityName { get; set; }
+
+ ///
+ /// 所属行业,如餐饮、零售等。
+ ///
+ public string? Industry { get; set; }
+
+ ///
+ /// LOGO 图片地址。
+ ///
+ public string? LogoUrl { get; set; }
+
+ ///
+ /// 品牌海报或封面图。
+ ///
+ public string? CoverImageUrl { get; set; }
+
+ ///
+ /// 官网或主要宣传链接。
+ ///
+ public string? Website { get; set; }
+
+ ///
+ /// 所在国家/地区。
+ ///
+ public string? Country { get; set; }
+
+ ///
+ /// 所在省份或州。
+ ///
+ public string? Province { get; set; }
+
+ ///
+ /// 所在城市。
+ ///
+ public string? City { get; set; }
+
+ ///
+ /// 详细地址信息。
+ ///
+ public string? Address { get; set; }
+
+ ///
+ /// 主联系人姓名。
+ ///
+ public string? ContactName { get; set; }
+
+ ///
+ /// 主联系人电话。
+ ///
+ public string? ContactPhone { get; set; }
+
+ ///
+ /// 主联系人邮箱。
+ ///
+ public string? ContactEmail { get; set; }
+
+ ///
+ /// 系统内对应的租户所有者账号 ID。
+ ///
+ public Guid? PrimaryOwnerUserId { get; set; }
+
+ ///
+ /// 租户当前状态,涵盖审核、启用、停用等场景。
+ ///
+ public TenantStatus Status { get; set; } = TenantStatus.PendingReview;
+
+ ///
+ /// 服务生效时间(UTC)。
+ ///
+ public DateTime? EffectiveFrom { get; set; }
+
+ ///
+ /// 服务到期时间(UTC)。
+ ///
+ public DateTime? EffectiveTo { get; set; }
+
+ ///
+ /// 最近一次暂停服务时间。
+ ///
+ public DateTime? SuspendedAt { get; set; }
+
+ ///
+ /// 暂停或终止的原因说明。
+ ///
+ public string? SuspensionReason { get; set; }
+
+ ///
+ /// 业务标签集合(逗号分隔)。
+ ///
+ public string? Tags { get; set; }
+
+ ///
+ /// 备注信息,用于运营记录特殊说明。
+ ///
+ public string? Remarks { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantBillingStatement.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantBillingStatement.cs
new file mode 100644
index 0000000..4fb50e2
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantBillingStatement.cs
@@ -0,0 +1,50 @@
+using TakeoutSaaS.Domain.Tenants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Tenants.Entities;
+
+///
+/// 租户账单,用于呈现周期性收费。
+///
+public sealed class TenantBillingStatement : MultiTenantEntityBase
+{
+ ///
+ /// 账单编号,供对账查询。
+ ///
+ public string StatementNo { get; set; } = string.Empty;
+
+ ///
+ /// 账单周期开始时间。
+ ///
+ public DateTime PeriodStart { get; set; }
+
+ ///
+ /// 账单周期结束时间。
+ ///
+ public DateTime PeriodEnd { get; set; }
+
+ ///
+ /// 应付金额。
+ ///
+ public decimal AmountDue { get; set; }
+
+ ///
+ /// 实付金额。
+ ///
+ public decimal AmountPaid { get; set; }
+
+ ///
+ /// 当前付款状态。
+ ///
+ public TenantBillingStatus Status { get; set; } = TenantBillingStatus.Pending;
+
+ ///
+ /// 到期日。
+ ///
+ public DateTime DueDate { get; set; }
+
+ ///
+ /// 账单明细 JSON,记录各项费用。
+ ///
+ public string? LineItemsJson { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantNotification.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantNotification.cs
new file mode 100644
index 0000000..8d2b881
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantNotification.cs
@@ -0,0 +1,45 @@
+using TakeoutSaaS.Domain.Tenants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Tenants.Entities;
+
+///
+/// 面向租户的站内通知或消息推送。
+///
+public sealed class TenantNotification : MultiTenantEntityBase
+{
+ ///
+ /// 通知标题。
+ ///
+ public string Title { get; set; } = string.Empty;
+
+ ///
+ /// 通知正文。
+ ///
+ public string Message { get; set; } = string.Empty;
+
+ ///
+ /// 发布通道(站内、邮件、短信等)。
+ ///
+ public TenantNotificationChannel Channel { get; set; } = TenantNotificationChannel.InApp;
+
+ ///
+ /// 通知重要级别。
+ ///
+ public TenantNotificationSeverity Severity { get; set; } = TenantNotificationSeverity.Info;
+
+ ///
+ /// 推送时间。
+ ///
+ public DateTime SentAt { get; set; } = DateTime.UtcNow;
+
+ ///
+ /// 租户是否已阅读。
+ ///
+ public DateTime? ReadAt { get; set; }
+
+ ///
+ /// 附加元数据 JSON。
+ ///
+ public string? MetadataJson { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantPackage.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantPackage.cs
new file mode 100644
index 0000000..807f159
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantPackage.cs
@@ -0,0 +1,70 @@
+using TakeoutSaaS.Domain.Tenants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Tenants.Entities;
+
+///
+/// 平台提供的租户套餐定义。
+///
+public sealed class TenantPackage : AuditableEntityBase
+{
+ ///
+ /// 套餐名称,展示给租户的简称。
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// 套餐描述,包含适用场景、权益等。
+ ///
+ public string? Description { get; set; }
+
+ ///
+ /// 套餐分类(试用、标准、旗舰等)。
+ ///
+ public TenantPackageType PackageType { get; set; } = TenantPackageType.Standard;
+
+ ///
+ /// 月付价格,单位:人民币元。
+ ///
+ public decimal? MonthlyPrice { get; set; }
+
+ ///
+ /// 年付价格,单位:人民币元。
+ ///
+ public decimal? YearlyPrice { get; set; }
+
+ ///
+ /// 允许的最大门店数。
+ ///
+ public int? MaxStoreCount { get; set; }
+
+ ///
+ /// 允许创建的最大账号数。
+ ///
+ public int? MaxAccountCount { get; set; }
+
+ ///
+ /// 存储容量上限(GB)。
+ ///
+ public int? MaxStorageGb { get; set; }
+
+ ///
+ /// 每月短信额度上限。
+ ///
+ public int? MaxSmsCredits { get; set; }
+
+ ///
+ /// 每月可调用的配送单数量上限。
+ ///
+ public int? MaxDeliveryOrders { get; set; }
+
+ ///
+ /// 权益明细 JSON,记录自定义特性开关。
+ ///
+ public string? FeaturePoliciesJson { get; set; }
+
+ ///
+ /// 是否仍可售卖。
+ ///
+ public bool IsActive { get; set; } = true;
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantQuotaUsage.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantQuotaUsage.cs
new file mode 100644
index 0000000..5b2f4c5
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantQuotaUsage.cs
@@ -0,0 +1,35 @@
+using TakeoutSaaS.Domain.Tenants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Tenants.Entities;
+
+///
+/// 租户配额使用情况快照。
+///
+public sealed class TenantQuotaUsage : MultiTenantEntityBase
+{
+ ///
+ /// 配额类型,例如门店数、短信条数等。
+ ///
+ public TenantQuotaType QuotaType { get; set; }
+
+ ///
+ /// 当前配额上限。
+ ///
+ public decimal LimitValue { get; set; }
+
+ ///
+ /// 已消耗的数量。
+ ///
+ public decimal UsedValue { get; set; }
+
+ ///
+ /// 配额刷新周期描述(如月、年)。
+ ///
+ public string? ResetCycle { get; set; }
+
+ ///
+ /// 最近一次重置时间。
+ ///
+ public DateTime? LastResetAt { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantSubscription.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantSubscription.cs
new file mode 100644
index 0000000..a54fce2
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Entities/TenantSubscription.cs
@@ -0,0 +1,50 @@
+using TakeoutSaaS.Domain.Tenants.Enums;
+using TakeoutSaaS.Shared.Abstractions.Entities;
+
+namespace TakeoutSaaS.Domain.Tenants.Entities;
+
+///
+/// 租户套餐订阅记录。
+///
+public sealed class TenantSubscription : MultiTenantEntityBase
+{
+ ///
+ /// 当前订阅关联的套餐标识。
+ ///
+ public Guid TenantPackageId { get; set; }
+
+ ///
+ /// 订阅生效时间(UTC)。
+ ///
+ public DateTime EffectiveFrom { get; set; }
+
+ ///
+ /// 订阅到期时间(UTC)。
+ ///
+ public DateTime EffectiveTo { get; set; }
+
+ ///
+ /// 下一个计费时间,配合自动续费使用。
+ ///
+ public DateTime? NextBillingDate { get; set; }
+
+ ///
+ /// 订阅当前状态。
+ ///
+ public SubscriptionStatus Status { get; set; } = SubscriptionStatus.Pending;
+
+ ///
+ /// 是否开启自动续费。
+ ///
+ public bool AutoRenew { get; set; }
+
+ ///
+ /// 若已排期升降配,对应的新套餐 ID。
+ ///
+ public Guid? ScheduledPackageId { get; set; }
+
+ ///
+ /// 运营备注信息。
+ ///
+ public string? Notes { get; set; }
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/SubscriptionStatus.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/SubscriptionStatus.cs
new file mode 100644
index 0000000..d1d1a49
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/SubscriptionStatus.cs
@@ -0,0 +1,32 @@
+namespace TakeoutSaaS.Domain.Tenants.Enums;
+
+///
+/// 订阅状态。
+///
+public enum SubscriptionStatus
+{
+ ///
+ /// 尚未支付或等待审批。
+ ///
+ Pending = 0,
+
+ ///
+ /// 订阅已生效。
+ ///
+ Active = 1,
+
+ ///
+ /// 已到期但仍保留数据。
+ ///
+ GracePeriod = 2,
+
+ ///
+ /// 已取消。
+ ///
+ Cancelled = 3,
+
+ ///
+ /// 因欠费被暂停。
+ ///
+ Suspended = 4
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantBillingStatus.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantBillingStatus.cs
new file mode 100644
index 0000000..11671d2
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantBillingStatus.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Tenants.Enums;
+
+///
+/// 账单状态。
+///
+public enum TenantBillingStatus
+{
+ ///
+ /// 等待付款。
+ ///
+ Pending = 0,
+
+ ///
+ /// 已付款结清。
+ ///
+ Paid = 1,
+
+ ///
+ /// 已逾期。
+ ///
+ Overdue = 2,
+
+ ///
+ /// 已取消或作废。
+ ///
+ Cancelled = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantNotificationChannel.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantNotificationChannel.cs
new file mode 100644
index 0000000..25a3a36
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantNotificationChannel.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Tenants.Enums;
+
+///
+/// 通知推送渠道。
+///
+public enum TenantNotificationChannel
+{
+ ///
+ /// 站内消息。
+ ///
+ InApp = 0,
+
+ ///
+ /// 邮件推送。
+ ///
+ Email = 1,
+
+ ///
+ /// 短信提醒。
+ ///
+ Sms = 2,
+
+ ///
+ /// 管理后台弹窗。
+ ///
+ Portal = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantNotificationSeverity.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantNotificationSeverity.cs
new file mode 100644
index 0000000..7947059
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantNotificationSeverity.cs
@@ -0,0 +1,22 @@
+namespace TakeoutSaaS.Domain.Tenants.Enums;
+
+///
+/// 租户通知的重要程度。
+///
+public enum TenantNotificationSeverity
+{
+ ///
+ /// 普通提示。
+ ///
+ Info = 0,
+
+ ///
+ /// 需要关注的提醒。
+ ///
+ Warning = 1,
+
+ ///
+ /// 影响业务的严重事件。
+ ///
+ Critical = 2
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantPackageType.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantPackageType.cs
new file mode 100644
index 0000000..111ae2c
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantPackageType.cs
@@ -0,0 +1,27 @@
+namespace TakeoutSaaS.Domain.Tenants.Enums;
+
+///
+/// 套餐类型枚举。
+///
+public enum TenantPackageType
+{
+ ///
+ /// 免费试用套餐。
+ ///
+ Trial = 0,
+
+ ///
+ /// 标准商业套餐。
+ ///
+ Standard = 1,
+
+ ///
+ /// 面向成长型商户的高级套餐。
+ ///
+ Professional = 2,
+
+ ///
+ /// 提供完整能力的旗舰套餐。
+ ///
+ Enterprise = 3
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantQuotaType.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantQuotaType.cs
new file mode 100644
index 0000000..5392bca
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantQuotaType.cs
@@ -0,0 +1,37 @@
+namespace TakeoutSaaS.Domain.Tenants.Enums;
+
+///
+/// 配额类型,覆盖容量及调用次数。
+///
+public enum TenantQuotaType
+{
+ ///
+ /// 门店数量限制。
+ ///
+ StoreCount = 0,
+
+ ///
+ /// 员工账号数量限制。
+ ///
+ AccountCount = 1,
+
+ ///
+ /// 存储空间限制。
+ ///
+ Storage = 2,
+
+ ///
+ /// 短信额度。
+ ///
+ SmsCredits = 3,
+
+ ///
+ /// 配送订单数量限制。
+ ///
+ DeliveryOrders = 4,
+
+ ///
+ /// 营销活动并发数量。
+ ///
+ PromotionSlots = 5
+}
diff --git a/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantStatus.cs b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantStatus.cs
new file mode 100644
index 0000000..369ed3a
--- /dev/null
+++ b/src/Domain/TakeoutSaaS.Domain/Tenants/Enums/TenantStatus.cs
@@ -0,0 +1,32 @@
+namespace TakeoutSaaS.Domain.Tenants.Enums;
+
+///
+/// 租户服务状态。
+///
+public enum TenantStatus
+{
+ ///
+ /// 已提交信息,等待审核。
+ ///
+ PendingReview = 0,
+
+ ///
+ /// 审核通过并正常运营。
+ ///
+ Active = 1,
+
+ ///
+ /// 因欠费或违规被暂时停用。
+ ///
+ Suspended = 2,
+
+ ///
+ /// 服务到期尚未续费。
+ ///
+ Expired = 3,
+
+ ///
+ /// 主动或被动注销,数据进入归档状态。
+ ///
+ Closed = 4
+}
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Migrations/20251201044927_InitialApp.Designer.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Migrations/20251201044927_InitialApp.Designer.cs
new file mode 100644
index 0000000..56454dc
--- /dev/null
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Migrations/20251201044927_InitialApp.Designer.cs
@@ -0,0 +1,949 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
+using TakeoutSaaS.Infrastructure.App.Persistence;
+
+#nullable disable
+
+namespace TakeoutSaaS.Infrastructure.App.Migrations
+{
+ [DbContext(typeof(TakeoutAppDbContext))]
+ [Migration("20251201044927_InitialApp")]
+ partial class InitialApp
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder
+ .HasAnnotation("ProductVersion", "10.0.0")
+ .HasAnnotation("Relational:MaxIdentifierLength", 63);
+
+ NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Deliveries.Entities.DeliveryOrder", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CourierName")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("CourierPhone")
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeliveredAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeliveryFee")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("DispatchedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("FailureReason")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("OrderId")
+ .HasColumnType("uuid");
+
+ b.Property("PickedUpAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Provider")
+ .HasColumnType("integer");
+
+ b.Property("ProviderOrderId")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "OrderId")
+ .IsUnique();
+
+ b.ToTable("delivery_orders", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Merchants.Entities.Merchant", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Address")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("BrandAlias")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("BrandName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.Property("BusinessLicenseNumber")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("City")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("ContactEmail")
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.Property("ContactPhone")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("District")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("LegalPerson")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("OnboardedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Province")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("ReviewRemarks")
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId");
+
+ b.ToTable("merchants", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.Order", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CancelReason")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("CancelledAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Channel")
+ .HasColumnType("integer");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("CustomerName")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("CustomerPhone")
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeliveryType")
+ .HasColumnType("integer");
+
+ b.Property("DiscountAmount")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("FinishedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("ItemsAmount")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("OrderNo")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("PaidAmount")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("PaidAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("PayableAmount")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("PaymentStatus")
+ .HasColumnType("integer");
+
+ b.Property("QueueNumber")
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("Remark")
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("ReservationId")
+ .HasColumnType("uuid");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("StoreId")
+ .HasColumnType("uuid");
+
+ b.Property("TableNo")
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "OrderNo")
+ .IsUnique();
+
+ b.HasIndex("TenantId", "StoreId", "Status");
+
+ b.ToTable("orders", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("AttributesJson")
+ .HasColumnType("text");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DiscountAmount")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("OrderId")
+ .HasColumnType("uuid");
+
+ b.Property("ProductId")
+ .HasColumnType("uuid");
+
+ b.Property("ProductName")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.Property("Quantity")
+ .HasColumnType("integer");
+
+ b.Property("SkuName")
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.Property("SubTotal")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid");
+
+ b.Property("Unit")
+ .HasMaxLength(16)
+ .HasColumnType("character varying(16)");
+
+ b.Property("UnitPrice")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("OrderId");
+
+ b.HasIndex("TenantId", "OrderId");
+
+ b.ToTable("order_items", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Payments.Entities.PaymentRecord", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Amount")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("ChannelTransactionId")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("Method")
+ .HasColumnType("integer");
+
+ b.Property("OrderId")
+ .HasColumnType("uuid");
+
+ b.Property("PaidAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Payload")
+ .HasColumnType("text");
+
+ b.Property("Remark")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid");
+
+ b.Property("TradeNo")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "OrderId");
+
+ b.ToTable("payment_records", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.Product", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CategoryId")
+ .HasColumnType("uuid");
+
+ b.Property("CoverImage")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("Description")
+ .HasColumnType("text");
+
+ b.Property("EnableDelivery")
+ .HasColumnType("boolean");
+
+ b.Property("EnableDineIn")
+ .HasColumnType("boolean");
+
+ b.Property("EnablePickup")
+ .HasColumnType("boolean");
+
+ b.Property("GalleryImages")
+ .HasMaxLength(1024)
+ .HasColumnType("character varying(1024)");
+
+ b.Property("IsFeatured")
+ .HasColumnType("boolean");
+
+ b.Property("MaxQuantityPerOrder")
+ .HasColumnType("integer");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.Property("OriginalPrice")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("Price")
+ .HasPrecision(18, 2)
+ .HasColumnType("numeric(18,2)");
+
+ b.Property("SpuCode")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("StockQuantity")
+ .HasColumnType("integer");
+
+ b.Property("StoreId")
+ .HasColumnType("uuid");
+
+ b.Property("Subtitle")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid");
+
+ b.Property("Unit")
+ .HasMaxLength(16)
+ .HasColumnType("character varying(16)");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "SpuCode")
+ .IsUnique();
+
+ b.HasIndex("TenantId", "StoreId");
+
+ b.ToTable("products", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Products.Entities.ProductCategory", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("Description")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("IsEnabled")
+ .HasColumnType("boolean");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("SortOrder")
+ .HasColumnType("integer");
+
+ b.Property("StoreId")
+ .HasColumnType("uuid");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "StoreId");
+
+ b.ToTable("product_categories", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Queues.Entities.QueueTicket", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CalledAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CancelledAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("EstimatedWaitMinutes")
+ .HasColumnType("integer");
+
+ b.Property("ExpiredAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("PartySize")
+ .HasColumnType("integer");
+
+ b.Property("Remark")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("StoreId")
+ .HasColumnType("uuid");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid");
+
+ b.Property("TicketNumber")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "StoreId");
+
+ b.HasIndex("TenantId", "StoreId", "TicketNumber")
+ .IsUnique();
+
+ b.ToTable("queue_tickets", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Reservations.Entities.Reservation", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("CancelledAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CheckInCode")
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("CheckedInAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("CustomerName")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("CustomerPhone")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("PeopleCount")
+ .HasColumnType("integer");
+
+ b.Property("Remark")
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("ReservationNo")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("ReservationTime")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("StoreId")
+ .HasColumnType("uuid");
+
+ b.Property("TablePreference")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("TenantId", "ReservationNo")
+ .IsUnique();
+
+ b.HasIndex("TenantId", "StoreId");
+
+ b.ToTable("reservations", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Address")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("Announcement")
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("BusinessHours")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("City")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeliveryRadiusKm")
+ .HasPrecision(6, 2)
+ .HasColumnType("numeric(6,2)");
+
+ b.Property("District")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("Latitude")
+ .HasColumnType("double precision");
+
+ b.Property("Longitude")
+ .HasColumnType("double precision");
+
+ b.Property("ManagerName")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("MerchantId")
+ .HasColumnType("uuid");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.Property("Phone")
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("Province")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("QueueEnabled")
+ .HasColumnType("boolean");
+
+ b.Property("ReservationEnabled")
+ .HasColumnType("boolean");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("SupportsDelivery")
+ .HasColumnType("boolean");
+
+ b.Property("SupportsDineIn")
+ .HasColumnType("boolean");
+
+ b.Property("SupportsPickup")
+ .HasColumnType("boolean");
+
+ b.Property("TenantId")
+ .HasColumnType("uuid");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("MerchantId");
+
+ b.HasIndex("TenantId", "Code")
+ .IsUnique();
+
+ b.HasIndex("TenantId", "MerchantId");
+
+ b.ToTable("stores", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Tenants.Entities.Tenant", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("uuid");
+
+ b.Property("Code")
+ .IsRequired()
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("ContactEmail")
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.Property("ContactName")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("ContactPhone")
+ .HasMaxLength(32)
+ .HasColumnType("character varying(32)");
+
+ b.Property("CreatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("CreatedBy")
+ .HasColumnType("uuid");
+
+ b.Property("DeletedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("DeletedBy")
+ .HasColumnType("uuid");
+
+ b.Property("EffectiveFrom")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("EffectiveTo")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("Industry")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("LogoUrl")
+ .HasMaxLength(256)
+ .HasColumnType("character varying(256)");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasMaxLength(128)
+ .HasColumnType("character varying(128)");
+
+ b.Property("Remarks")
+ .HasMaxLength(512)
+ .HasColumnType("character varying(512)");
+
+ b.Property("ShortName")
+ .HasMaxLength(64)
+ .HasColumnType("character varying(64)");
+
+ b.Property("Status")
+ .HasColumnType("integer");
+
+ b.Property("UpdatedAt")
+ .HasColumnType("timestamp with time zone");
+
+ b.Property("UpdatedBy")
+ .HasColumnType("uuid");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Code")
+ .IsUnique();
+
+ b.ToTable("tenants", (string)null);
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Orders.Entities.OrderItem", b =>
+ {
+ b.HasOne("TakeoutSaaS.Domain.Orders.Entities.Order", null)
+ .WithMany()
+ .HasForeignKey("OrderId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("TakeoutSaaS.Domain.Stores.Entities.Store", b =>
+ {
+ b.HasOne("TakeoutSaaS.Domain.Merchants.Entities.Merchant", "Merchant")
+ .WithMany()
+ .HasForeignKey("MerchantId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Merchant");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Migrations/20251201044927_InitialApp.cs b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Migrations/20251201044927_InitialApp.cs
new file mode 100644
index 0000000..f322c41
--- /dev/null
+++ b/src/Infrastructure/TakeoutSaaS.Infrastructure/App/Migrations/20251201044927_InitialApp.cs
@@ -0,0 +1,497 @@
+using System;
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace TakeoutSaaS.Infrastructure.App.Migrations
+{
+ ///
+ public partial class InitialApp : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.CreateTable(
+ name: "delivery_orders",
+ columns: table => new
+ {
+ Id = table.Column(type: "uuid", nullable: false),
+ OrderId = table.Column(type: "uuid", nullable: false),
+ Provider = table.Column(type: "integer", nullable: false),
+ ProviderOrderId = table.Column(type: "character varying(64)", maxLength: 64, nullable: true),
+ Status = table.Column(type: "integer", nullable: false),
+ DeliveryFee = table.Column(type: "numeric(18,2)", precision: 18, scale: 2, nullable: true),
+ CourierName = table.Column(type: "character varying(64)", maxLength: 64, nullable: true),
+ CourierPhone = table.Column(type: "character varying(32)", maxLength: 32, nullable: true),
+ DispatchedAt = table.Column(type: "timestamp with time zone", nullable: true),
+ PickedUpAt = table.Column(type: "timestamp with time zone", nullable: true),
+ DeliveredAt = table.Column(type: "timestamp with time zone", nullable: true),
+ FailureReason = table.Column(type: "character varying(256)", maxLength: 256, nullable: true),
+ CreatedAt = table.Column(type: "timestamp with time zone", nullable: false),
+ UpdatedAt = table.Column(type: "timestamp with time zone", nullable: true),
+ DeletedAt = table.Column(type: "timestamp with time zone", nullable: true),
+ CreatedBy = table.Column(type: "uuid", nullable: true),
+ UpdatedBy = table.Column(type: "uuid", nullable: true),
+ DeletedBy = table.Column(type: "uuid", nullable: true),
+ TenantId = table.Column(type: "uuid", nullable: false)
+ },
+ constraints: table =>
+ {
+ table.PrimaryKey("PK_delivery_orders", x => x.Id);
+ });
+
+ migrationBuilder.CreateTable(
+ name: "merchants",
+ columns: table => new
+ {
+ Id = table.Column(type: "uuid", nullable: false),
+ BrandName = table.Column(type: "character varying(128)", maxLength: 128, nullable: false),
+ BrandAlias = table.Column(type: "character varying(64)", maxLength: 64, nullable: true),
+ LegalPerson = table.Column(type: "character varying(64)", maxLength: 64, nullable: true),
+ BusinessLicenseNumber = table.Column(type: "character varying(64)", maxLength: 64, nullable: true),
+ ContactPhone = table.Column(type: "character varying(32)", maxLength: 32, nullable: false),
+ ContactEmail = table.Column(type: "character varying(128)", maxLength: 128, nullable: true),
+ Province = table.Column(type: "character varying(64)", maxLength: 64, nullable: true),
+ City = table.Column(type: "character varying(64)", maxLength: 64, nullable: true),
+ District = table.Column