package com.kingdee.eas.custom.compensation.service; import com.kingdee.bos.BOSException; import com.kingdee.bos.Context; import com.kingdee.eas.util.app.DbUtil; import com.kingdee.jdbc.rowset.IRowSet; import com.kingdee.shr.compensation.service.CalSubmitSchemeFunctionService; import com.kingdee.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.math.BigDecimal; import java.sql.Date; import java.sql.SQLException; import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.util.*; /** * 薪酬方案计算函数服务扩展类。 *

* 提供以下薪酬计算相关的扩展函数: *

*/ public class CalSubmitSchemeFunctionServiceEx extends CalSubmitSchemeFunctionService { private static final Logger logger = LoggerFactory.getLogger(CalSubmitSchemeFunctionServiceEx.class); /** * 人才留存奖金 * @param ctx * @param paramMap * @param tempMap * @param mainTableName * @param mainTableRowFilter * @return */ public double getTalentRetentionBonus(Context ctx, Map paramMap, HashMap tempMap, String mainTableName, String mainTableRowFilter,double isFixed) { try { //todo //计算的员工id String personId = (String) paramMap.get(mainTableName.toUpperCase() + "_FPERSONID"); //计算的数据行 String id = (String) paramMap.get(mainTableName.toUpperCase() + "_FID"); String Effect = getEffect(ctx, tempMap, mainTableName, mainTableRowFilter, id); StringBuilder sql = new StringBuilder(); sql.append(" /*dialect*/ "); // 主查询:按核算表和生效月份分组统计入职人数 sql.append(" SELECT mt.fpersonid,substring(convert(varchar,mt.FEffectDate,120),0,8) FEffectDate,count(abt.pid) pNum from ").append(mainTableName).append(" mt "); // 关联子查询:通过北森应聘表匹配到人员,再关联其最近一次入职记录 sql.append(" left join ( select ab.CFRecruitOwnerID,p.fid pid,t.fbizDate bizDate "); sql.append(" from CT_REC_ApplicantBeisen ab "); sql.append(" inner join T_REC_ResumeBaseRec rb on rb.CFCANDIDATEID = ab.CFCANDIDATEID "); sql.append(" inner join t_bd_person p on isnull(p.FIDCARDNO,p.FPASSPORTNO)=isnull(rb.FIdentityCardNo,rb.FPassportNo) "); // 取每个人员最近一次入职记录(ROW_NUMBER + rn=1) sql.append(" left join ( "); sql.append(" SELECT FPERSONID, FBIZDATE "); sql.append(" FROM ( "); sql.append(" SELECT "); sql.append(" e.FPERSONID, "); sql.append(" e.FBIZDATE, "); sql.append(" ROW_NUMBER() OVER (PARTITION BY e.FPERSONID ORDER BY e.FBIZDATE DESC) AS rn "); sql.append(" FROM T_HR_EmpEnrollBizBillEntry e "); sql.append(" LEFT JOIN T_HR_EmpEnrollBizBill b ON b.fid = e.FBillID "); sql.append(" where b.FBillState=3 "); sql.append(" ) t "); sql.append(" WHERE rn = 1) t on t.fpersonid=p.fid ) abt on abt.CFRecruitOwnerID=mt.fpersonid "); // 入职日期在生效日期当月范围内:[当月第一天, 下月第一天) sql.append(" AND abt.bizDate >= DATEADD(MONTH, DATEDIFF(MONTH, 0, mt.FEffectDate), 0)"); // 当月第一天 00:00:00.000 sql.append(" AND abt.bizDate < DATEADD(MONTH, DATEDIFF(MONTH, 0, mt.FEffectDate) + 1, 0) "); // 下个月第一天 00:00:00.000 sql.append(" AND mt.fid in(").append(mainTableRowFilter).append(") group by mt.fpersonid,substring(convert(varchar,mt.FEffectDate,120),0,8) "); IRowSet rs = DbUtil.executeQuery(ctx, sql.toString()); //fixPayMap = new HashMap<>(); while (rs.next()) { //获取人数 String fpersonid = rs.getString("fpersonid"); String FEffectDate = rs.getString("FEffectDate"); int pNum = rs.getInt("pNum"); //fixPayMap.put(fpersonid + "_" + FEffectDate, pNum); } }catch (Exception e){ logger.error(e.getMessage(),e); } return 0D; } /** * 当月净增人数 = 当月入职人数 - 当月离职人数(通过招聘渠道入职但当月即离职的人员统计)。 * @param ctx 上下文 * @param paramMap 参数(含 FPERSONID、FID) * @param tempMap 临时缓存 Map * @param mainTableName 计算表对象名 * @param mainTableRowFilter 计算表数据行过滤条件 * @return 当月净增人数 */ public double getEndMonthRetainedUsers(Context ctx, Map paramMap, HashMap tempMap, String mainTableName, String mainTableRowFilter) { try { //计算的员工id String personId = (String) paramMap.get(mainTableName.toUpperCase() + "_FPERSONID"); //计算的数据行 String id = (String) paramMap.get(mainTableName.toUpperCase() + "_FID"); String Effect = getEffect(ctx, tempMap, mainTableName,mainTableRowFilter, id); // 获取当月入职人数 double ruzhiNum = getMonthRuzhiUsers(ctx, paramMap, tempMap, mainTableName, mainTableRowFilter); // 获取当月离职人数 double lizhiNum = getMonthLiZhiUsers(ctx, paramMap, tempMap, mainTableName, mainTableRowFilter); // 净增 = 入职 - 离职 return ((double) ruzhiNum - lizhiNum); } catch (Exception ex) { logger.error(ex.getMessage(), ex); //ex.printStackTrace(); } return (double) 0.0F; } /** * 当月入职人数(通过招聘渠道入职且在生效日期当月入职的人数)。 * @param ctx 上下文 * @param paramMap 参数(含 FPERSONID、FID) * @param tempMap 临时缓存 Map * @param mainTableName 计算表对象名 * @param mainTableRowFilter 计算表数据行过滤条件 * @return 当前人员在生效日期对应的当月入职人数 */ public double getMonthRuzhiUsers(Context ctx, Map paramMap, HashMap tempMap, String mainTableName, String mainTableRowFilter) { try { //计算的员工id String personId = (String) paramMap.get(mainTableName.toUpperCase() + "_FPERSONID"); //计算的数据行 String id = (String) paramMap.get(mainTableName.toUpperCase() + "_FID"); String Effect = getEffect(ctx, tempMap, mainTableName,mainTableRowFilter, id); // 入职人数缓存 key String ruZhiMapKey = "getMonthRuzhiUsers_Map"; // 查询生效日期当月入职的人数 getRuZhiPersonNum(ctx, tempMap, mainTableName, mainTableRowFilter, ruZhiMapKey); Map fixPayMap = (Map) tempMap.get(ruZhiMapKey); String key = personId + "_" + Effect; if (fixPayMap.containsKey(key)) { int num = fixPayMap.containsKey(key) ? fixPayMap.get(key) : 0; return (double) (num); } else { return (double) 0.0F; } } catch (Exception ex) { logger.error(ex.getMessage(), ex); //ex.printStackTrace(); } return (double) 0.0F; } /** * 当月转正人数(通过招聘渠道入职且在生效日期当月转正的人数)。 * @param ctx 上下文 * @param paramMap 参数(含 FPERSONID、FID) * @param tempMap 临时缓存 Map * @param mainTableName 计算表对象名 * @param mainTableRowFilter 计算表数据行过滤条件 * @return 当前人员在生效日期对应的当月转正人数 */ public double getMonthZhuanZhengUsers(Context ctx, Map paramMap, HashMap tempMap, String mainTableName, String mainTableRowFilter) { try { //计算的员工id String personId = (String) paramMap.get(mainTableName.toUpperCase() + "_FPERSONID"); //计算的数据行 String id = (String) paramMap.get(mainTableName.toUpperCase() + "_FID"); String Effect = getEffect(ctx, tempMap, mainTableName,mainTableRowFilter, id); // 转正人数缓存 key String zhuanZhengMapKey = "getMonthZhuanZhengUsers_Map"; // 查询生效日期当月转正的人数 getZhuanZhengPersonNum(ctx, tempMap, mainTableName, mainTableRowFilter, zhuanZhengMapKey); Map fixPayMap = (Map) tempMap.get(zhuanZhengMapKey); String key = personId + "_" + Effect; if (fixPayMap.containsKey(key)) { int num = fixPayMap.containsKey(key) ? fixPayMap.get(key) : 0; return (double) (num); } else { return (double) 0.0F; } } catch (Exception ex) { logger.error(ex.getMessage(), ex); //ex.printStackTrace(); } return (double) 0.0F; } /** * 当月离职人数(通过招聘渠道入职且在生效日期当月离职的人数)。 * @param ctx 上下文 * @param paramMap 参数(含 FPERSONID、FID) * @param tempMap 临时缓存 Map * @param mainTableName 计算表对象名 * @param mainTableRowFilter 计算表数据行过滤条件 * @return 当前人员在生效日期对应的当月离职人数 */ public double getMonthLiZhiUsers(Context ctx, Map paramMap, HashMap tempMap, String mainTableName, String mainTableRowFilter) { try { //计算的员工id String personId = (String) paramMap.get(mainTableName.toUpperCase() + "_FPERSONID"); //计算的数据行 String id = (String) paramMap.get(mainTableName.toUpperCase() + "_FID"); String Effect = getEffect(ctx, tempMap, mainTableName,mainTableRowFilter, id); // 离职人数缓存 key String liZhiMapKey = "getMonthLiZhiUsers_Map"; // 查询生效日期当月离职的人数 getLiZhiPersonNum(ctx, tempMap, mainTableName, mainTableRowFilter, liZhiMapKey); Map fixPayMap = (Map) tempMap.get(liZhiMapKey); String key = personId + "_" + Effect; if (fixPayMap.containsKey(key)) { int num = fixPayMap.containsKey(key) ? fixPayMap.get(key) : 0; return (double) (num); } else { return (double) 0.0F; } } catch (Exception ex) { logger.error(ex.getMessage(), ex); //ex.printStackTrace(); } return (double) 0.0F; } /** * 查询生效日期当月离职的人数,按"人员ID_生效年月"为 key 缓存到 tempMap。 *

* 通过 CT_REC_ApplicantBeisen(北森应聘表)关联 T_HR_RESIGNBIZBILL(离职单据), * 统计招聘渠道入职的员工在生效日期当月离职的人数。 * @param ctx 上下文 * @param tempMap 临时缓存 Map * @param mainTableName 计算表对象名 * @param mainTableRowFilter 计算表数据行过滤条件 * @param lzZhiMapKey 缓存 key * @throws BOSException 数据库异常 * @throws SQLException SQL异常 */ private static void getLiZhiPersonNum(Context ctx, HashMap tempMap, String mainTableName, String mainTableRowFilter, String lzZhiMapKey) throws BOSException, SQLException { Map lzFixPayMap = (Map) tempMap.get(lzZhiMapKey); if(lzFixPayMap==null){ StringBuilder sql = new StringBuilder(); sql.append(" /*dialect*/ "); // 主查询:按核算表和生效月份分组统计离职人数 sql.append(" SELECT mt.fpersonid,substring(convert(varchar,mt.FEffectDate,120),0,8) FEffectDate,count(abt.pid) pNum from ").append(mainTableName).append(" mt "); // 关联子查询:通过北森应聘表匹配到人员,再关联其最近一次离职记录 sql.append(" left join ( select ab.CFRecruitOwnerID,p.fid pid,t.fbizDate bizDate "); sql.append(" from CT_REC_ApplicantBeisen ab "); sql.append(" inner join T_REC_ResumeBaseRec rb on rb.CFCANDIDATEID = ab.CFCANDIDATEID "); sql.append(" inner join t_bd_person p on isnull(p.FIDCARDNO,p.FPASSPORTNO)=isnull(rb.FIdentityCardNo,rb.FPassportNo) "); // 取每个人员最近一次离职记录(ROW_NUMBER + rn=1) sql.append(" left join ( "); sql.append(" SELECT FPERSONID, FBIZDATE "); sql.append(" FROM ( "); sql.append(" SELECT "); sql.append(" e.FPERSONID, "); sql.append(" e.FBIZDATE, "); sql.append(" ROW_NUMBER() OVER (PARTITION BY e.FPERSONID ORDER BY e.FBIZDATE DESC) AS rn "); sql.append(" FROM T_HR_RESIGNBIZBILLENTRY e "); sql.append(" LEFT JOIN T_HR_RESIGNBIZBILL b ON b.fid = e.FBillID "); sql.append(" where b.FBillState=3 "); sql.append(" ) t "); sql.append(" WHERE rn = 1) t on t.fpersonid=p.fid ) abt on abt.CFRecruitOwnerID=mt.fpersonid "); // 离职日期在生效日期当月范围内:[当月第一天, 下月第一天) sql.append(" AND abt.bizDate >= DATEADD(MONTH, DATEDIFF(MONTH, 0, mt.FEffectDate), 0)"); // 当月第一天 00:00:00.000 sql.append(" AND abt.bizDate < DATEADD(MONTH, DATEDIFF(MONTH, 0, mt.FEffectDate) + 1, 0) "); // 下个月第一天 00:00:00.000 sql.append(" AND mt.fid in(").append(mainTableRowFilter).append(") group by mt.fpersonid,substring(convert(varchar,mt.FEffectDate,120),0,8) "); IRowSet rs = DbUtil.executeQuery(ctx,sql.toString()); lzFixPayMap = new HashMap<>(); while (rs.next()) { //获取人数 String fpersonid = rs.getString("fpersonid"); String FEffectDate = rs.getString("FEffectDate"); int pNum = rs.getInt("pNum"); lzFixPayMap.put(fpersonid+"_"+FEffectDate,pNum); } tempMap.put(lzZhiMapKey, lzFixPayMap); } } /** * 查询生效日期当月入职的人数,按"人员ID_生效年月"为 key 缓存到 tempMap。 *

* 通过 CT_REC_ApplicantBeisen(北森应聘表)关联 T_HR_EmpEnrollBizBill(入职单据), * 统计招聘渠道入职的员工在生效日期当月入职的人数。 * @param ctx 上下文 * @param tempMap 临时缓存 Map * @param mainTableName 计算表对象名 * @param mainTableRowFilter 计算表数据行过滤条件 * @param ruZhiMapKey 缓存 key * @throws BOSException 数据库异常 * @throws SQLException SQL异常 */ private static void getRuZhiPersonNum(Context ctx, HashMap tempMap, String mainTableName, String mainTableRowFilter, String ruZhiMapKey) throws BOSException, SQLException { Map fixPayMap = (Map) tempMap.get(ruZhiMapKey); if(fixPayMap==null){ StringBuilder sql = new StringBuilder(); sql.append(" /*dialect*/ "); // 主查询:按核算表和生效月份分组统计入职人数 sql.append(" SELECT mt.fpersonid,substring(convert(varchar,mt.FEffectDate,120),0,8) FEffectDate,count(abt.pid) pNum from ").append(mainTableName).append(" mt "); // 关联子查询:通过北森应聘表匹配到人员,再关联其最近一次入职记录 sql.append(" left join ( select ab.CFRecruitOwnerID,p.fid pid,t.fbizDate bizDate "); sql.append(" from CT_REC_ApplicantBeisen ab "); sql.append(" inner join T_REC_ResumeBaseRec rb on rb.CFCANDIDATEID = ab.CFCANDIDATEID "); sql.append(" inner join t_bd_person p on isnull(p.FIDCARDNO,p.FPASSPORTNO)=isnull(rb.FIdentityCardNo,rb.FPassportNo) "); // 取每个人员最近一次入职记录(ROW_NUMBER + rn=1) sql.append(" left join ( "); sql.append(" SELECT FPERSONID, FBIZDATE "); sql.append(" FROM ( "); sql.append(" SELECT "); sql.append(" e.FPERSONID, "); sql.append(" e.FBIZDATE, "); sql.append(" ROW_NUMBER() OVER (PARTITION BY e.FPERSONID ORDER BY e.FBIZDATE DESC) AS rn "); sql.append(" FROM T_HR_EmpEnrollBizBillEntry e "); sql.append(" LEFT JOIN T_HR_EmpEnrollBizBill b ON b.fid = e.FBillID "); sql.append(" where b.FBillState=3 "); sql.append(" ) t "); sql.append(" WHERE rn = 1) t on t.fpersonid=p.fid ) abt on abt.CFRecruitOwnerID=mt.fpersonid "); // 入职日期在生效日期当月范围内:[当月第一天, 下月第一天) sql.append(" AND abt.bizDate >= DATEADD(MONTH, DATEDIFF(MONTH, 0, mt.FEffectDate), 0)"); // 当月第一天 00:00:00.000 sql.append(" AND abt.bizDate < DATEADD(MONTH, DATEDIFF(MONTH, 0, mt.FEffectDate) + 1, 0) "); // 下个月第一天 00:00:00.000 sql.append(" AND mt.fid in(").append(mainTableRowFilter).append(") group by mt.fpersonid,substring(convert(varchar,mt.FEffectDate,120),0,8) "); IRowSet rs = DbUtil.executeQuery(ctx,sql.toString()); fixPayMap = new HashMap<>(); while (rs.next()) { //获取人数 String fpersonid = rs.getString("fpersonid"); String FEffectDate = rs.getString("FEffectDate"); int pNum = rs.getInt("pNum"); fixPayMap.put(fpersonid+"_"+FEffectDate,pNum); } tempMap.put(ruZhiMapKey, fixPayMap); } } /** * 查询生效日期当月转正的人数,按"人员ID_生效年月"为 key 缓存到 tempMap。 *

* 通过 CT_REC_ApplicantBeisen(北森应聘表)关联 T_HR_EMPHIREBIZBILL(转正单据), * 统计招聘渠道入职的员工在生效日期当月转正的人数。 * @param ctx 上下文 * @param tempMap 临时缓存 Map * @param mainTableName 计算表对象名 * @param mainTableRowFilter 计算表数据行过滤条件 * @param ruZhiMapKey 缓存 key * @throws BOSException 数据库异常 * @throws SQLException SQL异常 */ private static void getZhuanZhengPersonNum(Context ctx, HashMap tempMap, String mainTableName, String mainTableRowFilter, String ruZhiMapKey) throws BOSException, SQLException { Map fixPayMap = (Map) tempMap.get(ruZhiMapKey); if(fixPayMap==null){ StringBuilder sql = new StringBuilder(); sql.append(" /*dialect*/ "); // 主查询:按核算表和生效月份分组统计转正人数 sql.append(" SELECT mt.fpersonid,substring(convert(varchar,mt.FEffectDate,120),0,8) FEffectDate,count(abt.pid) pNum from ").append(mainTableName).append(" mt "); // 关联子查询:通过北森应聘表匹配到人员,再关联其最近一次转正记录 sql.append(" left join ( select ab.CFRecruitOwnerID,p.fid pid,t.fbizDate bizDate "); sql.append(" from CT_REC_ApplicantBeisen ab "); sql.append(" inner join T_REC_ResumeBaseRec rb on rb.CFCANDIDATEID = ab.CFCANDIDATEID "); sql.append(" inner join t_bd_person p on isnull(p.FIDCARDNO,p.FPASSPORTNO)=isnull(rb.FIdentityCardNo,rb.FPassportNo) "); // 取每个人员最近一次转正记录(ROW_NUMBER + rn=1) sql.append(" left join ( "); sql.append(" SELECT FPERSONID, FBIZDATE "); sql.append(" FROM ( "); sql.append(" SELECT "); sql.append(" e.FPERSONID, "); sql.append(" e.FBIZDATE,e.FEnrollDate, "); sql.append(" ROW_NUMBER() OVER (PARTITION BY e.FPERSONID ORDER BY e.FBIZDATE DESC) AS rn "); sql.append(" FROM T_HR_EMPHIREBIZBILLENTRY e "); sql.append(" LEFT JOIN T_HR_EMPHIREBIZBILL b ON b.fid = e.FBillID "); sql.append(" where b.FBillState=3 "); sql.append(" ) t "); sql.append(" WHERE rn = 1) t on t.fpersonid=p.fid ) abt on abt.CFRecruitOwnerID=mt.fpersonid "); // 转正日期在生效日期当月范围内:[当月第一天, 下月第一天) sql.append(" AND abt.bizDate >= DATEADD(MONTH, DATEDIFF(MONTH, 0, mt.FEffectDate), 0)"); // 当月第一天 00:00:00.000 sql.append(" AND abt.bizDate < DATEADD(MONTH, DATEDIFF(MONTH, 0, mt.FEffectDate) + 1, 0) "); // 下个月第一天 00:00:00.000 sql.append(" AND mt.fid in(").append(mainTableRowFilter).append(") group by mt.fpersonid,substring(convert(varchar,mt.FEffectDate,120),0,8) "); IRowSet rs = DbUtil.executeQuery(ctx,sql.toString()); fixPayMap = new HashMap<>(); while (rs.next()) { //获取人数 String fpersonid = rs.getString("fpersonid"); String FEffectDate = rs.getString("FEffectDate"); int pNum = rs.getInt("pNum"); fixPayMap.put(fpersonid+"_"+FEffectDate,pNum); } tempMap.put(ruZhiMapKey, fixPayMap); } } /** * 获取生效日期的月份(yyyy-MM 格式)。 *

* 优先从 tempMap 中以 "getEffect_" + id 为 key 查找缓存; * 缓存未命中时,一次性批量查询 mainTableRowFilter 范围内所有行的 FEffectDate, * 逐行以 "getEffect_" + fid 为 key 写入 tempMap,后续同一批次其他行直接命中缓存。 * @param ctx 上下文 * @param tempMap 临时缓存 Map * @param mainTableName 计算表对象名 * @param mainTableRowFilter 计算表数据行过滤条件(用于批量加载) * @param id 当前数据行 FID * @return 生效日期对应的 yyyy-MM 格式月份字符串,若未查到则为空字符串 * @throws BOSException 数据库异常 * @throws SQLException SQL异常 */ private static String getEffect(Context ctx, HashMap tempMap, String mainTableName, String mainTableRowFilter, String id) throws BOSException, SQLException { String cacheKey = "getEffect_" + id; if (tempMap.containsKey(cacheKey)) { return (String) tempMap.get(cacheKey); } IRowSet rowSet = DbUtil.executeQuery(ctx, " SELECT mt.fid,mt.fpersonid,mt.FEffectDate from " + mainTableName + " mt where mt.fid in("+mainTableRowFilter+")"); String Effect = ""; while (rowSet.next()) { String fid = rowSet.getString("fid"); LocalDate effectDate = rowSet.getDate("FEffectDate").toLocalDate(); Effect = effectDate.format(DateTimeFormatter.ofPattern("yyyy-MM")); String Key = "getEffect_" + fid; tempMap.put(Key, Effect); } return (String) tempMap.getOrDefault(cacheKey, ""); } /** * 获取适用薪酬方案名称(fname_l2)。 *

* 通过计算表关联 T_HR_SBatchSubmitShemeBill 和 T_HR_SCalSubmitScheme, * 查询当前计算范围对应的薪酬方案名称,结果以"name"为 key 缓存。 * @param ctx 上下文 * @param paramMap 参数(含 FPERSONID、FID) * @param tempMap 临时缓存 Map * @param mainTableName 计算表对象名 * @param mainTableRowFilter 计算表数据行过滤条件 * @return 方案名称,未找到则返回空字符串 */ public String getApplicablePlan(Context ctx, Map paramMap, HashMap tempMap, String mainTableName, String mainTableRowFilter) { try { //计算的员工id String personId = (String) paramMap.get(mainTableName.toUpperCase() + "_FPERSONID"); //计算的数据行 String id = (String) paramMap.get(mainTableName.toUpperCase() + "_FID"); //根据计算范围初始化薪酬项目信息 String fixPayMapKey = "getApplicablePlan_SchemeName"; if (tempMap.get(fixPayMapKey) == null) { StringBuilder sql = new StringBuilder(); sql.append(" select sss.fname_l2 from "+mainTableName+" sbe "); sql.append(" left join T_HR_SBatchSubmitShemeBill ssb on ssb.fid=sbe.FBillID "); sql.append(" left join T_HR_SCalSubmitScheme sss on sss.fid=ssb.FSubmitSchemeID "); sql.append(" where sbe.fid in(" + mainTableRowFilter + ")"); IRowSet rs = DbUtil.executeQuery(ctx, sql.toString()); if (rs.next()) { Map objectMap = new HashMap<>(); objectMap.put("name", rs.getString("fname_l2")); tempMap.put(fixPayMapKey, objectMap); } } //获取薪酬项目值 Map fixPayMap = (Map) tempMap.get(fixPayMapKey); String key = "name"; if (fixPayMap.containsKey(key)) { String schemeName = fixPayMap.get(key); return schemeName; } else { return ""; } } catch (Exception e) { logger.error(e.getMessage(), e); //e.printStackTrace(); return ""; } } /** * 获取薪酬档案中指定薪资项目的金额。 *

* 根据人员 ID 和薪酬项目名称,从 T_HR_SFIXADJUSTSALARY 表中查询固定薪酬数据。 * 结果以 "personId_cmpItem" 为 key 缓存到 tempMap,后续同一计算范围直接复用。 * @param ctx 上下文 * @param paramMap 参数(含 FPERSONID、FID) * @param tempMap 临时缓存 Map * @param mainTableName 计算表对象名 * @param mainTableRowFilter 计算表数据行过滤条件 * @param cmpItem 薪酬项目名称(对应 T_HR_SCMPITEM.FNAME_L2) * @param isFixed 是否固定薪酬(0=按FEffectDate匹配, 非0=按FEffectDate匹配;预留扩展) * @return 薪资项目金额,若人员或项目不存在则返回 0.0 */ public double getItemSalary(Context ctx, Map paramMap, HashMap tempMap, String mainTableName, String mainTableRowFilter, String cmpItem, double isFixed) { try { //计算的员工id String personId = (String) paramMap.get(mainTableName.toUpperCase() + "_FPERSONID"); //计算的数据行 String id = (String) paramMap.get(mainTableName.toUpperCase() + "_FID"); //根据计算范围初始化薪酬项目信息 String fixPayMapKey = "getItemSalary_fixPayMap_" + isFixed; if (!StringUtils.isEmpty(cmpItem) && personId != null) { if (tempMap.get(fixPayMapKey) == null) { tempMap.put(fixPayMapKey, this.initFixPayForMoneyMap(ctx, mainTableName, isFixed, mainTableRowFilter)); } //获取薪酬项目值 Map fixPayMap = (Map) tempMap.get(fixPayMapKey); String key = personId + "_" + cmpItem; if (fixPayMap.containsKey(key)) { BigDecimal money = fixPayMap.containsKey(key) ? (BigDecimal) fixPayMap.get(key) : new BigDecimal(0); double pay = money.doubleValue(); return pay; } else { return (double) 0.0F; } } else { return (double) 0.0F; } } catch (Exception e) { logger.error(e.getMessage(), e); //e.printStackTrace(); return (double) 0.0F; } } /** * 初始化固定薪酬数据 Map,以 "personId_cmpItem" 为 key,金额为 value。 *

* 查询 T_HR_SFIXADJUSTSALARY(固定调整薪酬表),按生效日期匹配核算表中的薪酬项目。 * 查询结果按 type 优先级排序:type=1(相同组织)优先于 type=0(无组织限制), * 同一 key 仅保留首次出现的记录(优先级最高的)。 * @param ctx 上下文 * @param mainTableName 计算表对象名 * @param isFixed 是否固定薪酬(0=按FEffectDate匹配, 非0=按FEffectDate匹配;预留扩展) * @param mainTableRowFilter 计算表数据行过滤条件 * @return key 为 "personId_cmpItem",value 为对应金额的 Map * @throws Exception 数据库异常 */ public Map initFixPayForMoneyMap(Context ctx, String mainTableName, double isFixed, String mainTableRowFilter) throws Exception { StringBuilder sb = new StringBuilder(); String effectDayField = ""; String key = null; String personId = ""; String cmpItem = ""; Map fixPayMap = new HashMap(); Set set = new HashSet(); if (isFixed == (double) 0.0F) { effectDayField = "calTable.FEffectDate"; } else { effectDayField = "calTable.FEffectDate"; } sb.append(" SELECT DISTINCT CALTABLE.FPERSONID as personId, FIX.FMONEY MONEY, FIX.FCURRENCYID, "); sb.append(" CMPITEM.FNAME_L2 CMPITEM,FIX.FEFFECTDAY, "); // type: 0=组织为空(通用), 1=组织匹配(优先), 2=组织不匹配(排除) sb.append(" ( case when (fix.fpayhrorgunitid is null or fix.fpayhrorgunitid in ('')) then 0 when ( calTable.FHrOrgUnitID= fix.fpayhrorgunitid) then 1 else 2 end ) as type").append("\r\n"); sb.append(" FROM " + mainTableName + " CALTABLE "); sb.append(" INNER JOIN T_HR_SFIXADJUSTSALARY FIX ON CALTABLE.FPERSONID=FIX.FPERSONID AND (FIX.FCurrencyID = CALTABLE.FCurrencyID OR FIX.FCurrencyID IS NULL)"); sb.append(" LEFT JOIN T_HR_SCMPITEM CMPITEM ON CMPITEM.FID=FIX.FCMPITEMID "); sb.append(" WHERE FIX.feffectday <= ").append(effectDayField).append(" AND FIX.fleffectday >= ").append(effectDayField); sb.append(" AND CALTABLE.fid in(").append(mainTableRowFilter).append(")"); IRowSet rs = DbUtil.executeQuery(ctx, sb.toString()); List> dataList = this.getDataFromExecuteQuery(rs); Iterator> it = dataList.iterator(); while (it.hasNext()) { Map data = (Map) it.next(); personId = (String) data.get("personId"); cmpItem = (String) data.get("CMPITEM"); key = personId + "_" + cmpItem; if (!set.contains(key)) { set.add(key); BigDecimal money = (BigDecimal) data.get("MONEY"); fixPayMap.put(key, money); } } return fixPayMap; } /** * 将 IRowSet 查询结果按优先级排序后转换为 List<Map>。 *

* 排序规则:type=1(相同组织)的记录优先,type=0(无组织限制)的次之,type=2(组织不匹配)的排除。 * 同一人员同一薪酬项目的 key 只保留首次出现(即优先级最高)的记录。 * @param executeQuery 查询结果集 * @return 按优先级排序后的数据列表 * @throws SQLException SQL异常 */ public List> getDataFromExecuteQuery(IRowSet executeQuery) throws SQLException { Map map = null; List> dataList = null; Map>> mapList = null; Map>> mapListOne = null; Map>> mapListZero = null; List> list = null; List> oneList = null; List> zeroList = null; if (null != executeQuery) { String personId = null; dataList = new ArrayList(); mapList = new HashMap(); mapListOne = new HashMap(); mapListZero = new HashMap(); while (executeQuery.next()) { map = this.executeQueryToMap(executeQuery); personId = executeQuery.getString("personId"); int type = executeQuery.getInt("type"); if (mapList.containsKey(personId)) { list = (List) mapList.get(personId); list.add(map); } else { list = new ArrayList(); list.add(map); mapList.put(personId, list); } // type=1: 组织匹配,优先使用 if (type == 1) { if (mapListOne.containsKey(personId)) { oneList = (List) mapListOne.get(personId); oneList.add(map); } else { oneList = new ArrayList(); oneList.add(map); mapListOne.put(personId, oneList); } // type=0: 无组织限制,次优 } else if (type == 0) { if (mapListZero.containsKey(personId)) { zeroList = (List) mapListZero.get(personId); zeroList.add(map); } else { zeroList = new ArrayList(); zeroList.add(map); mapListZero.put(personId, zeroList); } } // type=2(组织不匹配)排除,不加入结果 } List> var21 = null; // 合并结果:先加入 type=1(组织匹配),再加入 type=0(无组织限制) // 后续去重逻辑会保留首次出现的记录,从而实现优先级 for (String str : mapList.keySet()) { List> var22 = (List) mapList.get(str); if (mapListOne.containsKey(str)) { dataList.addAll((Collection) mapListOne.get(str)); } if (mapListZero.containsKey(str)) { dataList.addAll((Collection) mapListZero.get(str)); } } } return (List>) (null != dataList && !dataList.isEmpty() ? dataList : new ArrayList(0)); } /** * 将 IRowSet 当前行转换为 Map,提取固定薪酬相关字段。 * @param executeQuery 查询结果集(已定位到某一行) * @return 包含 personId、MONEY、FCURRENCYID、CMPITEM、FEFFECTDAY 的 Map * @throws SQLException SQL异常 */ public Map executeQueryToMap(IRowSet executeQuery) throws SQLException { Map map = new HashMap(); map.put("personId", executeQuery.getString("personId")); map.put("MONEY", executeQuery.getBigDecimal("MONEY") == null ? new BigDecimal(0) : executeQuery.getBigDecimal("MONEY")); map.put("FCURRENCYID", executeQuery.getString("FCURRENCYID")); map.put("CMPITEM", executeQuery.getString("CMPITEM")); map.put("FEFFECTDAY", executeQuery.getDate("FEFFECTDAY")); return map; } }