| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- 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.bos.ctrl.swing.StringUtils;
- import com.kingdee.eas.custom.perfweb.util.PersonnelStatUtil;
- import com.kingdee.eas.custom.perfweb.util.ReportFilterUtil;
- import com.kingdee.eas.custom.perfweb.util.ReportOrgUtil;
- import com.kingdee.shr.base.syssetting.context.SHRContext;
- import com.kingdee.shr.base.syssetting.exception.SHRWebException;
- 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.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- /**
- * 类名称: CenterPersonnelStatHandler
- * 功能描述: 按中心统计人员结构报表数据处理
- * 创建日期: 2026-06-05
- * 作 者: 青梧
- * 版 本: 1.1
- *
- * 返回字段说明:
- * centerCode - 中心/部门编码(FNUMBER,同名取第一个)
- * centerName - 中心/部门名称(合计/劳务工等特殊行;品质部为单独汇总行)
- * personCount - 在职总人数(含下级组织)
- * personPercentage - 人数占全部中心在职合计的百分比
- * formalCount - 正式员工人数(员工类型001)
- * formalPercentage - 正式员工占本中心总人数的百分比
- * trialCount - 试用员工人数(员工类型002)
- * trialPercentage - 试用员工占本中心总人数的百分比
- * keyTalentCount - 关键人才人数(CFGjrc=1)
- *
- * 品质部行说明:
- * 全集团同名「品质部」跨公司合并单独一行,与中心行无互斥关系,不计入合计行累加。
- */
- public class CenterPersonnelStatHandler extends ListHandler {
- private static Logger logger = Logger.getLogger(CenterPersonnelStatHandler.class);
- Context ctx = SHRContext.getInstance().getContext();
- /** 单独汇总的品质部名称(跨公司合并) */
- private static final String QUALITY_DEPT_NAME = "品质部";
- /**
- * 列表查询入口:按中心汇总在职人数、正式/试用/关键人才人数及占比,末尾追加品质部、劳务工与合计行。
- */
- @Override
- protected GridDataEntity getGridRequestData(HttpServletRequest request, HttpServletResponse response, ModelMap modelMap) throws SHRWebException {
- logger.error("CenterPersonnelStatHandler getGridRequestData------------");
- GridDataEntity gridDataEntity = new GridDataEntity();
- try {
- // 快筛(company字段可能为中心F7) + 列表筛选 filterItems
- String filterItem = ReportFilterUtil.getFilterItems(request);
- JSONObject fastFilterItemsJson = ReportFilterUtil.parseFastFilterJson(request);
- logger.error("filterItem: " + filterItem);
- logger.error("fastFilterItemsJson: " + fastFilterItemsJson);
- Map<String, String> paramMap = ReportFilterUtil.parseCompanyParams(fastFilterItemsJson, logger, false);
- ReportOrgUtil.OrgScope centerScope = ReportFilterUtil.buildCenterOrgScope(ctx, fastFilterItemsJson, logger);
- logger.error("查询参数: " + paramMap);
- // 公司F7筛选,用于限定中心所属公司
- String companyId = paramMap.get("companyId");
- // 劳务工人数来自基础资料手工维护,不参与中心明细循环
- int laborCount = PersonnelStatUtil.getLaborCount(ctx, logger);
- // 按中心名称去重合并(排除130)
- List<ReportOrgUtil.OrgNameCode> centers = getCenterList(companyId, filterItem, centerScope);
- int totalCount = 0;
- int totalFormalCount = 0;
- int totalTrialCount = 0;
- int totalKeyTalentCount = 0;
- List<Map<String, Object>> dataList = new ArrayList<Map<String, Object>>();
- for (ReportOrgUtil.OrgNameCode center : centers) {
- String centerName = center.orgName;
- PersonnelStatUtil.PersonnelStat stat = PersonnelStatUtil.countStructure(ctx, buildCenterStatScope(centerName, companyId), logger);
- Map<String, Object> row = new HashMap<String, Object>();
- row.put("centerCode", center.orgCode); // centerCode: 中心编码
- row.put("centerName", centerName); // centerName: 中心名称
- row.put("personCount", stat.totalCount); // personCount: 在职总人数
- row.put("personPercentage", 0.0); // personPercentage: 占比(第二遍回填)
- row.put("formalCount", stat.formalCount); // formalCount: 正式员工数
- row.put("formalPercentage", 0.0); // formalPercentage: 正式占比(第二遍回填)
- row.put("trialCount", stat.trialCount); // trialCount: 试用员工数
- row.put("trialPercentage", 0.0); // trialPercentage: 试用占比(第二遍回填)
- row.put("keyTalentCount", stat.keyTalentCount); // keyTalentCount: 关键人才数
- dataList.add(row);
- totalCount += stat.totalCount;
- totalFormalCount += stat.formalCount;
- totalTrialCount += stat.trialCount;
- totalKeyTalentCount += stat.keyTalentCount;
- }
- // 品质部单独一行(跨公司合并,与中心行无互斥关系,不计入合计累加)
- PersonnelStatUtil.PersonnelStat qualityStat = PersonnelStatUtil.countStructure(ctx,
- PersonnelStatUtil.StatScope.dept(QUALITY_DEPT_NAME, companyId), logger);
- Map<String, Object> qualityRow = new HashMap<String, Object>();
- qualityRow.put("centerCode", resolveQualityDeptCode(companyId)); // centerCode: 部门编码
- qualityRow.put("centerName", QUALITY_DEPT_NAME); // centerName: 品质部
- qualityRow.put("personCount", qualityStat.totalCount);
- qualityRow.put("personPercentage", 0.0);
- qualityRow.put("formalCount", qualityStat.formalCount);
- qualityRow.put("formalPercentage", 0.0);
- qualityRow.put("trialCount", qualityStat.trialCount);
- qualityRow.put("trialPercentage", 0.0);
- qualityRow.put("keyTalentCount", qualityStat.keyTalentCount);
- dataList.add(qualityRow);
- // 第二遍循环:基于各中心合计数回填各行占比(含品质部行)
- for (Map<String, Object> row : dataList) {
- int personCount = (Integer) row.get("personCount");
- int formalCount = (Integer) row.get("formalCount");
- int trialCount = (Integer) row.get("trialCount");
- // 人数占比 = 本行人数 / 全部中心在职合计
- double personPercentage = totalCount > 0 ? (personCount * 100.0 / totalCount) : 0.0;
- row.put("personPercentage", String.format("%.2f", personPercentage) + "%");
- // 正式员工占比 = 本行正式人数 / 本行总人数
- double formalPercentage = personCount > 0 ? (formalCount * 100.0 / personCount) : 0.0;
- row.put("formalPercentage", String.format("%.2f", formalPercentage) + "%");
- // 试用员工占比 = 本行试用人数 / 本行总人数
- double trialPercentage = personCount > 0 ? (trialCount * 100.0 / personCount) : 0.0;
- row.put("trialPercentage", String.format("%.2f", trialPercentage) + "%");
- }
- // 正式工合计行(仅统计各中心在编人员,不含品质部重复行与劳务工)
- Map<String, Object> totalRow = new HashMap<String, Object>();
- totalRow.put("centerCode", ""); // centerCode: 合计行留空
- totalRow.put("centerName", "合计"); // centerName: 正式工合计
- totalRow.put("personCount", totalCount); // personCount: 各中心在职合计
- totalRow.put("personPercentage", totalCount > 0 ? "100.00%" : "0.00%");
- totalRow.put("formalCount", totalFormalCount); // formalCount: 正式员工合计
- totalRow.put("formalPercentage", totalCount > 0 ? String.format("%.2f", totalFormalCount * 100.0 / totalCount) + "%" : "0.00%");
- totalRow.put("trialCount", totalTrialCount); // trialCount: 试用员工合计
- totalRow.put("trialPercentage", totalCount > 0 ? String.format("%.2f", totalTrialCount * 100.0 / totalCount) + "%" : "0.00%");
- totalRow.put("keyTalentCount", totalKeyTalentCount); // keyTalentCount: 关键人才合计
- dataList.add(totalRow);
- // 劳务工行:人数取自基础资料,无正式/试用等细分字段
- Map<String, Object> laborRow = new HashMap<String, Object>();
- laborRow.put("centerCode", ""); // centerCode: 劳务工行留空
- laborRow.put("centerName", "劳务工"); // centerName: 劳务工标识
- laborRow.put("personCount", laborCount); // personCount: 劳务工人数
- dataList.add(laborRow);
- // 含劳务工的总计行
- int totalWithLabor = totalCount + laborCount;
- Map<String, Object> totalWithLaborRow = new HashMap<String, Object>();
- totalWithLaborRow.put("centerCode", ""); // centerCode: 含劳务工合计行留空
- totalWithLaborRow.put("centerName", "合计(含劳务工)"); // centerName: 含劳务工合计
- totalWithLaborRow.put("personCount", totalWithLabor); // personCount: 正式+劳务工合计
- dataList.add(totalWithLaborRow);
- gridDataEntity.setRows(dataList);
- gridDataEntity.setTotal(dataList.size());
- gridDataEntity.setPage(1);
- gridDataEntity.setRecords(dataList.size());
- logger.error("按中心统计报表数据查询成功,总记录数: " + dataList.size());
- } catch (SQLException e) {
- logger.error("数据库查询失败", e);
- throw new SHRWebException("数据查询失败: " + e.getMessage());
- } catch (BOSException e) {
- logger.error("业务异常", e);
- throw new SHRWebException("业务处理失败: " + e.getMessage());
- } catch (Exception e) {
- logger.error("未知异常", e);
- throw new SHRWebException("系统异常: " + e.getMessage());
- }
- ReportFilterUtil.applyGridUserData(request, gridDataEntity);
- return gridDataEntity;
- }
- /**
- * 查询品质部编码(跨公司同名取第一个)。
- */
- private String resolveQualityDeptCode(String companyId) throws BOSException, SQLException {
- List<ReportOrgUtil.OrgNameCode> depts = ReportOrgUtil.getDistinctOrgNameCodes(ctx, ReportOrgUtil.LAYER_DEPT, companyId);
- for (ReportOrgUtil.OrgNameCode dept : depts) {
- if (QUALITY_DEPT_NAME.equals(dept.orgName)) {
- return dept.orgCode;
- }
- }
- return "";
- }
- /**
- * 查询去重后的中心名称编码列表(跨公司合并,排除130)。
- */
- private List<ReportOrgUtil.OrgNameCode> getCenterList(String companyId, String filterItemsStr,
- ReportOrgUtil.OrgScope centerScope) throws BOSException, SQLException {
- List<ReportOrgUtil.OrgNameCode> centers = ReportOrgUtil.getDistinctOrgNameCodes(
- ctx, ReportOrgUtil.LAYER_CENTER, companyId);
- centers = applyCenterFastFilter(centers, centerScope);
- List<ReportOrgUtil.OrgNameCode> result = ReportOrgUtil.filterOrgNameCodes(centers, filterItemsStr);
- logger.error("中心数量: " + result.size());
- return result;
- }
- private List<ReportOrgUtil.OrgNameCode> applyCenterFastFilter(List<ReportOrgUtil.OrgNameCode> centers,
- ReportOrgUtil.OrgScope centerScope) {
- if (centerScope == null) {
- return centers;
- }
- if (!StringUtils.isEmpty(centerScope.orgName)) {
- List<ReportOrgUtil.OrgNameCode> filtered = new ArrayList<ReportOrgUtil.OrgNameCode>();
- for (ReportOrgUtil.OrgNameCode center : centers) {
- if (centerScope.orgName.equals(center.orgName)) {
- filtered.add(center);
- }
- }
- return filtered.isEmpty() ? centers : filtered;
- }
- return centers;
- }
- private PersonnelStatUtil.StatScope buildCenterStatScope(String centerName, String companyId) {
- return PersonnelStatUtil.StatScope.center(centerName, companyId);
- }
- }
|