feat: implement marketing punch card backend module

This commit is contained in:
2026-03-02 21:43:09 +08:00
parent 6588c85f27
commit 3b3bdcee71
48 changed files with 14863 additions and 1 deletions

View File

@@ -1012,6 +1012,363 @@ namespace TakeoutSaaS.Infrastructure.Migrations
});
});
modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PunchCardInstance", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasComment("实体唯一标识。");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间UTC。");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone")
.HasComment("软删除时间UTC未删除时为 null。");
b.Property<long?>("DeletedBy")
.HasColumnType("bigint")
.HasComment("删除人用户标识(软删除),未删除时为 null。");
b.Property<DateTime?>("ExpiresAt")
.HasColumnType("timestamp with time zone")
.HasComment("过期时间UTC可空。");
b.Property<string>("InstanceNo")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)")
.HasComment("实例编号(业务唯一)。");
b.Property<string>("MemberName")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)")
.HasComment("会员名称。");
b.Property<string>("MemberPhoneMasked")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)")
.HasComment("会员手机号(脱敏)。");
b.Property<decimal>("PaidAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)")
.HasComment("实付金额。");
b.Property<long>("PunchCardTemplateId")
.HasColumnType("bigint")
.HasComment("次卡模板 ID。");
b.Property<DateTime>("PurchasedAt")
.HasColumnType("timestamp with time zone")
.HasComment("购买时间UTC。");
b.Property<int>("RemainingTimes")
.HasColumnType("integer")
.HasComment("剩余次数。");
b.Property<int>("Status")
.HasColumnType("integer")
.HasComment("实例状态。");
b.Property<long>("StoreId")
.HasColumnType("bigint")
.HasComment("门店 ID。");
b.Property<long>("TenantId")
.HasColumnType("bigint")
.HasComment("所属租户 ID。");
b.Property<int>("TotalTimes")
.HasColumnType("integer")
.HasComment("总次数。");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("最近一次更新时间UTC从未更新时为 null。");
b.Property<long?>("UpdatedBy")
.HasColumnType("bigint")
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
b.HasKey("Id");
b.HasIndex("TenantId", "StoreId", "InstanceNo")
.IsUnique();
b.HasIndex("TenantId", "StoreId", "PunchCardTemplateId");
b.HasIndex("TenantId", "StoreId", "Status", "ExpiresAt");
b.ToTable("punch_card_instances", null, t =>
{
t.HasComment("次卡实例(顾客购买后生成)。");
});
});
modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PunchCardTemplate", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasComment("实体唯一标识。");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<bool>("AllowTransfer")
.HasColumnType("boolean")
.HasComment("是否允许转赠。");
b.Property<string>("CoverImageUrl")
.HasMaxLength(512)
.HasColumnType("character varying(512)")
.HasComment("封面图片地址。");
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间UTC。");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
b.Property<int?>("DailyLimit")
.HasColumnType("integer")
.HasComment("每日限用次数。");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone")
.HasComment("软删除时间UTC未删除时为 null。");
b.Property<long?>("DeletedBy")
.HasColumnType("bigint")
.HasComment("删除人用户标识(软删除),未删除时为 null。");
b.Property<string>("Description")
.HasMaxLength(512)
.HasColumnType("character varying(512)")
.HasComment("次卡描述。");
b.Property<int>("ExpireStrategy")
.HasColumnType("integer")
.HasComment("过期策略。");
b.Property<string>("Name")
.IsRequired()
.HasMaxLength(64)
.HasColumnType("character varying(64)")
.HasComment("次卡名称。");
b.Property<string>("NotifyChannelsJson")
.IsRequired()
.HasColumnType("text")
.HasComment("购买通知渠道 JSON。");
b.Property<decimal?>("OriginalPrice")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)")
.HasComment("原价。");
b.Property<int?>("PerOrderLimit")
.HasColumnType("integer")
.HasComment("每单限用次数。");
b.Property<int?>("PerUserPurchaseLimit")
.HasColumnType("integer")
.HasComment("每人限购张数。");
b.Property<decimal>("SalePrice")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)")
.HasComment("售价。");
b.Property<string>("ScopeCategoryIdsJson")
.IsRequired()
.HasColumnType("text")
.HasComment("指定分类 ID JSON。");
b.Property<string>("ScopeProductIdsJson")
.IsRequired()
.HasColumnType("text")
.HasComment("指定商品 ID JSON。");
b.Property<string>("ScopeTagIdsJson")
.IsRequired()
.HasColumnType("text")
.HasComment("指定标签 ID JSON。");
b.Property<int>("ScopeType")
.HasColumnType("integer")
.HasComment("适用范围类型。");
b.Property<int>("Status")
.HasColumnType("integer")
.HasComment("次卡状态。");
b.Property<long>("StoreId")
.HasColumnType("bigint")
.HasComment("门店 ID。");
b.Property<long>("TenantId")
.HasColumnType("bigint")
.HasComment("所属租户 ID。");
b.Property<int>("TotalTimes")
.HasColumnType("integer")
.HasComment("总次数。");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("最近一次更新时间UTC从未更新时为 null。");
b.Property<long?>("UpdatedBy")
.HasColumnType("bigint")
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
b.Property<decimal?>("UsageCapAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)")
.HasComment("金额上限UsageMode=Cap 时有效)。");
b.Property<int>("UsageMode")
.HasColumnType("integer")
.HasComment("使用模式。");
b.Property<DateTime?>("ValidFrom")
.HasColumnType("timestamp with time zone")
.HasComment("固定开始日期UTCValidityType=DateRange 时有效)。");
b.Property<DateTime?>("ValidTo")
.HasColumnType("timestamp with time zone")
.HasComment("固定结束日期UTCValidityType=DateRange 时有效)。");
b.Property<int?>("ValidityDays")
.HasColumnType("integer")
.HasComment("固定天数ValidityType=Days 时有效)。");
b.Property<int>("ValidityType")
.HasColumnType("integer")
.HasComment("有效期类型。");
b.HasKey("Id");
b.HasIndex("TenantId", "StoreId", "Name")
.IsUnique();
b.HasIndex("TenantId", "StoreId", "Status");
b.ToTable("punch_card_templates", null, t =>
{
t.HasComment("次卡模板配置。");
});
});
modelBuilder.Entity("TakeoutSaaS.Domain.Coupons.Entities.PunchCardUsageRecord", b =>
{
b.Property<long>("Id")
.ValueGeneratedOnAdd()
.HasColumnType("bigint")
.HasComment("实体唯一标识。");
NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property<long>("Id"));
b.Property<DateTime>("CreatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("创建时间UTC。");
b.Property<long?>("CreatedBy")
.HasColumnType("bigint")
.HasComment("创建人用户标识,匿名或系统操作时为 null。");
b.Property<DateTime?>("DeletedAt")
.HasColumnType("timestamp with time zone")
.HasComment("软删除时间UTC未删除时为 null。");
b.Property<long?>("DeletedBy")
.HasColumnType("bigint")
.HasComment("删除人用户标识(软删除),未删除时为 null。");
b.Property<decimal?>("ExtraPayAmount")
.HasPrecision(18, 2)
.HasColumnType("numeric(18,2)")
.HasComment("超额补差金额。");
b.Property<string>("ProductName")
.IsRequired()
.HasMaxLength(128)
.HasColumnType("character varying(128)")
.HasComment("兑换商品名称。");
b.Property<long>("PunchCardInstanceId")
.HasColumnType("bigint")
.HasComment("次卡实例 ID。");
b.Property<long>("PunchCardTemplateId")
.HasColumnType("bigint")
.HasComment("次卡模板 ID。");
b.Property<string>("RecordNo")
.IsRequired()
.HasMaxLength(32)
.HasColumnType("character varying(32)")
.HasComment("使用单号。");
b.Property<int>("RemainingTimesAfterUse")
.HasColumnType("integer")
.HasComment("使用后剩余次数。");
b.Property<int>("StatusAfterUse")
.HasColumnType("integer")
.HasComment("本次记录状态。");
b.Property<long>("StoreId")
.HasColumnType("bigint")
.HasComment("门店 ID。");
b.Property<long>("TenantId")
.HasColumnType("bigint")
.HasComment("所属租户 ID。");
b.Property<DateTime?>("UpdatedAt")
.HasColumnType("timestamp with time zone")
.HasComment("最近一次更新时间UTC从未更新时为 null。");
b.Property<long?>("UpdatedBy")
.HasColumnType("bigint")
.HasComment("最后更新人用户标识,匿名或系统操作时为 null。");
b.Property<DateTime>("UsedAt")
.HasColumnType("timestamp with time zone")
.HasComment("使用时间UTC。");
b.Property<int>("UsedTimes")
.HasColumnType("integer")
.HasComment("本次使用次数。");
b.HasKey("Id");
b.HasIndex("TenantId", "StoreId", "RecordNo")
.IsUnique();
b.HasIndex("TenantId", "StoreId", "PunchCardInstanceId", "UsedAt");
b.HasIndex("TenantId", "StoreId", "PunchCardTemplateId", "UsedAt");
b.ToTable("punch_card_usage_records", null, t =>
{
t.HasComment("次卡使用记录。");
});
});
modelBuilder.Entity("TakeoutSaaS.Domain.CustomerService.Entities.ChatMessage", b =>
{
b.Property<long>("Id")