feat(marketing): add new customer gift backend module
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
using TakeoutSaaS.Domain.Coupons.Enums;
|
||||
using TakeoutSaaS.Shared.Abstractions.Entities;
|
||||
|
||||
namespace TakeoutSaaS.Domain.Coupons.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// 新客有礼券规则。
|
||||
/// </summary>
|
||||
public sealed class NewCustomerCouponRule : MultiTenantEntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 门店 ID。
|
||||
/// </summary>
|
||||
public long StoreId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 券规则场景。
|
||||
/// </summary>
|
||||
public NewCustomerCouponScene Scene { get; set; } = NewCustomerCouponScene.Welcome;
|
||||
|
||||
/// <summary>
|
||||
/// 券类型。
|
||||
/// </summary>
|
||||
public NewCustomerCouponType CouponType { get; set; } = NewCustomerCouponType.AmountOff;
|
||||
|
||||
/// <summary>
|
||||
/// 面值或折扣值。
|
||||
/// </summary>
|
||||
public decimal? Value { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 使用门槛。
|
||||
/// </summary>
|
||||
public decimal? MinimumSpend { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 有效期天数。
|
||||
/// </summary>
|
||||
public int ValidDays { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 排序值(同场景内递增)。
|
||||
/// </summary>
|
||||
public int SortOrder { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using TakeoutSaaS.Domain.Coupons.Enums;
|
||||
using TakeoutSaaS.Shared.Abstractions.Entities;
|
||||
|
||||
namespace TakeoutSaaS.Domain.Coupons.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// 新客有礼门店配置。
|
||||
/// </summary>
|
||||
public sealed class NewCustomerGiftSetting : MultiTenantEntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 门店 ID。
|
||||
/// </summary>
|
||||
public long StoreId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否开启新客礼包。
|
||||
/// </summary>
|
||||
public bool GiftEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 礼包类型。
|
||||
/// </summary>
|
||||
public NewCustomerGiftType GiftType { get; set; } = NewCustomerGiftType.Coupon;
|
||||
|
||||
/// <summary>
|
||||
/// 首单直减金额。
|
||||
/// </summary>
|
||||
public decimal? DirectReduceAmount { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 首单直减门槛金额。
|
||||
/// </summary>
|
||||
public decimal? DirectMinimumSpend { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 是否开启老带新分享。
|
||||
/// </summary>
|
||||
public bool InviteEnabled { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 分享渠道(JSON)。
|
||||
/// </summary>
|
||||
public string ShareChannelsJson { get; set; } = "[]";
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
using TakeoutSaaS.Shared.Abstractions.Entities;
|
||||
|
||||
namespace TakeoutSaaS.Domain.Coupons.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// 新客成长记录。
|
||||
/// </summary>
|
||||
public sealed class NewCustomerGrowthRecord : MultiTenantEntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 门店 ID。
|
||||
/// </summary>
|
||||
public long StoreId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 顾客业务唯一键。
|
||||
/// </summary>
|
||||
public string CustomerKey { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 顾客展示名。
|
||||
/// </summary>
|
||||
public string? CustomerName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 注册时间。
|
||||
/// </summary>
|
||||
public DateTime RegisteredAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 礼包领取时间。
|
||||
/// </summary>
|
||||
public DateTime? GiftClaimedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 首单时间。
|
||||
/// </summary>
|
||||
public DateTime? FirstOrderAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 渠道来源。
|
||||
/// </summary>
|
||||
public string? SourceChannel { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
using TakeoutSaaS.Domain.Coupons.Enums;
|
||||
using TakeoutSaaS.Shared.Abstractions.Entities;
|
||||
|
||||
namespace TakeoutSaaS.Domain.Coupons.Entities;
|
||||
|
||||
/// <summary>
|
||||
/// 新客邀请记录。
|
||||
/// </summary>
|
||||
public sealed class NewCustomerInviteRecord : MultiTenantEntityBase
|
||||
{
|
||||
/// <summary>
|
||||
/// 门店 ID。
|
||||
/// </summary>
|
||||
public long StoreId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 邀请人展示名。
|
||||
/// </summary>
|
||||
public string InviterName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 被邀请人展示名。
|
||||
/// </summary>
|
||||
public string InviteeName { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// 邀请时间。
|
||||
/// </summary>
|
||||
public DateTime InviteTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 订单状态。
|
||||
/// </summary>
|
||||
public NewCustomerInviteOrderStatus OrderStatus { get; set; } = NewCustomerInviteOrderStatus.PendingOrder;
|
||||
|
||||
/// <summary>
|
||||
/// 奖励状态。
|
||||
/// </summary>
|
||||
public NewCustomerInviteRewardStatus RewardStatus { get; set; } = NewCustomerInviteRewardStatus.Pending;
|
||||
|
||||
/// <summary>
|
||||
/// 奖励发放时间。
|
||||
/// </summary>
|
||||
public DateTime? RewardIssuedAt { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 邀请来源渠道。
|
||||
/// </summary>
|
||||
public string? SourceChannel { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace TakeoutSaaS.Domain.Coupons.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 新客有礼券规则场景。
|
||||
/// </summary>
|
||||
public enum NewCustomerCouponScene
|
||||
{
|
||||
/// <summary>
|
||||
/// 新客礼包。
|
||||
/// </summary>
|
||||
Welcome = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 邀请人奖励。
|
||||
/// </summary>
|
||||
InviterReward = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 被邀请人奖励。
|
||||
/// </summary>
|
||||
InviteeReward = 3
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
namespace TakeoutSaaS.Domain.Coupons.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 新客有礼券类型。
|
||||
/// </summary>
|
||||
public enum NewCustomerCouponType
|
||||
{
|
||||
/// <summary>
|
||||
/// 满减券。
|
||||
/// </summary>
|
||||
AmountOff = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 折扣券。
|
||||
/// </summary>
|
||||
Discount = 2,
|
||||
|
||||
/// <summary>
|
||||
/// 免配送费券。
|
||||
/// </summary>
|
||||
FreeShipping = 3
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace TakeoutSaaS.Domain.Coupons.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 新客礼包类型。
|
||||
/// </summary>
|
||||
public enum NewCustomerGiftType
|
||||
{
|
||||
/// <summary>
|
||||
/// 优惠券包。
|
||||
/// </summary>
|
||||
Coupon = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 首单直减。
|
||||
/// </summary>
|
||||
Direct = 2
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace TakeoutSaaS.Domain.Coupons.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 邀请记录订单状态。
|
||||
/// </summary>
|
||||
public enum NewCustomerInviteOrderStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 待下单。
|
||||
/// </summary>
|
||||
PendingOrder = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 已下单。
|
||||
/// </summary>
|
||||
Ordered = 2
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace TakeoutSaaS.Domain.Coupons.Enums;
|
||||
|
||||
/// <summary>
|
||||
/// 邀请奖励发放状态。
|
||||
/// </summary>
|
||||
public enum NewCustomerInviteRewardStatus
|
||||
{
|
||||
/// <summary>
|
||||
/// 待触发。
|
||||
/// </summary>
|
||||
Pending = 1,
|
||||
|
||||
/// <summary>
|
||||
/// 已发放。
|
||||
/// </summary>
|
||||
Issued = 2
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
using TakeoutSaaS.Domain.Coupons.Entities;
|
||||
|
||||
namespace TakeoutSaaS.Domain.Coupons.Repositories;
|
||||
|
||||
/// <summary>
|
||||
/// 新客有礼仓储契约。
|
||||
/// </summary>
|
||||
public interface INewCustomerGiftRepository
|
||||
{
|
||||
/// <summary>
|
||||
/// 查询门店配置。
|
||||
/// </summary>
|
||||
Task<NewCustomerGiftSetting?> FindSettingByStoreIdAsync(
|
||||
long tenantId,
|
||||
long storeId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 新增门店配置。
|
||||
/// </summary>
|
||||
Task AddSettingAsync(NewCustomerGiftSetting entity, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 更新门店配置。
|
||||
/// </summary>
|
||||
Task UpdateSettingAsync(NewCustomerGiftSetting entity, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 查询门店全部券规则。
|
||||
/// </summary>
|
||||
Task<IReadOnlyList<NewCustomerCouponRule>> GetCouponRulesByStoreIdAsync(
|
||||
long tenantId,
|
||||
long storeId,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 替换门店券规则集合。
|
||||
/// </summary>
|
||||
Task ReplaceCouponRulesAsync(
|
||||
long tenantId,
|
||||
long storeId,
|
||||
IReadOnlyCollection<NewCustomerCouponRule> entities,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 分页查询邀请记录。
|
||||
/// </summary>
|
||||
Task<(IReadOnlyList<NewCustomerInviteRecord> Items, int TotalCount)> GetInviteRecordsAsync(
|
||||
long tenantId,
|
||||
long storeId,
|
||||
int page,
|
||||
int pageSize,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 新增邀请记录。
|
||||
/// </summary>
|
||||
Task AddInviteRecordAsync(NewCustomerInviteRecord entity, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 按业务键查询成长记录。
|
||||
/// </summary>
|
||||
Task<NewCustomerGrowthRecord?> FindGrowthRecordByCustomerKeyAsync(
|
||||
long tenantId,
|
||||
long storeId,
|
||||
string customerKey,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 新增成长记录。
|
||||
/// </summary>
|
||||
Task AddGrowthRecordAsync(NewCustomerGrowthRecord entity, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 更新成长记录。
|
||||
/// </summary>
|
||||
Task UpdateGrowthRecordAsync(NewCustomerGrowthRecord entity, CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 统计时间范围内注册新客数。
|
||||
/// </summary>
|
||||
Task<int> CountRegisteredCustomersAsync(
|
||||
long tenantId,
|
||||
long storeId,
|
||||
DateTime startAt,
|
||||
DateTime endAt,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 统计时间范围内礼包已领取数。
|
||||
/// </summary>
|
||||
Task<int> CountGiftClaimedCustomersAsync(
|
||||
long tenantId,
|
||||
long storeId,
|
||||
DateTime startAt,
|
||||
DateTime endAt,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 统计时间范围内首单完成数。
|
||||
/// </summary>
|
||||
Task<int> CountFirstOrderedCustomersAsync(
|
||||
long tenantId,
|
||||
long storeId,
|
||||
DateTime startAt,
|
||||
DateTime endAt,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
/// <summary>
|
||||
/// 持久化变更。
|
||||
/// </summary>
|
||||
Task SaveChangesAsync(CancellationToken cancellationToken = default);
|
||||
}
|
||||
Reference in New Issue
Block a user