package com.kingdee.eas.custom.perfweb.service;
import com.kingdee.bos.BOSException;
import com.kingdee.bos.Context;
import com.kingdee.bos.bsf.service.app.IHRMsfService;
import com.kingdee.bos.metadata.entity.EntityViewInfo;
import com.kingdee.bos.metadata.entity.FilterInfo;
import com.kingdee.bos.metadata.entity.FilterItemInfo;
import com.kingdee.bos.metadata.entity.SelectorItemCollection;
import com.kingdee.bos.metadata.entity.SelectorItemInfo;
import com.kingdee.bos.metadata.query.util.CompareType;
import com.kingdee.eas.basedata.org.AdminOrgUnitInfo;
import com.kingdee.eas.common.EASBizException;
import com.kingdee.eas.custom.perfweb.AssessmentResultDescriptionCollection;
import com.kingdee.eas.custom.perfweb.AssessmentResultDescriptionFactory;
import com.kingdee.eas.custom.perfweb.AssessmentResultDescriptionInfo;
import com.kingdee.eas.custom.perfweb.IAssessmentResultDescription;
import com.kingdee.eas.custom.perfweb.bizEnum.AutoStatusEnum;
import com.kingdee.eas.custom.perfweb.utils.CenterOrgUtil;
import com.kingdee.shr.perfweb.app.base.evalplan.EvaResultSummaryCollection;
import com.kingdee.shr.perfweb.app.base.evalplan.EvaResultSummaryFactory;
import com.kingdee.shr.perfweb.app.base.evalplan.EvaResultSummaryInfo;
import com.kingdee.shr.perfweb.app.base.evalplan.IEvaResultSummary;
import com.kingdee.shr.perfweb.app.base.evalplan.EvaPeriodStatusEnum;
import com.kingdee.shr.perfweb.app.base.evalplan.IPerfPeriod;
import com.kingdee.shr.perfweb.app.base.evalplan.PerfEvaObjectInfo;
import com.kingdee.shr.perfweb.app.base.evalplan.PerfPeriodCollection;
import com.kingdee.shr.perfweb.app.base.evalplan.PerfPeriodFactory;
import com.kingdee.shr.perfweb.app.base.evalplan.PerfPeriodInfo;
import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* 绩效考核结果报表 MSF/OSF 查询服务。
*
* 以「考核结果说明」({@code AssessmentResultDescription}) 为主表,一个中心组织对应一条报表数据;
* 各等级推荐/实际人数从考核结果汇总按中心及其全部下级组织范围内员工统计。
* 审批、飞书推送由列表页 Handler 处理,不在本服务内实现。
*
* 入参:periodId(选填,空则取考核中最新考核周期)、orgId(选填,按组织过滤)
*
* 作 者: 青梧
* 创建日期: 2026-06-17
*/
public class CenterPerfStatService implements IHRMsfService {
private static final Logger logger = Logger.getLogger(CenterPerfStatService.class);
/**
* MSF 入参:考核周期 ID
*/
private static final String PARAM_PERIOD_ID = "periodId";
/**
* MSF 入参:行政组织 ID
*/
private static final String PARAM_ORG_ID = "orgId";
/**
* 绩效等级顺序(与报表原型一致)
*/
private static final List GRADE_ORDER = Arrays.asList("S", "A+", "A", "B", "C");
/**
* 各等级分布占比(%):S=5, A+=25, A=45, B=20, C=5。
* A 等级标准人数不直接按比例四舍五入,见 {@link #calcStandardRecommendCounts(int)}。
*/
private static final Map GRADE_PERCENT = new LinkedHashMap<>();
/**
* S/A+/B/C 按占比四舍五入取标准人数;A 用剩余人数兜底
*/
private static final List ROUNDED_GRADE_ORDER = Arrays.asList("S", "A+", "B", "C");
/**
* 考核状态枚举值 → 单据字段展示名
*/
private static final Map AUTO_STATUS_LABELS = new LinkedHashMap<>();
/**
* 考核状态 → 报表「单据状态」列展示名(未提交 / 审批中 / 已通过)
*/
private static final Map BILL_STATUS_LABELS = new LinkedHashMap<>();
static {
GRADE_PERCENT.put("S", 5);
GRADE_PERCENT.put("A+", 25);
GRADE_PERCENT.put("A", 45);
GRADE_PERCENT.put("B", 20);
GRADE_PERCENT.put("C", 5);
AUTO_STATUS_LABELS.put(AutoStatusEnum.WFQ_VALUE, "未发起");
AUTO_STATUS_LABELS.put(AutoStatusEnum.ZJSPZ_VALUE, "总监审批中");
AUTO_STATUS_LABELS.put(AutoStatusEnum.ZJLSPZ_VALUE, "总经理审批中");
AUTO_STATUS_LABELS.put(AutoStatusEnum.SPTG_VALUE, "审批通过");
BILL_STATUS_LABELS.put(AutoStatusEnum.WFQ_VALUE, "未提交");
BILL_STATUS_LABELS.put(AutoStatusEnum.ZJSPZ_VALUE, "审批中");
BILL_STATUS_LABELS.put(AutoStatusEnum.ZJLSPZ_VALUE, "审批中");
BILL_STATUS_LABELS.put(AutoStatusEnum.SPTG_VALUE, "已通过");
}
public CenterPerfStatService() {
}
/**
* MSF 统一入口:按 periodId、orgId 查询报表 JSON。
*/
@Override
public Object process(Context context, Map params) throws EASBizException, BOSException {
if (params == null) {
params = new HashMap<>();
}
String periodId = getStringParam(params, PARAM_PERIOD_ID);
String orgId = getStringParam(params, PARAM_ORG_ID);
logger.info("CenterPerfStatService.process periodId=" + periodId + ",orgId=" + orgId);
return queryReport(context, periodId, orgId);
}
/**
* 查询绩效考核结果报表:主表为考核结果说明,一组织一行。
*
* @param ctx 上下文
* @param periodId 考核周期 ID(选填,空则取默认周期)
* @param orgId 行政组织 ID(选填,快速过滤手工选择)
*/
public static Map queryReport(Context ctx, String periodId, String orgId) {
return queryReport(ctx, periodId, orgId, null);
}
/**
* 查询绩效考核结果报表:主表为考核结果说明,一组织一行。
*
* @param ctx 上下文
* @param periodId 考核周期 ID(选填,空则取默认周期)
* @param orgId 行政组织 ID(选填,快速过滤手工选择)
* @param adminOrgRangeIds 当前用户行政组织范围(未选手工组织时由 Handler 传入,对标品 getCurrentRequestAdminOrgRangeIdSet)
*/
public static Map queryReport(Context ctx, String periodId, String orgId, Set adminOrgRangeIds) {
Map result = baseResult();
try {
if (StringUtils.isBlank(periodId)) {
periodId = resolveDefaultPeriodId(ctx);
}
if (StringUtils.isBlank(periodId)) {
return fail(result, "未找到状态为考核中的考核周期");
}
PerfPeriodInfo period = loadPeriod(ctx, periodId);
if (period == null) {
return fail(result, "未找到考核周期,periodId=" + periodId);
}
// 主表:考核结果说明;orgId 选手工过滤,否则按 adminOrgRangeIds 系统组织范围过滤
AssessmentResultDescriptionCollection collection = loadDescriptionByPeriod(ctx, periodId);
List centerContexts = buildCenterContexts(ctx, collection, orgId, adminOrgRangeIds);
// 按中心组织树汇总各等级人数(中心 + 全部下级部门员工)
Map gradeAggMap = aggregateGradeByCenter(ctx, periodId, centerContexts);
List