256 lines
8.3 KiB
C#
256 lines
8.3 KiB
C#
|
|
using YD_Event.Core.Enum;
|
|||
|
|
|
|||
|
|
namespace YD_Event.Core.Domain.Pricing;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 赛事定价计算服务
|
|||
|
|
/// 所有金额计算均以此服务为准,确保计算结果的一致性
|
|||
|
|
/// </summary>
|
|||
|
|
public static class EventPricingService
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 赛事基础定价(元)
|
|||
|
|
/// </summary>
|
|||
|
|
public const decimal EventBasePrice = 1000m;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 项目A定价(元)
|
|||
|
|
/// </summary>
|
|||
|
|
public const decimal ProjectAPrice = 500m;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 项目B定价(元)
|
|||
|
|
/// </summary>
|
|||
|
|
public const decimal ProjectBPrice = 1000m;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 定价计算输入参数
|
|||
|
|
/// </summary>
|
|||
|
|
public class PricingInput
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 收费模式
|
|||
|
|
/// </summary>
|
|||
|
|
public ChargeMode ChargeMode { get; set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 参赛人数
|
|||
|
|
/// </summary>
|
|||
|
|
public int ParticipantCount { get; set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 项目列表(单价项目模式使用)
|
|||
|
|
/// </summary>
|
|||
|
|
public List<ProjectPricingInfo> Projects { get; set; } = new List<ProjectPricingInfo>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 项目定价信息
|
|||
|
|
/// </summary>
|
|||
|
|
public class ProjectPricingInfo
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 项目ID
|
|||
|
|
/// </summary>
|
|||
|
|
public long ProjectId { get; set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 项目名称
|
|||
|
|
/// </summary>
|
|||
|
|
public string ProjectName { get; set; } = string.Empty;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 项目单价(元)
|
|||
|
|
/// </summary>
|
|||
|
|
public decimal UnitPrice { get; set; }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 定价计算结果
|
|||
|
|
/// </summary>
|
|||
|
|
public class PricingResult
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 总金额(精确到分)
|
|||
|
|
/// </summary>
|
|||
|
|
public decimal TotalAmount { get; set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 总人数
|
|||
|
|
/// </summary>
|
|||
|
|
public int TotalPersonCount { get; set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 费用明细
|
|||
|
|
/// </summary>
|
|||
|
|
public List<PricingDetailItem> Details { get; set; } = new List<PricingDetailItem>();
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 计算日志(用于审计)
|
|||
|
|
/// </summary>
|
|||
|
|
public List<string> CalculationLogs { get; set; } = new List<string>();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 费用明细项
|
|||
|
|
/// </summary>
|
|||
|
|
public class PricingDetailItem
|
|||
|
|
{
|
|||
|
|
/// <summary>
|
|||
|
|
/// 项目名称
|
|||
|
|
/// </summary>
|
|||
|
|
public string ItemName { get; set; } = string.Empty;
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 单价
|
|||
|
|
/// </summary>
|
|||
|
|
public decimal UnitPrice { get; set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 数量
|
|||
|
|
/// </summary>
|
|||
|
|
public int Quantity { get; set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 小计
|
|||
|
|
/// </summary>
|
|||
|
|
public decimal Subtotal { get; set; }
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 备注
|
|||
|
|
/// </summary>
|
|||
|
|
public string? Remark { get; set; }
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 计算赛事报名费用
|
|||
|
|
/// </summary>
|
|||
|
|
/// <param name="input">定价计算输入</param>
|
|||
|
|
/// <returns>定价计算结果</returns>
|
|||
|
|
public static PricingResult Calculate(PricingInput input)
|
|||
|
|
{
|
|||
|
|
var result = new PricingResult
|
|||
|
|
{
|
|||
|
|
TotalPersonCount = input.ParticipantCount
|
|||
|
|
};
|
|||
|
|
|
|||
|
|
result.CalculationLogs.Add($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 开始计算费用,收费模式: {input.ChargeMode}, 人数: {input.ParticipantCount}");
|
|||
|
|
|
|||
|
|
switch (input.ChargeMode)
|
|||
|
|
{
|
|||
|
|
case ChargeMode.Free:
|
|||
|
|
CalculateFreeMode(result);
|
|||
|
|
break;
|
|||
|
|
case ChargeMode.FixedPrice:
|
|||
|
|
CalculateFixedPriceMode(result, input.ParticipantCount);
|
|||
|
|
break;
|
|||
|
|
case ChargeMode.UnitPriceEvent:
|
|||
|
|
CalculateUnitPriceEventMode(result, input.ParticipantCount);
|
|||
|
|
break;
|
|||
|
|
case ChargeMode.UnitPriceProject:
|
|||
|
|
CalculateUnitPriceProjectMode(result, input.Projects, input.ParticipantCount);
|
|||
|
|
break;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// 确保金额精确到分
|
|||
|
|
result.TotalAmount = Math.Round(result.TotalAmount, 2, MidpointRounding.AwayFromZero);
|
|||
|
|
result.CalculationLogs.Add($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 最终总金额: {result.TotalAmount:F2} 元");
|
|||
|
|
|
|||
|
|
return result;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 免费模式
|
|||
|
|
/// </summary>
|
|||
|
|
private static void CalculateFreeMode(PricingResult result)
|
|||
|
|
{
|
|||
|
|
result.TotalAmount = 0;
|
|||
|
|
result.Details.Add(new PricingDetailItem
|
|||
|
|
{
|
|||
|
|
ItemName = "报名费",
|
|||
|
|
UnitPrice = 0,
|
|||
|
|
Quantity = 1,
|
|||
|
|
Subtotal = 0,
|
|||
|
|
Remark = "免费"
|
|||
|
|
});
|
|||
|
|
result.CalculationLogs.Add($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 免费模式,总金额: 0 元");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 定价(赛事)模式:固定为1000元/场,无论参赛主体是个人还是单位,也无论参赛项目数量多少,均统一按1000元计算
|
|||
|
|
/// </summary>
|
|||
|
|
private static void CalculateFixedPriceMode(PricingResult result, int participantCount)
|
|||
|
|
{
|
|||
|
|
var price = EventBasePrice;
|
|||
|
|
result.TotalAmount = price;
|
|||
|
|
result.Details.Add(new PricingDetailItem
|
|||
|
|
{
|
|||
|
|
ItemName = "赛事报名费",
|
|||
|
|
UnitPrice = price,
|
|||
|
|
Quantity = 1,
|
|||
|
|
Subtotal = price,
|
|||
|
|
Remark = $"固定价格 {EventBasePrice:F2} 元/场,参赛人数: {participantCount} 人"
|
|||
|
|
});
|
|||
|
|
result.CalculationLogs.Add($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 定价(赛事)模式: 固定价格 {EventBasePrice:F2} 元/场");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 单价(赛事)模式:赛事基础定价为1000元,个人参赛按1000元计算;团队参赛按人数乘以1000元计算
|
|||
|
|
/// </summary>
|
|||
|
|
private static void CalculateUnitPriceEventMode(PricingResult result, int participantCount)
|
|||
|
|
{
|
|||
|
|
var unitPrice = EventBasePrice;
|
|||
|
|
var totalAmount = unitPrice * participantCount;
|
|||
|
|
result.TotalAmount = totalAmount;
|
|||
|
|
result.Details.Add(new PricingDetailItem
|
|||
|
|
{
|
|||
|
|
ItemName = "赛事报名费",
|
|||
|
|
UnitPrice = unitPrice,
|
|||
|
|
Quantity = participantCount,
|
|||
|
|
Subtotal = totalAmount,
|
|||
|
|
Remark = participantCount == 1
|
|||
|
|
? $"个人参赛 {unitPrice:F2} 元"
|
|||
|
|
: $"团队参赛 {unitPrice:F2} 元/人 × {participantCount} 人"
|
|||
|
|
});
|
|||
|
|
result.CalculationLogs.Add($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 单价(赛事)模式: {unitPrice:F2} 元/人 × {participantCount} 人 = {totalAmount:F2} 元");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
/// <summary>
|
|||
|
|
/// 单价(项目)模式:按具体项目定价计算,个人参加多项时,费用为各项单价之和;团队参加多项时,费用为(各项单价之和)×团队人数
|
|||
|
|
/// </summary>
|
|||
|
|
private static void CalculateUnitPriceProjectMode(PricingResult result, List<ProjectPricingInfo> projects, int participantCount)
|
|||
|
|
{
|
|||
|
|
decimal totalProjectPrice = 0;
|
|||
|
|
|
|||
|
|
foreach (var project in projects)
|
|||
|
|
{
|
|||
|
|
totalProjectPrice += project.UnitPrice;
|
|||
|
|
result.Details.Add(new PricingDetailItem
|
|||
|
|
{
|
|||
|
|
ItemName = project.ProjectName,
|
|||
|
|
UnitPrice = project.UnitPrice,
|
|||
|
|
Quantity = 1,
|
|||
|
|
Subtotal = project.UnitPrice,
|
|||
|
|
Remark = "项目单价"
|
|||
|
|
});
|
|||
|
|
result.CalculationLogs.Add($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 项目: {project.ProjectName}, 单价: {project.UnitPrice:F2} 元");
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
var totalAmount = totalProjectPrice * participantCount;
|
|||
|
|
result.TotalAmount = totalAmount;
|
|||
|
|
|
|||
|
|
// 添加汇总项
|
|||
|
|
result.Details.Add(new PricingDetailItem
|
|||
|
|
{
|
|||
|
|
ItemName = participantCount == 1 ? "项目总价" : "项目总价 × 人数",
|
|||
|
|
UnitPrice = totalProjectPrice,
|
|||
|
|
Quantity = participantCount,
|
|||
|
|
Subtotal = totalAmount,
|
|||
|
|
Remark = participantCount == 1
|
|||
|
|
? $"个人参赛,项目总价 {totalProjectPrice:F2} 元"
|
|||
|
|
: $"团队参赛,({totalProjectPrice:F2} 元) × {participantCount} 人"
|
|||
|
|
});
|
|||
|
|
result.CalculationLogs.Add($"[{DateTime.Now:yyyy-MM-dd HH:mm:ss}] 单价(项目)模式: 项目总价 {totalProjectPrice:F2} 元 × {participantCount} 人 = {totalAmount:F2} 元");
|
|||
|
|
}
|
|||
|
|
}
|