All checks were successful
Build and Deploy / deploy (push) Successful in 3m50s
Co-authored-by: Cursor <cursoragent@cursor.com>
119 lines
4.1 KiB
C#
119 lines
4.1 KiB
C#
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;
|
||
}
|
||
}
|