健康师薪酬计算规则梳理-额外数据与金三角战队业绩整合逻辑.md
15.8 KB
健康师薪酬计算规则梳理 - 额外数据与金三角战队业绩整合逻辑
一、核心问题
健康师的额外数据(lq_salary_extra_calculation 表)会影响健康师的业绩计算,变动后的业绩需要整合到金三角战队业绩中。
二、数据流程梳理
2.1 数据来源
1. 基础业绩数据
- 表名:
lq_kd_jksyj(健康师业绩表) - 字段:
jkszh: 健康师账号/IDjksyj: 健康师业绩(字符串类型,需转换)PerformanceType: 业绩类型("基础业绩" 或 "合作业绩")yjsj: 业绩时间glkdbh: 关联开单编号
2. 额外计算数据
- 表名:
lq_salary_extra_calculation(健康师工资额外计算表) - 关键字段:
F_EmployeeId: 健康师IDF_Year: 年份F_Month: 月份F_BaseRewardPerformance: 基础奖励业绩(需从基础业绩中扣除)F_CooperationRewardPerformance: 合作奖励业绩(需从合作业绩中扣除)F_OtherPerformanceAdd: 其他业绩加(需加到总业绩中)F_OtherPerformanceSubtract: 其他业绩减(需从总业绩中扣除)F_NewCustomerPerformance: 新客业绩(可能被额外数据覆盖)F_UpgradePerformance: 升单业绩(可能被额外数据覆盖)
3. 退款数据
- 表名:
lq_hytk_jksyj(退款健康师业绩表) - 作用: 从总业绩中扣除退款金额
4. 金三角战队数据
- 表名:
lq_jinsanjiao_user(金三角用户表) - 表名:
lq_ycsd_jsj(金三角基础信息表) - 作用: 确定健康师所属的战队
2.2 当前计算流程(代码位置:LqSalaryService.cs 的 CalculateHealthCoachSalary 方法)
步骤1: 计算基础业绩数据(第563-591行)
// 2.1 计算个人业绩
var myPerf = performanceData.Where(x => x.Jks == empId).ToList();
salary.BasePerformance = myPerf.Where(x => (x.PerformanceType ?? "").Trim() == "基础业绩")
.Sum(x => decimal.Parse(x.Jksyj ?? "0"));
salary.CooperationPerformance = myPerf.Where(x => (x.PerformanceType ?? "").Trim() == "合作业绩")
.Sum(x => decimal.Parse(x.Jksyj ?? "0"));
salary.TotalPerformance = myPerf.Sum(x => decimal.Parse(x.Jksyj ?? "0")); // 第567行
// 扣除退款
var myRefunds = refundList.Where(x => x.Jks == empId).ToList();
if (myRefunds.Any())
{
decimal totalRefund = myRefunds.Sum(x => x.Jksyj ?? 0);
salary.TotalPerformance -= totalRefund; // 第584行
salary.BasePerformance -= baseRefund;
salary.CooperationPerformance -= cooperationRefund;
}
// 新客与升单业绩(从开单记录中统计)
salary.NewCustomerPerformance = myPerf.Where(x => string.Equals(x.Sfskdd, "是"))
.Sum(x => decimal.Parse(x.Jksyj ?? "0"));
salary.UpgradePerformance = myPerf.Where(x => string.Equals(x.Sfskdd, "否"))
.Sum(x => decimal.Parse(x.Jksyj ?? "0"));
当前问题:
TotalPerformance只统计了开单业绩并扣除了退款- 没有加上
OtherPerformanceAdd - 没有减去
OtherPerformanceSubtract
步骤2: 填充额外计算数据(第593-605行)
// 2.1.1 填充额外计算数据
if (extraCalculationDict.ContainsKey(empId))
{
var extraData = extraCalculationDict[empId];
salary.BaseRewardPerformance = extraData.BaseRewardPerformance;
salary.CooperationRewardPerformance = extraData.CooperationRewardPerformance;
salary.OtherPerformanceAdd = extraData.OtherPerformanceAdd; // 第599行
salary.OtherPerformanceSubtract = extraData.OtherPerformanceSubtract; // 第600行
salary.UpgradeCustomerCount = extraData.UpgradeCustomerCount;
salary.NewCustomerConversionRate = extraData.NewCustomerConversionRate;
salary.NewCustomerPerformance = extraData.NewCustomerPerformance; // 可能覆盖之前的值
salary.UpgradePerformance = extraData.UpgradePerformance; // 可能覆盖之前的值
}
说明:
- 额外数据被填充到工资统计对象中
NewCustomerPerformance和UpgradePerformance可能被额外数据覆盖
步骤3: 计算实际基础业绩和实际合作业绩(第607-636行)
// 2.1.2 计算实际基础业绩和实际合作业绩
// 实际基础业绩 = 基础业绩 - 基础奖励业绩 + 其他业绩加 - 其他业绩减
decimal actualBasePerformance = salary.BasePerformance
- salary.BaseRewardPerformance
+ salary.OtherPerformanceAdd // 第615行:只影响实际基础业绩
- salary.OtherPerformanceSubtract; // 第616行:只影响实际基础业绩
// 新店额外调整:根据阶段扣除新客业绩或升单业绩
if (isNewStore)
{
if (newStoreStage == 1)
{
actualBasePerformance -= salary.NewCustomerPerformance;
}
else if (newStoreStage == 2)
{
actualBasePerformance -= salary.UpgradePerformance;
}
}
salary.ActualBasePerformance = actualBasePerformance;
// 实际合作业绩 = 合作业绩 - 合作奖励业绩
salary.ActualCooperationPerformance = salary.CooperationPerformance - salary.CooperationRewardPerformance;
当前问题:
OtherPerformanceAdd和OtherPerformanceSubtract只用于计算ActualBasePerformance- 没有用于调整
TotalPerformance
步骤4: 计算金三角战队业绩(第700-753行)
// 3. 处理战队逻辑 (考勤规则)
// 规则:若出勤天数 < 20天,则该健康师不计入战队,按单人计算。
// 按战队分组
var teamGroups = employeeStats.Values
.Where(x => !string.IsNullOrEmpty(x.GoldTriangleId))
.GroupBy(x => x.GoldTriangleId)
.ToList();
foreach (var group in teamGroups)
{
var validMembers = new List<LqSalaryStatisticsEntity>();
var invalidMembers = new List<LqSalaryStatisticsEntity>();
foreach (var member in group)
{
if (member.WorkingDays >= 20)
{
validMembers.Add(member);
}
else
{
invalidMembers.Add(member);
}
}
// 对于无效成员,移除战队标识,视为单人
foreach (var member in invalidMembers)
{
member.GoldTriangleId = null;
member.GoldTriangleTeam = "个人";
member.Position = "健康师";
}
// 计算有效战队的总业绩和总消耗
var teamTotalPerformance = validMembers.Sum(x => x.TotalPerformance); // 第735行
var teamTotalConsumption = validMembers.Sum(x => x.Consumption);
// 更新有效成员的战队业绩和战队总消耗
foreach (var member in validMembers)
{
member.TeamPerformance = teamTotalPerformance; // 第741行
member.TeamTotalConsumption = teamTotalConsumption;
}
}
// 补充处理:对于没有战队ID的(个人,或被剔除的),战队业绩等于个人总业绩
foreach (var salary in employeeStats.Values)
{
if (string.IsNullOrEmpty(salary.GoldTriangleId))
{
salary.TeamPerformance = salary.TotalPerformance; // 第751行
}
}
当前问题:
- 第735行计算战队总业绩时,使用的是
x.TotalPerformance - 但
TotalPerformance没有包含额外数据的调整(OtherPerformanceAdd和OtherPerformanceSubtract) - 因此,金三角战队业绩没有整合变动后的业绩
三、问题分析
3.1 核心问题
总业绩未包含额外数据调整
TotalPerformance只统计了开单业绩并扣除了退款- 没有加上
OtherPerformanceAdd - 没有减去
OtherPerformanceSubtract
金三角战队业绩计算不准确
- 战队业绩 = 所有有效成员的总业绩之和
- 但使用的是未调整的
TotalPerformance - 导致额外数据的变动没有反映到战队业绩中
3.2 影响范围
- 健康师个人总业绩: 不准确(缺少额外数据调整)
- 金三角战队业绩: 不准确(基于不准确的个人总业绩)
- 提成计算: 可能受影响(如果提成计算依赖
TotalPerformance) - 业绩占比: 不准确(个人业绩占比 = 个人总业绩 / 战队总业绩)
四、解决方案建议
4.1 方案一:在计算总业绩时直接加上额外数据调整
修改位置: LqSalaryService.cs 第567-605行
修改逻辑:
// 2.1 计算个人业绩
var myPerf = performanceData.Where(x => x.Jks == empId).ToList();
salary.BasePerformance = myPerf.Where(x => (x.PerformanceType ?? "").Trim() == "基础业绩")
.Sum(x => decimal.Parse(x.Jksyj ?? "0"));
salary.CooperationPerformance = myPerf.Where(x => (x.PerformanceType ?? "").Trim() == "合作业绩")
.Sum(x => decimal.Parse(x.Jksyj ?? "0"));
salary.TotalPerformance = myPerf.Sum(x => decimal.Parse(x.Jksyj ?? "0"));
// 扣除退款
var myRefunds = refundList.Where(x => x.Jks == empId).ToList();
if (myRefunds.Any())
{
decimal totalRefund = myRefunds.Sum(x => x.Jksyj ?? 0);
salary.TotalPerformance -= totalRefund;
salary.BasePerformance -= baseRefund;
salary.CooperationPerformance -= cooperationRefund;
}
// 新客与升单业绩(从开单记录中统计)
salary.NewCustomerPerformance = myPerf.Where(x => string.Equals(x.Sfskdd, "是"))
.Sum(x => decimal.Parse(x.Jksyj ?? "0"));
salary.UpgradePerformance = myPerf.Where(x => string.Equals(x.Sfskdd, "否"))
.Sum(x => decimal.Parse(x.Jksyj ?? "0"));
// 2.1.1 填充额外计算数据
if (extraCalculationDict.ContainsKey(empId))
{
var extraData = extraCalculationDict[empId];
salary.BaseRewardPerformance = extraData.BaseRewardPerformance;
salary.CooperationRewardPerformance = extraData.CooperationRewardPerformance;
salary.OtherPerformanceAdd = extraData.OtherPerformanceAdd;
salary.OtherPerformanceSubtract = extraData.OtherPerformanceSubtract;
salary.UpgradeCustomerCount = extraData.UpgradeCustomerCount;
salary.NewCustomerConversionRate = extraData.NewCustomerConversionRate;
salary.NewCustomerPerformance = extraData.NewCustomerPerformance;
salary.UpgradePerformance = extraData.UpgradePerformance;
// 【新增】调整总业绩:加上其他业绩加,减去其他业绩减
salary.TotalPerformance += salary.OtherPerformanceAdd;
salary.TotalPerformance -= salary.OtherPerformanceSubtract;
}
优点:
- 简单直接,在填充额外数据后立即调整总业绩
- 确保后续所有使用
TotalPerformance的地方都能获取到调整后的值
缺点:
- 需要确认
OtherPerformanceAdd和OtherPerformanceSubtract是否应该影响总业绩 - 需要确认是否应该影响基础业绩或合作业绩
4.2 方案二:在计算战队业绩前调整总业绩
修改位置: LqSalaryService.cs 第700-753行
修改逻辑:
// 3. 处理战队逻辑 (考勤规则)
// 规则:若出勤天数 < 20天,则该健康师不计入战队,按单人计算。
// 【新增】在计算战队业绩前,先调整所有健康师的总业绩(加上额外数据)
foreach (var salary in employeeStats.Values)
{
salary.TotalPerformance += salary.OtherPerformanceAdd;
salary.TotalPerformance -= salary.OtherPerformanceSubtract;
}
// 按战队分组
var teamGroups = employeeStats.Values
.Where(x => !string.IsNullOrEmpty(x.GoldTriangleId))
.GroupBy(x => x.GoldTriangleId)
.ToList();
// ... 后续逻辑不变
优点:
- 集中处理,逻辑清晰
- 确保在计算战队业绩前,所有成员的总业绩都已调整
缺点:
- 如果其他地方也使用
TotalPerformance,可能也需要调整
4.3 方案三:使用调整后的总业绩字段
修改逻辑:
- 保持
TotalPerformance不变(原始总业绩) - 新增
AdjustedTotalPerformance字段(调整后的总业绩) - 在计算战队业绩时使用
AdjustedTotalPerformance
优点:
- 保留原始数据,便于追溯
- 明确区分原始业绩和调整后业绩
缺点:
- 需要修改数据库表结构
- 需要修改所有使用总业绩的地方
五、推荐方案
推荐使用方案一,原因:
- 逻辑简单,在填充额外数据后立即调整总业绩
- 确保后续所有使用
TotalPerformance的地方都能获取到调整后的值 - 不需要修改数据库表结构
- 符合业务逻辑:额外数据应该影响总业绩
六、需要确认的问题
OtherPerformanceAdd和OtherPerformanceSubtract是否应该影响总业绩?- 当前代码中,这两个字段只影响
ActualBasePerformance - 需要确认业务规则:是否应该同时影响
TotalPerformance
- 当前代码中,这两个字段只影响
额外数据中的
NewCustomerPerformance和UpgradePerformance是否应该覆盖从开单记录中统计的值?- 当前代码中,如果存在额外数据,会覆盖之前统计的值
- 需要确认业务规则:是覆盖还是累加?
额外数据是否应该影响基础业绩或合作业绩?
- 当前代码中,
OtherPerformanceAdd和OtherPerformanceSubtract只影响ActualBasePerformance - 需要确认:是否应该同时调整
BasePerformance或CooperationPerformance?
- 当前代码中,
金三角战队业绩的计算时机
- 当前在计算战队业绩时,使用的是
TotalPerformance - 如果
TotalPerformance没有包含额外数据调整,战队业绩就不准确 - 需要确认:是否应该在计算战队业绩前,先调整所有成员的总业绩?
- 当前在计算战队业绩时,使用的是
七、代码修改建议
7.1 修改位置
文件: netcore/src/Modularity/Extend/NCC.Extend/LqSalaryService.cs
方法: CalculateHealthCoachSalary
位置: 第593-605行(填充额外计算数据后)
7.2 修改内容
在填充额外计算数据后,立即调整总业绩:
// 2.1.1 填充额外计算数据
if (extraCalculationDict.ContainsKey(empId))
{
var extraData = extraCalculationDict[empId];
salary.BaseRewardPerformance = extraData.BaseRewardPerformance;
salary.CooperationRewardPerformance = extraData.CooperationRewardPerformance;
salary.OtherPerformanceAdd = extraData.OtherPerformanceAdd;
salary.OtherPerformanceSubtract = extraData.OtherPerformanceSubtract;
salary.UpgradeCustomerCount = extraData.UpgradeCustomerCount;
salary.NewCustomerConversionRate = extraData.NewCustomerConversionRate;
salary.NewCustomerPerformance = extraData.NewCustomerPerformance;
salary.UpgradePerformance = extraData.UpgradePerformance;
// 【新增】调整总业绩:加上其他业绩加,减去其他业绩减
// 注意:这里调整的是总业绩,确保后续计算(包括战队业绩)使用的是调整后的值
salary.TotalPerformance += salary.OtherPerformanceAdd;
salary.TotalPerformance -= salary.OtherPerformanceSubtract;
}
7.3 影响分析
修改后的影响:
- ✅ 健康师个人总业绩包含额外数据调整
- ✅ 金三角战队业绩 = 所有有效成员的调整后总业绩之和
- ✅ 提成计算(如果依赖
TotalPerformance)会使用调整后的值 - ✅ 业绩占比计算会使用调整后的值
需要注意:
- 确保
OtherPerformanceAdd和OtherPerformanceSubtract的值是正确的 - 确保额外数据表(
lq_salary_extra_calculation)的数据是准确的 - 如果后续有其他地方也使用
TotalPerformance,需要确认是否应该使用调整后的值
八、测试建议
单元测试:
- 测试额外数据为0时,总业绩不变
- 测试
OtherPerformanceAdd > 0时,总业绩增加 - 测试
OtherPerformanceSubtract > 0时,总业绩减少 - 测试两者同时存在时的计算
集成测试:
- 测试单个健康师的额外数据调整后,总业绩是否正确
- 测试战队中多个成员都有额外数据时,战队总业绩是否正确
- 测试战队中部分成员有额外数据时,战队总业绩是否正确
数据验证:
- 对比修改前后的计算结果
- 验证金三角战队业绩是否包含额外数据调整
- 验证业绩占比计算是否正确
文档版本: v1.0
创建日期: 2026-01-09
适用范围: 健康师薪酬计算 - 额外数据与金三角战队业绩整合