| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- package com.kingdee.eas.custom.perfweb.handler;
- import com.alibaba.fastjson.JSONObject;
- import com.kingdee.bos.BOSException;
- import com.kingdee.bos.Context;
- import com.kingdee.eas.custom.perfweb.util.ReportDateUtil;
- import com.kingdee.eas.custom.perfweb.util.ReportFilterUtil;
- import com.kingdee.eas.custom.perfweb.util.ReportOrgUtil;
- import com.kingdee.eas.custom.perfweb.util.ReportTurnoverUtil;
- import com.kingdee.shr.base.syssetting.context.SHRContext;
- import com.kingdee.shr.base.syssetting.exception.ShrWebBizException;
- import com.kingdee.shr.base.syssetting.json.GridDataEntity;
- import com.kingdee.shr.base.syssetting.web.handler.ListHandler;
- import org.apache.log4j.Logger;
- import org.springframework.ui.ModelMap;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- import java.sql.SQLException;
- import java.util.*;
- /**
- * 类名称: ProbationTurnoverReportHandler
- * 功能描述: 试用期流失率报表(期间试用期人员主动/被动离职及累计离职、累计入职、累计流失率)
- * 创建日期: 2026-06-23
- * 作 者: 青梧
- * 版 本: 1.1
- *
- * 返回字段说明:
- * month - 月份(合计行显示合计)
- * activeResign - 期间试用期人员主动离职(员工类型002)
- * passiveResign - 期间试用期人员被动离职
- * totalResign - 期间试用期人员离职合计
- * newEntry - 期间试用期人员入职人数
- * ytdActiveResign - 截止目前累计主动离职
- * ytdPassiveResign - 截止目前累计被动离职
- * ytdTotalResign - 截止目前累计离职合计
- * ytdEntry - 截止目前累计试用期入职
- * ytdActiveRate - 截止目前累计主动流失率(两位小数%)
- * ytdPassiveRate - 截止目前累计被动流失率(两位小数%)
- * ytdTotalRate - 截止目前累计总流失率(两位小数%)
- */
- public class ProbationTurnoverReportHandler extends ListHandler {
- private static Logger logger = Logger.getLogger(ProbationTurnoverReportHandler.class);
- Context ctx = SHRContext.getInstance().getContext();
- /** 试用员工类型编码 */
- private static final String TRIAL_EMPLOYEE_TYPE = "002";
- /**
- * 列表查询入口:按年度逐月统计试用期人员流失,末尾追加合计行。
- */
- @Override
- protected GridDataEntity getGridRequestData(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws ShrWebBizException {
- logger.error("ProbationTurnoverReportHandler getGridRequestData------------");
- GridDataEntity gridDataEntity = new GridDataEntity();
- try {
- // 快筛(company字段可能为中心F7) + 列表筛选
- String filterItem = ReportFilterUtil.getFilterItems(request);
- JSONObject fastFilterItemsJson = ReportFilterUtil.parseFastFilterJson(request);
- logger.error("filterItem: " + filterItem);
- logger.error("fastFilterItemsJson: " + fastFilterItemsJson);
- ReportOrgUtil.OrgScope scope = ReportFilterUtil.buildCenterOrgScope(ctx, fastFilterItemsJson, logger);
- String year = ReportFilterUtil.resolveYear(filterItem, fastFilterItemsJson, logger);
- logger.error("查询年度: " + year);
- List<Map<String, Object>> monthDataList = getMonthTurnoverData(year, scope);
- monthDataList.add(calculateSummary(monthDataList));
- gridDataEntity.setRows(monthDataList);
- gridDataEntity.setTotal(monthDataList.size());
- gridDataEntity.setPage(1);
- gridDataEntity.setRecords(monthDataList.size());
- logger.error("试用期流失率报表数据查询成功,总记录数: " + monthDataList.size());
- } catch (Exception e) {
- e.fillInStackTrace();
- throw new ShrWebBizException(e.getMessage());
- }
- ReportFilterUtil.applyGridUserData(request, gridDataEntity);
- return gridDataEntity;
- }
- /**
- * 循环1~12月,逐月统计试用期离职/入职及累计指标。
- */
- private List<Map<String, Object>> getMonthTurnoverData(String year, ReportOrgUtil.OrgScope scope) throws BOSException, SQLException {
- List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
- int ytdActiveResign = 0;
- int ytdPassiveResign = 0;
- int ytdTotalResign = 0;
- int ytdEntry = 0;
- for (int month = 1; month <= 12; month++) {
- Map<String, Object> monthData = new LinkedHashMap<String, Object>();
- monthData.put("month", ReportDateUtil.formatMonthLabel(year, month)); // month: 月份
- String monthStart = ReportDateUtil.getMonthStart(year, month);
- String monthEnd = ReportDateUtil.getMonthEnd(year, month);
- int activeResignCount = getResignCount(monthStart, monthEnd, false, scope);
- monthData.put("activeResign", activeResignCount); // activeResign: 期间主动离职
- int passiveResignCount = getResignCount(monthStart, monthEnd, true, scope);
- monthData.put("passiveResign", passiveResignCount); // passiveResign: 期间被动离职
- int totalResignCount = activeResignCount + passiveResignCount;
- monthData.put("totalResign", totalResignCount); // totalResign: 期间离职合计
- int newEntryCount = getEntryCount(monthStart, monthEnd, scope);
- monthData.put("newEntry", newEntryCount); // newEntry: 期间试用期入职
- ytdActiveResign += activeResignCount;
- monthData.put("ytdActiveResign", ytdActiveResign); // ytdActiveResign: 累计主动离职
- ytdPassiveResign += passiveResignCount;
- monthData.put("ytdPassiveResign", ytdPassiveResign); // ytdPassiveResign: 累计被动离职
- ytdTotalResign += totalResignCount;
- monthData.put("ytdTotalResign", ytdTotalResign); // ytdTotalResign: 累计离职合计
- ytdEntry += newEntryCount;
- monthData.put("ytdEntry", ytdEntry); // ytdEntry: 累计试用期入职
- monthData.put("ytdActiveRate", ReportTurnoverUtil.formatRatioPercent(
- ReportTurnoverUtil.calculateRatio(ytdActiveResign, ytdEntry))); // ytdActiveRate: 累计主动流失率
- monthData.put("ytdPassiveRate", ReportTurnoverUtil.formatRatioPercent(
- ReportTurnoverUtil.calculateRatio(ytdPassiveResign, ytdEntry))); // ytdPassiveRate: 累计被动流失率
- monthData.put("ytdTotalRate", ReportTurnoverUtil.formatRatioPercent(
- ReportTurnoverUtil.calculateRatio(ytdTotalResign, ytdEntry))); // ytdTotalRate: 累计总流失率
- dataList.add(monthData);
- }
- return dataList;
- }
- /**
- * 统计试用期人员离职人数。
- * 口径:取离职单分录离职前员工类型 FOldEmpTypeID=002,不能用人员档案当前类型(离职后可能已变更)。
- *
- * @param isPassive true=被动离职,false=主动离职
- */
- private int getResignCount(String monthStart, String monthEnd, boolean isPassive, ReportOrgUtil.OrgScope scope) throws BOSException, SQLException {
- StringBuilder sql = new StringBuilder();
- sql.append("SELECT COUNT(*) as count ");
- sql.append("FROM T_HR_ResignBizBillEntry entry ");
- sql.append("INNER JOIN T_HR_ResignBizBill bill ON entry.FBillID = bill.FID ");
- sql.append("INNER JOIN T_HR_BDEmployeeType empType ON empType.FID = entry.FOLDEMPTYPEID ");
- sql.append("WHERE bill.FBillState = 3 ");
- sql.append("AND empType.FNumber = '").append(TRIAL_EMPLOYEE_TYPE).append("' ");
- sql.append("AND entry.FBizDate >= '").append(monthStart).append("' ");
- sql.append("AND entry.FBizDate <= '").append(monthEnd).append("' ");
- ReportTurnoverUtil.appendPassiveResignFilter(sql, isPassive);
- ReportOrgUtil.appendAdminOrgScopeFilter(sql, ctx, scope, "entry.FAdminOrgID");
- return ReportOrgUtil.executeCountQuery(ctx, sql,
- "试用期人员" + (isPassive ? "被动" : "主动") + "离职人数", logger);
- }
- /**
- * 统计试用期人员新入职人数。
- */
- private int getEntryCount(String monthStart, String monthEnd, ReportOrgUtil.OrgScope scope) throws BOSException, SQLException {
- StringBuilder sql = new StringBuilder();
- sql.append("SELECT COUNT(*) as count ");
- sql.append("FROM T_HR_EmpEnrollBizBillEntry entry ");
- sql.append("INNER JOIN T_BD_PERSON person ON entry.FPersonID = person.FID ");
- sql.append("INNER JOIN T_HR_BDEmployeeType empType ON empType.FID = person.FEMPLOYEETYPEID ");
- sql.append("WHERE empType.FNumber = '").append(TRIAL_EMPLOYEE_TYPE).append("' ");
- sql.append("AND entry.FBizDate >= '").append(monthStart).append("' ");
- sql.append("AND entry.FBizDate <= '").append(monthEnd).append("' ");
- ReportOrgUtil.appendAdminOrgScopeFilter(sql, ctx, scope, "entry.FAdminOrgID");
- return ReportOrgUtil.executeCountQuery(ctx, sql, "试用期人员新入职人数", logger);
- }
- /**
- * 合计行:期间字段全年累加,累计字段取12月值并重算流失率。
- */
- private Map<String, Object> calculateSummary(List<Map<String, Object>> monthDataList) {
- Map<String, Object> summary = new LinkedHashMap<String, Object>();
- summary.put("month", "合计"); // month: 合计行
- int totalActiveResign = 0;
- int totalPassiveResign = 0;
- int totalResign = 0;
- int totalNewEntry = 0;
- int totalYtdActiveResign = 0;
- int totalYtdPassiveResign = 0;
- int totalYtdTotalResign = 0;
- int totalYtdEntry = 0;
- for (Map<String, Object> monthData : monthDataList) {
- totalActiveResign += (Integer) monthData.get("activeResign");
- totalPassiveResign += (Integer) monthData.get("passiveResign");
- totalResign += (Integer) monthData.get("totalResign");
- totalNewEntry += (Integer) monthData.get("newEntry");
- }
- if (!monthDataList.isEmpty()) {
- Map<String, Object> lastMonth = monthDataList.get(monthDataList.size() - 1);
- totalYtdActiveResign = (Integer) lastMonth.get("ytdActiveResign");
- totalYtdPassiveResign = (Integer) lastMonth.get("ytdPassiveResign");
- totalYtdTotalResign = (Integer) lastMonth.get("ytdTotalResign");
- totalYtdEntry = (Integer) lastMonth.get("ytdEntry");
- }
- summary.put("activeResign", totalActiveResign);
- summary.put("passiveResign", totalPassiveResign);
- summary.put("totalResign", totalResign);
- summary.put("newEntry", totalNewEntry);
- summary.put("ytdActiveResign", totalYtdActiveResign);
- summary.put("ytdPassiveResign", totalYtdPassiveResign);
- summary.put("ytdTotalResign", totalYtdTotalResign);
- summary.put("ytdEntry", totalYtdEntry);
- summary.put("ytdActiveRate", ReportTurnoverUtil.formatRatioPercent(
- ReportTurnoverUtil.calculateRatio(totalYtdActiveResign, totalYtdEntry)));
- summary.put("ytdPassiveRate", ReportTurnoverUtil.formatRatioPercent(
- ReportTurnoverUtil.calculateRatio(totalYtdPassiveResign, totalYtdEntry)));
- summary.put("ytdTotalRate", ReportTurnoverUtil.formatRatioPercent(
- ReportTurnoverUtil.calculateRatio(totalYtdTotalResign, totalYtdEntry)));
- return summary;
- }
- }
|