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