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

@@ -0,0 +1,65 @@
using TakeoutSaaS.Domain.Coupons.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Coupons.Entities;
/// <summary>
/// 次卡实例(顾客购买后生成)。
/// </summary>
public sealed class PunchCardInstance : MultiTenantEntityBase
{
/// <summary>
/// 门店 ID。
/// </summary>
public long StoreId { get; set; }
/// <summary>
/// 次卡模板 ID。
/// </summary>
public long PunchCardTemplateId { get; set; }
/// <summary>
/// 实例编号(业务唯一)。
/// </summary>
public string InstanceNo { get; set; } = string.Empty;
/// <summary>
/// 会员名称。
/// </summary>
public string MemberName { get; set; } = string.Empty;
/// <summary>
/// 会员手机号(脱敏)。
/// </summary>
public string MemberPhoneMasked { get; set; } = string.Empty;
/// <summary>
/// 购买时间UTC
/// </summary>
public DateTime PurchasedAt { get; set; }
/// <summary>
/// 过期时间UTC可空
/// </summary>
public DateTime? ExpiresAt { get; set; }
/// <summary>
/// 总次数。
/// </summary>
public int TotalTimes { get; set; }
/// <summary>
/// 剩余次数。
/// </summary>
public int RemainingTimes { get; set; }
/// <summary>
/// 实付金额。
/// </summary>
public decimal PaidAmount { get; set; }
/// <summary>
/// 实例状态。
/// </summary>
public PunchCardInstanceStatus Status { get; set; } = PunchCardInstanceStatus.Active;
}

View File

@@ -0,0 +1,130 @@
using TakeoutSaaS.Domain.Coupons.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Coupons.Entities;
/// <summary>
/// 次卡模板配置。
/// </summary>
public sealed class PunchCardTemplate : MultiTenantEntityBase
{
/// <summary>
/// 门店 ID。
/// </summary>
public long StoreId { get; set; }
/// <summary>
/// 次卡名称。
/// </summary>
public string Name { get; set; } = string.Empty;
/// <summary>
/// 封面图片地址。
/// </summary>
public string? CoverImageUrl { get; set; }
/// <summary>
/// 售价。
/// </summary>
public decimal SalePrice { get; set; }
/// <summary>
/// 原价。
/// </summary>
public decimal? OriginalPrice { get; set; }
/// <summary>
/// 总次数。
/// </summary>
public int TotalTimes { get; set; }
/// <summary>
/// 有效期类型。
/// </summary>
public PunchCardValidityType ValidityType { get; set; } = PunchCardValidityType.Days;
/// <summary>
/// 固定天数ValidityType=Days 时有效)。
/// </summary>
public int? ValidityDays { get; set; }
/// <summary>
/// 固定开始日期UTCValidityType=DateRange 时有效)。
/// </summary>
public DateTime? ValidFrom { get; set; }
/// <summary>
/// 固定结束日期UTCValidityType=DateRange 时有效)。
/// </summary>
public DateTime? ValidTo { get; set; }
/// <summary>
/// 适用范围类型。
/// </summary>
public PunchCardScopeType ScopeType { get; set; } = PunchCardScopeType.All;
/// <summary>
/// 指定分类 ID JSON。
/// </summary>
public string ScopeCategoryIdsJson { get; set; } = "[]";
/// <summary>
/// 指定标签 ID JSON。
/// </summary>
public string ScopeTagIdsJson { get; set; } = "[]";
/// <summary>
/// 指定商品 ID JSON。
/// </summary>
public string ScopeProductIdsJson { get; set; } = "[]";
/// <summary>
/// 使用模式。
/// </summary>
public PunchCardUsageMode UsageMode { get; set; } = PunchCardUsageMode.Free;
/// <summary>
/// 金额上限UsageMode=Cap 时有效)。
/// </summary>
public decimal? UsageCapAmount { get; set; }
/// <summary>
/// 每日限用次数。
/// </summary>
public int? DailyLimit { get; set; }
/// <summary>
/// 每单限用次数。
/// </summary>
public int? PerOrderLimit { get; set; }
/// <summary>
/// 每人限购张数。
/// </summary>
public int? PerUserPurchaseLimit { get; set; }
/// <summary>
/// 是否允许转赠。
/// </summary>
public bool AllowTransfer { get; set; }
/// <summary>
/// 过期策略。
/// </summary>
public PunchCardExpireStrategy ExpireStrategy { get; set; } = PunchCardExpireStrategy.Invalidate;
/// <summary>
/// 次卡描述。
/// </summary>
public string? Description { get; set; }
/// <summary>
/// 购买通知渠道 JSON。
/// </summary>
public string NotifyChannelsJson { get; set; } = "[]";
/// <summary>
/// 次卡状态。
/// </summary>
public PunchCardStatus Status { get; set; } = PunchCardStatus.Enabled;
}

View File

@@ -0,0 +1,60 @@
using TakeoutSaaS.Domain.Coupons.Enums;
using TakeoutSaaS.Shared.Abstractions.Entities;
namespace TakeoutSaaS.Domain.Coupons.Entities;
/// <summary>
/// 次卡使用记录。
/// </summary>
public sealed class PunchCardUsageRecord : MultiTenantEntityBase
{
/// <summary>
/// 门店 ID。
/// </summary>
public long StoreId { get; set; }
/// <summary>
/// 次卡模板 ID。
/// </summary>
public long PunchCardTemplateId { get; set; }
/// <summary>
/// 次卡实例 ID。
/// </summary>
public long PunchCardInstanceId { get; set; }
/// <summary>
/// 使用单号。
/// </summary>
public string RecordNo { get; set; } = string.Empty;
/// <summary>
/// 兑换商品名称。
/// </summary>
public string ProductName { get; set; } = string.Empty;
/// <summary>
/// 使用时间UTC
/// </summary>
public DateTime UsedAt { get; set; }
/// <summary>
/// 本次使用次数。
/// </summary>
public int UsedTimes { get; set; } = 1;
/// <summary>
/// 使用后剩余次数。
/// </summary>
public int RemainingTimesAfterUse { get; set; }
/// <summary>
/// 本次记录状态。
/// </summary>
public PunchCardUsageRecordStatus StatusAfterUse { get; set; } = PunchCardUsageRecordStatus.Normal;
/// <summary>
/// 超额补差金额。
/// </summary>
public decimal? ExtraPayAmount { get; set; }
}