?????????????????????????????????? SQL? Co-authored-by: Cursor <cursoragent@cursor.com>
146 lines
5.3 KiB
C#
146 lines
5.3 KiB
C#
using Fake.Application;
|
||
using Fake.Domain.Exceptions;
|
||
using Oms.Domain.CustomersAggregate.Entities;
|
||
using Oms.Domain.CustomersAggregate.Enums;
|
||
using Oms.Domain.CustomersAggregate.Repositories;
|
||
using Oms.Domain.MarketingAggregate.Entities;
|
||
using Oms.Domain.MarketingAggregate.Repositories;
|
||
using Oms.Domain.Shared.Enums;
|
||
|
||
namespace Oms.Application.Shared;
|
||
|
||
/// <summary>
|
||
/// 营销域主客户解析与价区键。
|
||
/// </summary>
|
||
public static class MarketingCustomerHelper
|
||
{
|
||
/// <summary>缺省/空价区键回落(卖价 JSON 标准键)。</summary>
|
||
public const string FallbackPriceTierKey = "普通客户";
|
||
|
||
/// <summary>新注册客户默认价区键(与会员等级名称对齐为「普通会员」)。</summary>
|
||
public const string DefaultNewCustomerPriceTierKey = "普通会员";
|
||
|
||
/// <summary>新注册客户默认会员等级编码/名称。</summary>
|
||
public const string DefaultMemberLevelName = "普通会员";
|
||
|
||
public static async Task<Customer> ResolveMarketingMainCustomerAsync(
|
||
ICustomerRepository customerRepository,
|
||
Customer sessionCustomer,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
ArgumentNullException.ThrowIfNull(sessionCustomer);
|
||
|
||
if (!sessionCustomer.ParentCustomerId.HasValue)
|
||
{
|
||
return sessionCustomer;
|
||
}
|
||
|
||
var mainCustomer = await customerRepository.FirstOrDefaultAsync(
|
||
x => x.Id == sessionCustomer.ParentCustomerId.Value,
|
||
cancellationToken);
|
||
if (mainCustomer == null)
|
||
{
|
||
throw new BusinessException("主客户不存在");
|
||
}
|
||
|
||
return mainCustomer;
|
||
}
|
||
|
||
public static async Task<int> ResolveMarketingMainCustomerIdAsync(
|
||
ICustomerRepository customerRepository,
|
||
Customer sessionCustomer,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
var main = await ResolveMarketingMainCustomerAsync(customerRepository, sessionCustomer, cancellationToken);
|
||
return main.Id;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 解析用于计价的价区键:主客户.PriceTierKey;空则回落「普通客户」。与会员等级无关。
|
||
/// </summary>
|
||
public static async Task<string?> ResolvePriceTierKeyAsync(
|
||
ICustomerRepository customerRepository,
|
||
IMemberLevelRepository memberLevelRepository,
|
||
int? customerId,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
// memberLevelRepository 保留参数以兼容既有调用方签名;价区已与等级解耦。
|
||
_ = memberLevelRepository;
|
||
|
||
if (!customerId.HasValue || customerId.Value <= 0)
|
||
{
|
||
return FallbackPriceTierKey;
|
||
}
|
||
|
||
var sessionCustomer = await customerRepository.FirstOrDefaultAsync(x => x.Id == customerId.Value, cancellationToken);
|
||
if (sessionCustomer == null)
|
||
{
|
||
return FallbackPriceTierKey;
|
||
}
|
||
|
||
var mainCustomer = sessionCustomer.ParentCustomerId.HasValue
|
||
? await customerRepository.FirstOrDefaultAsync(x => x.Id == sessionCustomer.ParentCustomerId.Value, cancellationToken)
|
||
: sessionCustomer;
|
||
if (mainCustomer == null)
|
||
{
|
||
return FallbackPriceTierKey;
|
||
}
|
||
|
||
if (!string.IsNullOrWhiteSpace(mainCustomer.PriceTierKey))
|
||
{
|
||
return mainCustomer.PriceTierKey.Trim();
|
||
}
|
||
|
||
// 兼容未回填客户:短暂回退遗留 CustomerGroup,最终仍归一到标准键
|
||
return MapCustomerGroupToPriceTierKey(mainCustomer.CustomerGroup) ?? FallbackPriceTierKey;
|
||
}
|
||
|
||
public static string NormalizePriceTierKeyOrDefault(string? priceTierKey)
|
||
{
|
||
return string.IsNullOrWhiteSpace(priceTierKey) ? FallbackPriceTierKey : priceTierKey.Trim();
|
||
}
|
||
|
||
/// <summary>新客默认价区键。</summary>
|
||
public static string ResolveNewCustomerPriceTierKey(string? input) =>
|
||
string.IsNullOrWhiteSpace(input) ? DefaultNewCustomerPriceTierKey : input.Trim();
|
||
|
||
/// <summary>
|
||
/// 解析默认「普通会员」等级 Id;不存在则取启用等级中 MinPoints 最低者。
|
||
/// </summary>
|
||
public static async Task<int?> ResolveDefaultMemberLevelIdAsync(
|
||
IMemberLevelRepository memberLevelRepository,
|
||
CancellationToken cancellationToken = default)
|
||
{
|
||
var named = await memberLevelRepository.FirstOrDefaultAsync(
|
||
x => x.Status == EnableStatus.Enabled
|
||
&& (x.LevelName == DefaultMemberLevelName || x.LevelCode == DefaultMemberLevelName),
|
||
cancellationToken);
|
||
if (named != null)
|
||
{
|
||
return named.Id;
|
||
}
|
||
|
||
var levels = await memberLevelRepository.GetAllEnabledOrderedAsync(cancellationToken);
|
||
return levels.OrderBy(x => x.MinPoints).ThenBy(x => x.Sort).ThenBy(x => x.Id).FirstOrDefault()?.Id;
|
||
}
|
||
|
||
public static string? MapCustomerGroupToPriceTierKey(CustomerGroup? customerGroup)
|
||
{
|
||
if (!customerGroup.HasValue)
|
||
{
|
||
return FallbackPriceTierKey;
|
||
}
|
||
|
||
return customerGroup.Value switch
|
||
{
|
||
CustomerGroup.Normal => FallbackPriceTierKey,
|
||
CustomerGroup.Vip1 => "客户组1",
|
||
CustomerGroup.Vip2 => "客户组2",
|
||
CustomerGroup.Vip3 => "客户组3",
|
||
CustomerGroup.Vip4 => "客户组4",
|
||
CustomerGroup.Vip5 => "客户组5",
|
||
_ => FallbackPriceTierKey
|
||
};
|
||
}
|
||
}
|