admin/src/Oms.Application/Shared/MarketingReferralBinder.cs
zzh f972a28d79
All checks were successful
Build and Deploy / deploy (push) Successful in 3m50s
feat: 落地滚动会员、券发放与邀请分成奖励
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-06 17:40:24 +08:00

119 lines
4.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using Fake.Application;
using Fake.Domain.Exceptions;
using Oms.Domain.CustomersAggregate.Entities;
using Oms.Domain.CustomersAggregate.Repositories;
using Oms.Domain.MarketingAggregate.Entities;
using Oms.Domain.MarketingAggregate.Enums;
using Oms.Domain.MarketingAggregate.Repositories;
namespace Oms.Application.Shared;
public static class MarketingReferralBinder
{
public static async Task BindReferrerOnCreateAsync(
Customer entity,
string? inviteCode,
ICustomerReferralCodeRepository referralCodeRepository,
ICustomerRepository customerRepository,
IMemberLevelRepository? memberLevelRepository = null,
IReferralCommissionRuleRepository? commissionRuleRepository = null,
CancellationToken cancellationToken = default)
{
if (entity.ParentCustomerId.HasValue || entity.ReferrerCustomerId.HasValue)
{
return;
}
var code = inviteCode?.Trim();
if (string.IsNullOrWhiteSpace(code))
{
return;
}
var referral = await referralCodeRepository.GetByInviteCodeAsync(code, cancellationToken);
if (referral == null || referral.Status != ReferralCodeStatus.Enabled)
{
throw new BusinessException("邀请码无效或已停用");
}
// 新建时 entity.Id 多为 0,不能只靠 Id 判自引荐
if (entity.Id > 0 && referral.CustomerId == entity.Id)
{
throw new BusinessException("不能使用自己的邀请码");
}
var referrer = await customerRepository.FirstOrDefaultAsync(x => x.Id == referral.CustomerId, cancellationToken);
if (referrer == null || referrer.ParentCustomerId.HasValue)
{
throw new BusinessException("邀请码对应客户无效");
}
if (memberLevelRepository != null)
{
var minLevel = "V1";
if (commissionRuleRepository != null)
{
var rule = await commissionRuleRepository.GetActiveRuleAsync(cancellationToken);
if (!string.IsNullOrWhiteSpace(rule?.MinInviteLevelCode))
{
minLevel = rule.MinInviteLevelCode;
}
}
MemberLevel? level = null;
if (referrer.MemberLevelId.HasValue)
{
level = await memberLevelRepository.FirstOrDefaultAsync(
x => x.Id == referrer.MemberLevelId.Value, cancellationToken);
}
if (!MarketingInviteRewardCalculator.CanInvite(level?.LevelCode, minLevel))
{
throw new BusinessException("邀请人暂无邀请资格");
}
}
if (IsSameIdentity(entity, referrer))
{
throw new BusinessException("不能使用自己的邀请码");
}
entity.ReferrerCustomerId = referral.CustomerId;
entity.ReferralBindTime = DateTime.Now;
entity.ReferralChannel = "link";
}
private static bool IsSameIdentity(Customer entity, Customer referrer)
{
if (!string.IsNullOrWhiteSpace(entity.Phone) &&
!string.IsNullOrWhiteSpace(referrer.Phone) &&
string.Equals(entity.Phone.Trim(), referrer.Phone.Trim(), StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (!string.IsNullOrWhiteSpace(entity.Email) &&
!string.IsNullOrWhiteSpace(referrer.Email) &&
string.Equals(entity.Email.Trim(), referrer.Email.Trim(), StringComparison.OrdinalIgnoreCase))
{
return true;
}
if (!string.IsNullOrWhiteSpace(entity.WechatOpenid) &&
!string.IsNullOrWhiteSpace(referrer.WechatOpenid) &&
string.Equals(entity.WechatOpenid.Trim(), referrer.WechatOpenid.Trim(), StringComparison.Ordinal))
{
return true;
}
if (!string.IsNullOrWhiteSpace(entity.CustomerCode) &&
!string.IsNullOrWhiteSpace(referrer.CustomerCode) &&
string.Equals(entity.CustomerCode.Trim(), referrer.CustomerCode.Trim(), StringComparison.OrdinalIgnoreCase))
{
return true;
}
return false;
}
}