package com.yonyou.hrcloud.pm.result.impl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

import javax.annotation.Resource;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.yonyou.hrcloud.adder.context.AppContext;
import com.yonyou.hrcloud.adder.exception.AdderBusinessException;
import com.yonyou.hrcloud.adder.model.param.PagerRequest;
import com.yonyou.hrcloud.adder.model.param.Sorter;
import com.yonyou.hrcloud.adder.model.query.Condition;
import com.yonyou.hrcloud.adder.model.query.Operator;
import com.yonyou.hrcloud.pm.base.model.Grade;
import com.yonyou.hrcloud.pm.base.model.GradeItem;
import com.yonyou.hrcloud.pm.base.model.Indicator;
import com.yonyou.hrcloud.pm.base.model.Period;
import com.yonyou.hrcloud.pm.base.service.IGradeService;
import com.yonyou.hrcloud.pm.base.service.IPeriodService;
import com.yonyou.hrcloud.pm.common.model.CommonValue;
import com.yonyou.hrcloud.pm.common.model.CommonValue.EnumAuditType;
import com.yonyou.hrcloud.pm.common.model.CommonValue.EnumDistType;
import com.yonyou.hrcloud.pm.common.model.CommonValue.EnumMarkState30;
import com.yonyou.hrcloud.pm.common.model.CommonValue.EnumWorkStep;
import com.yonyou.hrcloud.pm.common.model.CommonValue.EnumWorkflowState;
import com.yonyou.hrcloud.pm.common.model.CommonValue.EnumWorkflowType;
import com.yonyou.hrcloud.pm.common.model.PmStaff;
import com.yonyou.hrcloud.pm.helper.LoggerDecorator;
import com.yonyou.hrcloud.pm.helper.OrgHelper;
import com.yonyou.hrcloud.pm.helper.ListHelper;
import com.yonyou.hrcloud.pm.helper.StaffHelper;
import com.yonyou.hrcloud.pm.helper.Systemutil;
import com.yonyou.hrcloud.pm.notice.model.NoticeBaseParam;
import com.yonyou.hrcloud.pm.notice.model.NoticeExtendParam;
import com.yonyou.hrcloud.pm.notice.service.INoticeEngineService;
import com.yonyou.hrcloud.pm.notice.service.INoticeFactoryService;
import com.yonyou.hrcloud.pm.pa.model.AppraiseData;
import com.yonyou.hrcloud.pm.pa.service.IAppraiseService;
import com.yonyou.hrcloud.pm.ps.model.ApproverGroup;
import com.yonyou.hrcloud.pm.ps.model.Distribution;
import com.yonyou.hrcloud.pm.ps.model.DistributionItem;
import com.yonyou.hrcloud.pm.ps.model.EvaAppraiser;
import com.yonyou.hrcloud.pm.ps.model.EvaGroup;
import com.yonyou.hrcloud.pm.ps.model.Scheme;
import com.yonyou.hrcloud.pm.ps.model.Sheet;
import com.yonyou.hrcloud.pm.ps.model.SheetIndicator;
import com.yonyou.hrcloud.pm.ps.service.IEvaGroupService;
import com.yonyou.hrcloud.pm.ps.service.IResultSettingService;
import com.yonyou.hrcloud.pm.ps.service.ISchemeService;
import com.yonyou.hrcloud.pm.ps.service.ISheetIndicatorService;
import com.yonyou.hrcloud.pm.ps.service.ISheetService;
import com.yonyou.hrcloud.pm.result.dao.IApproveScoreDao;
import com.yonyou.hrcloud.pm.result.model.ApproveScore;
import com.yonyou.hrcloud.pm.result.model.Score;
import com.yonyou.hrcloud.pm.result.service.IApproveScoreService;
import com.yonyou.hrcloud.pm.result.service.IScoreService;
import com.yonyou.hrcloud.pm.wf.model.BaseParam;
import com.yonyou.hrcloud.pm.wf.model.Event;
import com.yonyou.hrcloud.pm.wf.model.WorkflowEngine;
import com.yonyou.hrcloud.pm.wf.model.WorkflowParam;
import com.yonyou.hrcloud.pm.wf.service.IWorkflowService;

/**
 * 结果审核实现层
 *
 * @author Flysea
 */
@Service
@Transactional
public class ApproveScoreServiceImpl implements IApproveScoreService {

	@Resource
	public com.yonyou.hrcloud.adder.service.IGenericService daoex;

	@Resource
	public ISheetService sheetServ;

	@Resource
	public IAppraiseService apprServ;

	@Resource
	public IWorkflowService wfService;

	@Resource
	public IScoreService scoreService;

	@Resource
	public IResultSettingService rsService;

	@Resource
	public ISchemeService schemeService;

	@Resource
	public IGradeService gradeService;

	@Resource
	public IEvaGroupService groupService;

	@Resource
	public INoticeFactoryService fService;

	@Resource
	public IPeriodService periodSrv;

	@Resource
	public INoticeEngineService noticeEngineService;

	@Resource
	ISheetIndicatorService sheetIndiServ;
	
    @Resource
    public IApproveScoreDao dao;
    
    protected static final Logger logger = new LoggerDecorator(ApproveScoreServiceImpl.class);
    
	@Override
	public List<ApproveScore> queryApproveScoreByConditon(Condition cond, Sorter sort) {
		return daoex.find(ApproveScore.class, cond, sort);
	}

	@Override
	public List<Object> queryMultiSchemeByAuditState(Integer flag) {
		if (flag > 1 || flag < 0)
			throw new AdderBusinessException("不正确的参数","pm.i18n_pbc.pa.001");
		String userId = AppContext.getContext().getUserId();
		String staffid = StaffHelper.getStaffByUserId(userId);
		List<Scheme> schemeList = new ArrayList<Scheme>();
		List<String> schemeids = new ArrayList<String>();
		List<Object> retList = new ArrayList<Object>();
		// 准备查询工作流条件
		BaseParam param = new BaseParam();
		param.setBiztype(EnumWorkflowType.performance);
		param.setWorkstep(EnumWorkStep.step3);
		param.setCurrentOperator(staffid);
		if (flag == 0) {
			// 查询工作流，获得当前人的结果审核状态的待处理方案
			param.setWorkflowState(EnumWorkflowState.PENDING);
			List<WorkflowEngine> wfList = wfService.queryWorkflowEngine(param);
			retList = getMultiSchemeList(wfList, flag);
		} else if (flag == 1) {
			Condition condObj = new Condition();
			Sorter sortObj = new Sorter(Direction.DESC, "fdate");
			// edit by nijb 20201218 考核结果已审核列表查询包含已结束的方案
			condObj.addExpression("schemestate",
					CommonValue.EnumSchemeState.State7.ordinal(), Operator.GREATEREQUAL);
			// 获取结果审核中的方案
			schemeList = daoex.find(Scheme.class, condObj, sortObj);
			for (Scheme scheme : schemeList) {
				if (!schemeids.contains(scheme.getId()))
					schemeids.add(scheme.getId());
			}
			// 和评分处不同，审核人可重复。查询工作流中有我处理过的，已审核过的方案
			param.setBizinfo(schemeids);
			param.setWorkflowState(CommonValue.EnumWorkflowState.PASS_AUDIT);
			List<WorkflowEngine> wfList = wfService.queryWorkflowEngine(param);
			schemeids.clear();
			retList = getMultiSchemeList(wfList, flag);
		}
		return retList;
	}

	@Override
	public List<Scheme> querySchemeByAuditState(Integer flag) {
		if (flag > 1 || flag < 0)
			throw new AdderBusinessException("不正确的参数","pm.i18n_pbc.pa.001");
		String userId = AppContext.getContext().getUserId();
		String staffid = StaffHelper.getStaffByUserId(userId);
		List<Scheme> schemeList = new ArrayList<Scheme>();
		List<String> schemeids = new ArrayList<String>();
		// 准备查询工作流条件
		Condition condObj = new Condition();
		Sorter sortObj = new Sorter(Direction.DESC, "fdate");
		BaseParam param = new BaseParam();
		param.setBiztype(EnumWorkflowType.performance);
		param.setWorkstep(EnumWorkStep.step3);
		param.setCurrentOperator(staffid);
		if (flag == 0) {
			// 查询工作流，获得当前人的结果审核状态的待处理方案
			param.setWorkflowState(EnumWorkflowState.PENDING);
			List<WorkflowEngine> wfList = wfService.queryWorkflowEngine(param);
			// 得到待处理的方案id集合
			for (WorkflowEngine wf : wfList) {
				String schemeid = wf.getBizinfo();
				if (!schemeids.contains(schemeid)) {
					schemeids.add(schemeid);
				}
			}
			if (schemeids.size() > 0) {
				condObj.addExpression("id", schemeids, Operator.IN);
				condObj.addExpression("schemestate",
						CommonValue.EnumSchemeState.State7.ordinal());
				schemeList = daoex.find(Scheme.class, condObj, sortObj);
			}
		} else if (flag == 1) {
			condObj.addExpression("schemestate",
					CommonValue.EnumSchemeState.State7.ordinal());
			// 获取结果审核中的方案
			schemeList = daoex.find(Scheme.class, condObj, sortObj);
			for (Scheme scheme : schemeList) {
				if (!schemeids.contains(scheme.getId()))
					schemeids.add(scheme.getId());
			}
			// 和评分处不同，工作流中有我处理的，已审核过的方案
			param.setBizinfo(schemeids);
			param.setWorkflowState(CommonValue.EnumWorkflowState.PASS_AUDIT);
			List<WorkflowEngine> wfList = wfService.queryWorkflowEngine(param);
			schemeids.clear();
			for (WorkflowEngine wf : wfList) {
				if (!schemeids.contains(wf.getBizinfo()))
					schemeids.add(wf.getBizinfo());
			}
			// 方案集合中不在schemeids中则要删除
			for (int i = schemeList.size() - 1; i >= 0; i--) {
				if (!schemeids.contains(schemeList.get(i).getId()))
					schemeList.remove(i);
			}
		}
		return schemeList;
	}

	@Override
	public ApproveScore queryApproveScoreByID(String id) {
		List<ApproveScore> appScoreList = new ArrayList<ApproveScore>();
		ApproveScore obj = daoex.load(ApproveScore.class, id);
		if (obj == null)
			throw new AdderBusinessException("结果审核数据不存在","pm.i18n_pbc.result.001");
		appScoreList.add(obj);
		List<String> sheetids = new ArrayList<String>();
		sheetids.add(obj.getSheetid());
		Sheet sheet = daoex.load(Sheet.class, obj.getSheetid());
		Map<String, String> sheetMap = new Hashtable<String, String>();
		sheetMap.put(obj.getSheetid(), sheet.getStaffid());
		setApproveScoreInfo(sheetids, sheetMap, appScoreList);
		return appScoreList.get(0);
	}

	@Override
	public List<ApproveScore> queryStaffByScheme(String schemeid, Integer flag, Integer markFlag) {
		if (markFlag != null && (markFlag > 2 || markFlag < 1))
			throw new AdderBusinessException("不正确的参数","pm.i18n_pbc.pa.001");
		// 获取人员集合
		List<ApproveScore> appScoreList = getAppScoreWithStaff(Arrays.asList(schemeid), flag, markFlag);
		// 按等级排序
		sortApproveScore(schemeid, appScoreList);
		return appScoreList;
	}

	@Override
	public List<ApproveScore> queryStaffBySchemeGroup(String schemegroupid, Integer flag, Integer markFlag) {
		if (markFlag != null && (markFlag > 2 || markFlag < 1))
			throw new AdderBusinessException("不正确的参数","pm.i18n_pbc.pa.001");
		// 获取人员集合
		List<String> schemeids = rsService.querySchemeidsByGroupid(schemegroupid);
		List<ApproveScore> appScoreList = getAppScoreWithStaff(schemeids, flag, markFlag);
		return appScoreList;
	}
	
	@Override
	public JSONObject queryGradeStaffByScheme(String id, Integer flag, Integer markFlag) {
		Condition condObj = new Condition();
		condObj.addExpression("schemegroupid", id);
		List<ApproverGroup> appGroup = daoex.find(ApproverGroup.class, condObj, null);
		JSONObject jsonReturn = new JSONObject();
		if (appGroup.isEmpty()) {
			// id是方案id
			String schemeid = id;
			Scheme scheme = daoex.load(Scheme.class, schemeid);
			// 查询结果审核方案下人员
			List<ApproveScore> appScoreList = queryStaffByScheme(schemeid, flag, markFlag);
			if (appScoreList.isEmpty())
				throw new AdderBusinessException("未查询到结果审核数据","pm.i18n_pbc.result.002");
			// 方案下考核组会进行分组
			jsonReturn = queryApproveScoreByDist(scheme, appScoreList);
		} else {
			// 多方案id，查询多方案下人员
			List<ApproveScore> appScoreList = queryStaffBySchemeGroup(id, flag, markFlag);
			if (appScoreList.isEmpty())
				throw new AdderBusinessException("未查询到结果审核数据","pm.i18n_pbc.result.002");
			jsonReturn = queryApproveScoreByDist(appGroup, appScoreList);
		}
		return jsonReturn;
	}

	@Override
	public void saveScore(ApproveScore appScore) {
		ApproveScore newAppScore = daoex.load(ApproveScore.class, appScore.getId());
		if (newAppScore == null)
			throw new AdderBusinessException("数据不存在", "pm.i18n_pbc.result.003");
		if (newAppScore.getMarkStatus() == CommonValue.EnumMarkState30.State3.getIndex())
			throw new AdderBusinessException("流程状态不匹配！", "pm.i18n_flow.wf.003");
		newAppScore.setComment(appScore.getComment());
		newAppScore.setGradeitemid(appScore.getGradeitemid());
		newAppScore.setGradeitemname(appScore.getGradeitemname());
		
		Scheme scheme = schemeService.querySchemeByID(appScore.getSchemeid(), false);
		if(scheme.isIsaccount()) {
			newAppScore.setOneScore(appScore.getOneScore() == null ? BigDecimal.ZERO : appScore.getOneScore());
			newAppScore.setSecondScore(appScore.getSecondScore() == null ? BigDecimal.ZERO : appScore.getSecondScore());
			newAppScore.setThirdScore(appScore.getThirdScore() == null ? BigDecimal.ZERO : appScore.getThirdScore());
			BigDecimal score = appScore.getScore();
			score = score.subtract(newAppScore.getOneScore()).subtract(newAppScore.getSecondScore().multiply(new BigDecimal("2"))).subtract(newAppScore.getThirdScore().multiply(new BigDecimal("3")));
			newAppScore.setScore(score);
		}else {
			newAppScore.setScore(appScore.getScore());
		}
		
		daoex.update(newAppScore);
	}

	@Override
	public Sheet queryApproveScore(String sheetid) {
		// 20200108判断量表结果是导入的，则不允许看明细
		Condition condObj = new Condition();
		condObj.addExpression("sheetid", sheetid);
		List<SheetIndicator> indis = sheetIndiServ.querySheetIndicators(condObj, null);
		if (indis.isEmpty())
			throw new AdderBusinessException("该人员在此方案没有结果详情数据", "pm.i18n_pbc.result.015");
		Sheet sheet = sheetServ.querySheetByID(sheetid, true);
		if (sheet == null)
			throw new AdderBusinessException("数据不存在", "pm.i18n_pbc.result.003");
		Systemutil.checkSafety(sheet.getTenantid());
		condObj = new Condition();
		condObj.addExpression("sheetid", sheetid);
		condObj.addExpression("columncode", Arrays.asList("008", "009"), Operator.IN);
		Sorter sortObj = new Sorter(Direction.ASC, "indicatorid", "turn", "columncode");
		// 查询出此量表的评价数据
		List<AppraiseData> apprList = apprServ.queryAppraiseDataByCondition(condObj, sortObj);
		Map<String, PmStaff> staffsMap = StaffHelper.getStaffListConcise(apprList, "getAppraiser");
		// 把评价数据转换成Map<指标id,评价轮次数据集合>
		Map<String, List<AppraiseData>> dataMap = new HashMap<String, List<AppraiseData>>();
		for (AppraiseData item : apprList) {
			item.setAppraisername(staffsMap.get(item.getAppraiser()).name);
			if (!dataMap.containsKey(item.getIndicatorid()))
				dataMap.put(item.getIndicatorid(), new ArrayList<AppraiseData>());
			dataMap.get(item.getIndicatorid()).add(item);
		}
		// 和量表指标数据整合
		for (SheetIndicator item : sheet.getOSheetIndis()) {
			// 循环每一条指标，把轮次数据赋值到oAppraiseData
			Map<String, AppraiseData> oAppraiseData = new HashMap<String, AppraiseData>();
			for (AppraiseData item2 : dataMap.get(item.getIndicatorid())) {
				// 结果审核有轮次数据，用轮次代替了原来的栏目编码，为了显示评分说明，在AppraiseData加了栏目扩展
				// 顺序是1-008、1-009、2-008、2-009
				if (item2.getColumncode().equals(CommonValue.EnumSchemeScoreColumnCode.CODE008.getCode())) {
					oAppraiseData.put(String.valueOf(item2.getTurn()), item2);
				} else {
					AppraiseData col008 = oAppraiseData.get(String.valueOf(item2.getTurn()));
					if (col008 != null) {
						if (col008.getOColumn() == null) {
							Map<String, Object> otherCols = new HashMap<>();
							col008.setOColumn(otherCols);
						}
						col008.getOColumn().put(item2.getColumncode(), item2);
					}
				}
			}
			item.setOAppraiseData(oAppraiseData);
		}
		// querySheetByID里已经有Scoreway
		// Scheme scheme = daoex.load(Scheme.class, sheet.getSchemeid());
		// sheet.setScoreway(scheme.getScoreway());
		return sheet;
	}

	@Override
	public Map<String, Object> queryResultScore(String id, String staffid) {
		ApproveScore appScore = daoex.load(ApproveScore.class, id);
		if (appScore != null && appScore.getAuditor().equals(staffid)) {
			Map<String, Object> obj = new Hashtable<String, Object>();
			Condition condObj = new Condition();
			condObj.addExpression("sheetid", appScore.getSheetid());
			condObj.addExpression("columncode", Arrays.asList("002", "004"), Operator.IN);
			List<Score> objs = daoex.find(Score.class, condObj, null);
			if (objs.get(0).getColumncode().equals("002")) {
				obj.put("score", objs.get(0).getNumvalue());
				obj.put("grade", objs.get(1).getText());
			} else {
				obj.put("score", objs.get(1).getNumvalue());
				obj.put("grade", objs.get(0).getText());
			}
			return obj;
		} else
			return null;
	}

	@Override
	public Map<String, Object> queryResultScoreAll(String id, String schemeid, String staffid) {
		Scheme scheme = schemeService.querySchemeByID(schemeid, false);
		if (scheme == null)
			throw new AdderBusinessException("数据不存在","pm.i18n_pbc.result.003");
		Map<String, Object> obj = new Hashtable<String, Object>();
		// 原始得分
		Map<String, Object> scoreMap = queryResultScore(id, staffid);
		if (scoreMap != null)
			obj.put("score", scoreMap);
		Grade grade = gradeService.queryGradeByID(scheme.getGradeid(), true);
		// 考核等级
		obj.put("grade", grade.getOGradeItem());
		// 结果审核人明细
		obj.put("detail", queryApproveScoreByID(id));
		return obj;
	}

	@Override
	public void doResultAudit(List<String> sheetids, String staffid) {
		doResultAudit(sheetids, staffid, true, false);
	}
	
	@Override
	public int doResultAudit(List<String> sheetids, String staffid, boolean isforce, boolean isreturn) {
		// sheetids要么是方案的，要么是一个组下的人，不能是多考核对象组的人（强分不同）
		// 查询当前轮次
		int turn = getCurrentTurn(0, sheetids.get(0), staffid);
		// 根据当前量表，当前审核人及轮次 查找审核记录以进行批准
		Condition condObj = new Condition();
		condObj.addExpression("sheetid", sheetids, Operator.IN);
		condObj.addExpression("auditor", staffid);
		condObj.addExpression("turn", turn);
		List<ApproveScore> appScoreList = daoex.find(ApproveScore.class, condObj, null);
		if (appScoreList == null || appScoreList.isEmpty()) {
			throw new AdderBusinessException("数据不存在", "pm.i18n_pbc.result.003");
		} else if (sheetids.size() != appScoreList.size())
			throw new AdderBusinessException("人员数量不符合", "pm.i18n_pbc.result.004");
		// groupids包含考核对象组id和多方案组id
		List<String> groupids = new ArrayList<String>();
		for (ApproveScore item : appScoreList) {
			if (item.getGroupid() != null && !groupids.contains(item.getGroupid()))
				groupids.add(item.getGroupid());
		}
		Scheme scheme = schemeService.querySchemeByID(appScoreList.get(0).getSchemeid(), false);
		if (groupids.size() > 1)
			throw new AdderBusinessException("不支持多组审核", "pm.i18n_pbc.result.005");
		else if (groupids.size() == 0) {
			// 方案审核下，汇总审核检查所有组是否已审核
			condObj = new Condition();
			condObj.addExpression("schemeid", scheme.getId());
			condObj.addExpression("mark_status", Arrays.asList(EnumMarkState30.State1.getIndex(),
					EnumMarkState30.State2.getIndex(), EnumMarkState30.State4.getIndex()), Operator.IN);
			condObj.addExpression("audittype", 1);
			Pageable page = new PagerRequest(0, 3);
			List<ApproveScore> appScoreTmp = daoex.findPage(ApproveScore.class, condObj, page).getContent();
			if (!appScoreTmp.isEmpty()) {
				throw new AdderBusinessException("还有前轮次人员未审核", "pm.i18n_pbc.result.006");
			}
		}
		// 检查是否强分通过
		// 判断sheetids属于组还是方案？
		if (groupids.size() == 0) {
			// 方案级
			if (scheme.getDistid() != null) {
				boolean checked = checkDistributionByScheme(scheme.getId());
				Distribution distObj = rsService.queryDistributionByCondition(scheme.getDistid());
				if (distObj == null) {
					return 0;
				}
				if (isreturn) {
					// 前端首先会调用isreturn，判断是否需要提示不严格强分。1提示0不提示
					if (!checked && distObj.getDistway() == CommonValue.EnumDistWay.way2.getIndex())
						return 1;
					else
						return 0;
				} else if (!checked) {
					if (!isforce || distObj.getDistway() == CommonValue.EnumDistWay.way3.getIndex())
						throw new AdderBusinessException("不符合强制分布规则", "pm.i18n_pbc.result.007");
				}
			} else if (isreturn)
				return 0;
		} else if (appScoreList.get(0).getAudittype() == 1) {
			// 对象组
			boolean checked = checkDistributionByGroup(scheme.getId(), groupids.get(0));
			if (isreturn) {
				if (!checked && isDistributeWay2(groupids.get(0), appScoreList.get(0).getAudittype()))
					return 1;
				else
					return 0;
			} else if (!checked) {
				if (!isforce || !isDistributeWay2(groupids.get(0), appScoreList.get(0).getAudittype()))
					throw new AdderBusinessException("不符合强制分布规则", "pm.i18n_pbc.result.007");
			}
		} else {
			boolean checked = checkDistributionBySchemeGroup(groupids.get(0));
			if (isreturn) {
				if (!checked && isDistributeWay2(groupids.get(0), appScoreList.get(0).getAudittype()))
					return 1;
				else
					return 0;
			} else if (!checked) {
				if (!isforce || !isDistributeWay2(groupids.get(0), appScoreList.get(0).getAudittype()))
					throw new AdderBusinessException("不符合强制分布规则", "pm.i18n_pbc.result.007");
			}
		}
		Integer nextTurn = null;
		for (ApproveScore appScore : appScoreList) {
			// 获取当前评分记录
			appScore.setMarkStatus(CommonValue.EnumMarkState30.State3.getIndex());
			appScore.setAprTime(new Date());
			// 如果第一轮没有保存过，则score是空，需要取一下
			if (appScore.getGradeitemid() == null) {
				condObj = new Condition();
				condObj.addExpression("sheetid", appScore.getSheetid());
				condObj.addExpression("columncode", Arrays.asList("002", "004"), Operator.IN);
				Sorter sortObj = new Sorter(Direction.ASC, "columncode");
				List<Score> scoreList = daoex.find(Score.class, condObj, sortObj);
				appScore.setScore(scoreList.get(0).getNumvalue());
				String strGradeItemID = gradeService.queryGradeItemIdByName(scheme.getGradeid(),
						scoreList.get(1).getText());
				appScore.setGradeitemid(strGradeItemID);
				appScore.setGradeitemname(scoreList.get(1).getText());
			}
			if (!daoex.update(appScore)){
				throw new AdderBusinessException("更新数据失败", "pm.i18n_core.comm.022");
			}
			// 把当前轮次的得分和等级更新到下一轮次
			// 2019-7-23由于考核组轮次总数不一定一样，会有跨轮次推动
			if (nextTurn == null) {
				nextTurn = getNextTurn(appScore.getSheetid(), appScore.getTurn());
				if (nextTurn == null)
					nextTurn = 0;
			}
			if (nextTurn > 0) {
				// 没有下一轮次就不用更新了
				condObj = new Condition();
				condObj.addExpression("sheetid", appScore.getSheetid());
				condObj.addExpression("turn", nextTurn);
				List<ApproveScore> appScoreNextList = daoex.find(ApproveScore.class, condObj, null);
				if (!appScoreNextList.isEmpty()) {
					for (ApproveScore item : appScoreNextList) {
						item.setScore(appScore.getScore());
						item.setGradeitemid(appScore.getGradeitemid());
						item.setGradeitemname(appScore.getGradeitemname());
						item.setComment(appScore.getComment());
						item.setOneScore(appScore.getOneScore() == null ? BigDecimal.ZERO : appScore.getOneScore());
						item.setSecondScore(appScore.getSecondScore() == null ? BigDecimal.ZERO : appScore.getSecondScore());
						item.setThirdScore(appScore.getThirdScore() == null ? BigDecimal.ZERO : appScore.getThirdScore());
						if (!daoex.update(item))
							throw new AdderBusinessException("更新数据失败", "pm.i18n_core.comm.022");
					}
				}
			}
		}
		// 批量更新工作流，回调效率低
		WorkflowParam param = new WorkflowParam();
		param.setBizids(sheetids);
		param.setWorkstep(EnumWorkStep.step3);
		param.setCurrentOperator(staffid);
		param.setStepserial(turn);
		param.setWorkflowState(EnumWorkflowState.PASS_AUDIT);
		// 终审回调函数
		Event event = new Event("finalCallbackList", new Object[] { JSONArray.toJSONString(appScoreList) },
				IApproveScoreService.class);
		param.setEvent(event);
		try {
			wfService.updateWorkflowEngine(param);
		} catch (Exception e) {
			logger.error("pm:doResultAudit", e);
			throw new RuntimeException(e);
		}
		// 查询下轮代办审核人
		WorkflowParam wp = new WorkflowParam();
		wp.setBiztype(EnumWorkflowType.performance);
		wp.setBizinfo(Arrays.asList(scheme.getId()));
		wp.setWorkstep(EnumWorkStep.step3);
		wp.setWorkflowState(EnumWorkflowState.PENDING);
		List<WorkflowEngine> engins = wfService.queryWorkflowEngine(wp);
		if (engins != null && engins.size() > 0) {
			// 发送审核通知提醒 和 待办提醒
			NoticeExtendParam ep = new NoticeExtendParam("您有新的对" + scheme.getSchemename() + "方案的结果审核", scheme.getId(),
					Arrays.asList(engins.get(0).getDisposeperson()), false, true, true);
			ep.businessKey = String.format("resultAudit_%s", scheme.getId());// 待办的业务主键
			ep.isSynchronized = false;
			fService.getNoticeServiceToSend(CommonValue.EnumNoticeType.RESULTAUDIT, ep);
		}

		//结果审核后处理待办 liushm 2018-06-21
		NoticeBaseParam ep = new NoticeBaseParam();
		sheetids.add(scheme.getId());
		String businessKey = org.apache.commons.lang.StringUtils.join(sheetids.toArray(), ",").replace(",",
				",resultAudit_");
		ep.businessKey = String.format("%s_%s", "resultAudit", businessKey);
		noticeEngineService.disposeTODO(ep);
		return 0;
	}

	@Override
	public void doResultAbandoned(List<String> sheetids, String staffid) {
		// 查询当前轮次
		int turn = getCurrentTurn(1, sheetids.get(0), staffid);
		Condition condObj = new Condition();
		condObj.addExpression("sheetid", sheetids, Operator.IN);
		condObj.addExpression("auditor", staffid);
		condObj.addExpression("turn", turn);
		List<ApproveScore> appScoreList = daoex.find(ApproveScore.class, condObj, null);
		if (appScoreList != null && appScoreList.size() > 0) {
			Integer nextTurn = null;
			for (ApproveScore appScore : appScoreList) {
				String sheetid = appScore.getSheetid();
				// 获取当前审核记录
				if (appScore.getMarkStatus() != CommonValue.EnumMarkState30.State3.getIndex())
					throw new AdderBusinessException("不是已审核状态，无法弃审！", "pm.i18n_pbc.result.008");
				// 2019-7-23由于考核组轮次总数不一定一样，会有跨轮次推动
				if (nextTurn == null) {
					nextTurn = getNextTurn(appScore.getSheetid(), appScore.getTurn());
					if (nextTurn == null)
						nextTurn = 0;
				}
				// 获得下一轮的审核记录，如果已审核完成则不能收回
				condObj = new Condition();
				condObj.addExpression("sheetid", sheetid);
				condObj.addExpression("turn", nextTurn);
				List<ApproveScore> next_score = daoex.find(ApproveScore.class, condObj, null);
				for (int i = 0; next_score != null && i < next_score.size(); i++) {
					if (CommonValue.EnumMarkState30.State3.getIndex() == next_score.get(i).getMarkStatus()) {
						throw new AdderBusinessException("后轮次的审核人已审核，无法执行弃审！", "pm.i18n_pbc.result.009");
					}
				}
				// 判断当前量表是否已发布
				Sheet sheet = sheetServ.querySheetByID(sheetid);
				if (sheet != null && sheet.isIsrelease()) {
					throw new AdderBusinessException("绩效考核已发布", "pm.i18n_pbc.result.010");
				}

				appScore.setMarkStatus(CommonValue.EnumMarkState30.State2.getIndex());
				daoex.update(appScore, Arrays.asList("markStatus"));
				// 更新量表
				if (sheet != null && sheet.isIsover()) {
					sheet.setIsover(false);
					daoex.update(sheet);
				}
			}
			// 批量更新工作流
			WorkflowParam param = new WorkflowParam();
			param.setBizids(sheetids);
			param.setWorkstep(EnumWorkStep.step3);
			param.setCurrentOperator(staffid);
			param.setWorkflowState(EnumWorkflowState.PENDING);
			param.setCurrentAuditor(Arrays.asList(staffid));
			param.setStepserial(turn);
			try {
				wfService.updateWorkflowEngine(param);
			} catch (Exception e) {
				logger.error("pm:doResultAbandoned", e);
				throw new RuntimeException(e);
			}
		} else {
			throw new AdderBusinessException("数据不存在", "pm.i18n_pbc.result.003");
		}
	}

	@Override
	public void finalCallback(ApproveScore appScore) {
		// 赋值确认结果
		String sheetid = appScore.getSheetid();
		Sheet sheet = sheetServ.querySheetByID(sheetid);
		scoreService.saveObjectScore(sheet.getSchemeid(), sheet, appScore.getScore(), appScore.getGradeitemname(),
				true);
		sheet.setIsover(true);
		daoex.update(sheet);
	}

	@Override
	public void finalCallbackList(String scoreJson) {
		List<ApproveScore> appScoreList = JSONObject.parseArray(scoreJson, ApproveScore.class);
		if (appScoreList.isEmpty())
			return;
		// 20200209提高效率
		List<String> sheetids = appScoreList.stream().map(obj -> obj.getSheetid()).collect(Collectors.toList());
		List<Sheet> sheetList = daoex.findByIds(Sheet.class, sheetids.toArray(new String[0]));
		Map<String, Sheet> sheetMap = sheetList.stream().collect(Collectors.toMap(Sheet::getId, Function.identity()));
		for (ApproveScore appScore : appScoreList) {
			// 赋值确认结果
			String sheetid = appScore.getSheetid();
			Sheet sheet = sheetMap.get(sheetid);
			scoreService.saveObjectScore(sheet.getSchemeid(), sheet, appScore.getScore(), appScore.getGradeitemname(),
					true);
			sheet.setIsover(true);
			daoex.update(sheet, Arrays.asList("isover"));
		}
		sheetMap = null;
	}

	 /**
	  * 设置结果审核人的考核对象详细信息和GradeItemId
	  *
	  * @param sheetids
	 *            量表id集合
	 * @param sheetMap
	 *            量表和考核对象Map
	 * @param appScoreList
	 *            结果审核人数据集合
	 */
	private void setApproveScoreInfo(List<String> sheetids,
			Map<String, String> sheetMap, List<ApproveScore> appScoreList) {
		boolean isFirst = true;
		List<Score> scoreList = new ArrayList<Score>();
		List<String> staffidList = new ArrayList<String>();
		for (ApproveScore item : appScoreList) {
			// 获取考核对象id集合
			staffidList.add(sheetMap.get(item.getSheetid()));
			if (item.getScore() == null || item.getGradeitemname() == null) {
				if (isFirst) {
					// 获取考核对象计算结果、等级，当审核人数据为空则替换
					Condition condObj = new Condition();
					condObj.addExpression("sheetid", sheetids, Operator.IN);
					condObj.addExpression("columncode",
							Arrays.asList("002", "004"), Operator.IN);
					scoreList = daoex.find(Score.class, condObj, null);
					isFirst = false;
				}
				Score item2 = new Score(); /*scoreList
						.stream()
						.filter(obj -> obj.getSheetid().equals(
								item.getSheetid())
								&& obj.getColumncode().equals("002"))
						.findFirst().get();*/
				for(Score obj : scoreList){
					if(obj.getSheetid().equals(item.getSheetid())
								&& obj.getColumncode().equals("002")){
						item2 = obj;
						break;
					}
				}
				item.setScore(item2.getNumvalue());
				/*item2 = scoreList
						.stream()
						.filter(obj -> obj.getSheetid().equals(
								item.getSheetid())
								&& obj.getColumncode().equals("004"))
						.findFirst().get();*/
				for(Score obj : scoreList){
					if(obj.getSheetid().equals(item.getSheetid())
							&& obj.getColumncode().equals("004")){
						item2 = obj;
						break;
					}
				}
				item.setGradeitemname(item2.getText());
			}
		}
		// 获取方案的考核等级，添加GradeItemId
		Scheme scheme = daoex
				.load(Scheme.class, appScoreList.get(0).getSchemeid());
		Grade grade = gradeService.queryGradeByID(scheme.getGradeid(), true);
		addGradeItemIdForApproveScore(grade, appScoreList);
		// 设置人员信息
		Map<String, PmStaff> staffList = StaffHelper
				.queryStaffByIds(staffidList);
		StaffHelper.simplifyStaff(staffList);
		for (ApproveScore item : appScoreList) {
			item.setStatusname(CommonValue.EnumMarkState30.values()[item
					.getMarkStatus() - 1].getDescription());
			String strid = sheetMap.get(item.getSheetid());
			item.setStaff(staffList.get(strid));
		}
		scoreList = null;
	}

	/**
	 * 对结果审核中考核对象按等级倒序，Ordernum
	 * 
	 * @param schemeid
	 * @param appScoreList
	 */
	private void sortApproveScore(String schemeid,
			List<ApproveScore> appScoreList) {
		Scheme scheme = daoex.load(Scheme.class, schemeid);
		Condition condObj = new Condition();
		condObj.addExpression("gradeid", scheme.getGradeid());
		Sorter sortObj = new Sorter(Direction.ASC, "ordernum");
		// 获取方案的考核等级明细
		List<GradeItem> gradeItemList = daoex.find(GradeItem.class, condObj,
				sortObj);
		final Map<String, Integer> gradeItemMap = new HashMap<String, Integer>(); /*gradeItemList.stream().collect(
				Collectors.toMap(GradeItem::getGradeitemname,
						GradeItem::getOrdernum));*/
		for(GradeItem item : gradeItemList){ 
			gradeItemMap.put(item.getGradeitemname(), item.getOrdernum());
		}
		Collections.sort(appScoreList, new Comparator<ApproveScore>() {
			@Override
			public int compare(ApproveScore o1, ApproveScore o2) {
				if (o1.getGradeitemname() == null
						&& o2.getGradeitemname() == null)
					return 0;
				else if (o1.getGradeitemname() == null
						&& o2.getGradeitemname() != null)
					return 1;
				else if (o1.getGradeitemname() != null
						&& o2.getGradeitemname() == null)
					return -1;
				else {
					int i = gradeItemMap.get(o1.getGradeitemname())
							- gradeItemMap.get(o2.getGradeitemname());
					if (i == 0)
						return 0 - o1.getScore().compareTo(o2.getScore());
					return i;
				}
			}
		});
	}

	/**
	 * 获得当前轮次
	 * 
	 * @param flag
	 *            0未审核1已审核
	 * @param sheetid
	 * @param staffid
	 *            处理人
	 * @return
	 */
	private int getCurrentTurn(int flag, String sheetid, String staffid) {
		// 查询当前轮次
		BaseParam baseparam = new BaseParam();
		baseparam.setBizid(sheetid);
		baseparam.setCurrentOperator(staffid);
		if (flag == 0)
			baseparam.setWorkflowState(CommonValue.EnumWorkflowState.PENDING);
		else
			baseparam.setWorkflowState(CommonValue.EnumWorkflowState.PASS_AUDIT);
		baseparam.setWorkstep(CommonValue.EnumWorkStep.step3);
		List<WorkflowEngine> engineList = wfService.queryWorkflowEngine(baseparam);
		if (engineList.isEmpty())
			throw new AdderBusinessException("没有待审核的任务", "pm.i18n_pbc.result.011");
		// 由于已排序，查询最小最大轮次
		int turn = engineList.get(0).getStepserial();
		if (flag == 1)
			turn = engineList.get(engineList.size() - 1).getStepserial();
		return turn;
	}

	/**
	 * 获得结果审核下一轮次
	 * 
	 * @param sheetid
	 *            量表
	 * @param turn
	 *            当前轮次
	 * @return
	 */
	private Integer getNextTurn(String sheetid, int turn) {
		Condition cond = new Condition();
		cond.addExpression("sheetid", sheetid);
		cond.addExpression("turn", turn, Operator.GREATER);
		Integer nextTurn = dao.queryNextTurn(cond);
		return nextTurn;
	}

	@Override
	public JSONArray doDistributeAuto(String id, Integer flag, Integer markFlag, String groupid) {
		// 执行自动强制分布
		Condition condObj = new Condition();
		condObj.addExpression("schemegroupid", id);
		List<ApproverGroup> appGroup = daoex.find(ApproverGroup.class, condObj, null);
		List<ApproveScore> appScoreList = null;
		Grade grade = null;
		String distid = null;
		if (appGroup.isEmpty()) {
			// id是方案id
			String schemeid = id;
			Scheme scheme = daoex.load(Scheme.class, schemeid);
			appScoreList = queryStaffByScheme(schemeid, flag, markFlag);
			distid = scheme.getDistid();
			if (groupid != null) {
				EvaGroup evaGroup = daoex.load(EvaGroup.class, groupid);
				/*appScoreList= (List<ApproveScore>) appScoreList
						.stream().filter(obj -> obj.getGroupid().equals(
						evaGroup.getId())).collect(Collectors.toList());
				*/
				appScoreList = ListHelper.filter(appScoreList, "getGroupid", ListHelper.Operator.EQUAL, evaGroup.getId());
				distid = evaGroup.getDistid();
			}
			grade = gradeService.queryGradeByID(scheme.getGradeid(), true);
		} else {
			// 多方案id
			appScoreList = queryStaffBySchemeGroup(id, flag, markFlag);
			ApproverGroup obj = appGroup.get(0);
			List<String> schemeids = new ArrayList<String>();
			for (ApproverGroup item : appGroup) {
				schemeids.add(item.getSchemeid());
			}
			List<Scheme> schemeList = daoex.findByIds(Scheme.class, schemeids.toArray(new String[schemeids.size()]));
			// 多方案中方案考核等级都一样
			String gradeid = schemeList.get(0).getGradeid();
			grade = gradeService.queryGradeByID(gradeid, true);

			distid = obj.getDistid();
		}
		// 获取强制分布
		Map<String, DistributionItem> distItemMap = new Hashtable<String, DistributionItem>();
		Distribution distObj = null;
		if (distid != null) {
			distObj = rsService.queryDistributionByCondition(distid);
			if (distObj != null) {
				// 处理尾数
				if (distObj.getDistcalc() == CommonValue.EnumDistCalc.way1.getIndex())
					rsService.doDistCalc(appScoreList.size(), distObj);
				else
					rsService.doDistCalc2(appScoreList.size(), distObj);
			/*distItemMap = distObj
					.getODistributionItem()
					.stream()
					.collect(
							Collectors.toMap(
									DistributionItem::getGradeitemid,
									Function.identity()));*/
				distItemMap = ListHelper.toMap(distObj.getODistributionItem(), "getGradeitemid");
			}
		}
		for (int i = 0; i < grade.getOGradeItem().size(); i++) {
			GradeItem item = grade.getOGradeItem().get(i);
			/*List<ApproveScore> appScoreGradeList = appScoreList
					.stream()
					.filter(obj -> obj.getGradeitemid()
							.equals(item.getId()))
					.collect(Collectors.toList());*/
			List<ApproveScore> appScoreGradeList = ListHelper.filter(appScoreList, "getGradeitemid", ListHelper.Operator.EQUAL, item.getId());
			Integer distnum = distItemMap.get(item.getId()).getDistnum();
			if (distnum > appScoreGradeList.size()) {
				// 该等级人不够，将下面其他等级和分数靠前的添加到该等级。
				int num = distnum - appScoreGradeList.size();
				List<ApproveScore> nextScoreGradeList = new ArrayList<ApproveScore>();
				for (int k = i + 1; k < grade.getOGradeItem().size(); k++) {
					GradeItem gradeItem2 = grade.getOGradeItem().get(k);
					/*List<ApproveScore> appScoreGradeList2 = appScoreList
							.stream()
							.filter(obj -> obj.getGradeitemid().equals(
									gradeItem2.getId()))
							.collect(Collectors.toList());*/
					List<ApproveScore> appScoreGradeList2 = ListHelper.filter(appScoreList, "getGradeitemid", ListHelper.Operator.EQUAL, gradeItem2.getId());
					if (appScoreGradeList2.size() >= num) {
						nextScoreGradeList.addAll(appScoreGradeList2.subList(0, num));
						break;
					} else {
						nextScoreGradeList.addAll(appScoreGradeList2);
						num -= appScoreGradeList2.size();
					}
				}
				for (ApproveScore score : nextScoreGradeList) {
					score.setGradeitemid(item.getId());
					score.setGradeitemname(item.getGradeitemname());
				}
			} else if (distnum < appScoreGradeList.size()) {
				// 该等级人多了，则按照分数排序，分数最低的放到下一级
				int next = i + 1;
				/*appScoreGradeList.stream().sorted(
						Comparator.comparing(ApproveScore::getScore).reversed());*/
				Collections.sort(appScoreGradeList, new Comparator<ApproveScore>(){
					@Override
					public int compare(ApproveScore o1, ApproveScore o2) {
						//return o1.getScore().compareTo(o2.getScore());
						return o2.getScore().compareTo(o1.getScore());
					}
				}); // .reversed()
				List<ApproveScore> sublist = appScoreGradeList
						.subList(distnum, appScoreGradeList.size());
				for(ApproveScore appscore :sublist){
					GradeItem item2 = grade.getOGradeItem().get(next);
					appscore.setGradeitemid(item2.getId());
					appscore.setGradeitemname(item2.getGradeitemname());
				}
			}
		}
		// 没有批量更新得方法
		for (ApproveScore score : appScoreList) {
			daoex.update(score);
		}
		return null;
	}

	/**
	 * 查询方案内结果审核人员数据，通过强分
	 * 
	 * @param scheme
	 * @param appScoreList
	 *            需要强分人员集合，不要求排序
	 * @return 返回符合前端的json格式数据
	 */
	private JSONObject queryApproveScoreByDist(Scheme scheme, List<ApproveScore> appScoreList) {
		String gradeid = scheme.getGradeid();
		JSONObject jsonReturn = new JSONObject();
		JSONObject jsonInfo = new JSONObject();
		JSONArray jsonArray = new JSONArray();
		Grade grade = gradeService.queryGradeByID(gradeid, true);
		// 判断是方案的强分还是组的
		boolean isGroup = false;
		List<Map<String, String>> data = new ArrayList<Map<String, String>>();
		Map<String, String> dataItem = new Hashtable<String, String>();
		if (appScoreList.get(0).getGroupid() == null) {
			dataItem.put("id", scheme.getId());
			dataItem.put("name", scheme.getSchemename());
			data.add(dataItem);
			// 方案
			jsonInfo.put("type", 2);
			jsonInfo.put("data", data);
			jsonArray = getDistributionPsn(grade, scheme.getDistid(), appScoreList);
			JSONObject json = new JSONObject();
			json.put(scheme.getId(), jsonArray);
			jsonReturn.put("detail", json);
		} else {
			isGroup = true;
			List<String> groupidList = new ArrayList<String>();
			JSONObject jsonGroup = new JSONObject();
			for (ApproveScore item : appScoreList) {
				if (!groupidList.contains(item.getGroupid()))
					groupidList.add(item.getGroupid());
			}
			// 根据不同组id，分组人员，并获取组distid
			List<EvaGroup> evaObjs = daoex.findByIds(EvaGroup.class,
					groupidList.toArray(new String[groupidList.size()]));
			for (EvaGroup item : evaObjs) {
				// 循环对象组，组装detail和info
				jsonArray = getDistributionPsn(
						grade,
						item.getDistid(),
						ListHelper.filter(appScoreList, "getGroupid", ListHelper.Operator.EQUAL, item.getId())
						/*appScoreList.stream().filter(obj -> obj.getGroupid().equals(item.getId()))
								.collect(Collectors.toList())*/);
				dataItem = new Hashtable<String, String>();
				dataItem.put("id", item.getId());
				dataItem.put("name", item.getGroupname());
				data.add(dataItem);
				jsonGroup.put(item.getId(), jsonArray);
			}
			// 组
			jsonInfo.put("type", 1);
			jsonInfo.put("data", data);
			jsonReturn.put("detail", jsonGroup);
		}
		jsonInfo.put("schememode", scheme.getSchememode());
		jsonInfo.put("isdoubleweight", scheme.isIsdoubleweight());
		jsonReturn.put("info", jsonInfo);
		// 获取强制分布
		return jsonReturn;
	}

	/**
	 * 查询多方案结果审核人员数据，通过强分
	 * 
	 * @param appGroup
	 * @param appScoreList
	 * @return 返回符合前端的json格式数据
	 */
	private JSONObject queryApproveScoreByDist(List<ApproverGroup> appGroup, List<ApproveScore> appScoreList) {
		ApproverGroup obj = appGroup.get(0);
		List<String> schemeids = new ArrayList<String>();
		for (ApproverGroup item : appGroup) {
			schemeids.add(item.getSchemeid());
		}
		List<Scheme> schemeList = daoex.findByIds(Scheme.class, schemeids.toArray(new String[schemeids.size()]));
		// 多方案中方案考核等级都一样
		String gradeid = schemeList.get(0).getGradeid();
		JSONObject jsonReturn = new JSONObject();
		JSONObject jsonInfo = new JSONObject();
		JSONArray jsonArray = new JSONArray();
		Grade grade = gradeService.queryGradeByID(gradeid, true);
		List<Map<String, String>> data = new ArrayList<Map<String, String>>();
		Map<String, String> dataItem = new Hashtable<String, String>();
		dataItem.put("id", obj.getSchemegroupid());
		dataItem.put("name", obj.getSchemegroupname());
		data.add(dataItem);
		jsonInfo.put("type", 3);
		jsonInfo.put("data", data);
		jsonArray = getDistributionPsn(grade, obj.getDistid(), appScoreList);
		JSONObject jsonDetail = new JSONObject();
		jsonDetail.put(obj.getSchemegroupid(), jsonArray);
		jsonReturn.put("detail", jsonDetail);
		jsonReturn.put("info", jsonInfo);
		data = new ArrayList<Map<String, String>>();
		for (Scheme item : schemeList) {
			dataItem = new Hashtable<String, String>();
			dataItem.put("id", item.getId());
			dataItem.put("name", item.getSchemename());
			dataItem.put("schememode", String.valueOf(item.getSchememode()));
			dataItem.put("isdoubleweight", String.valueOf(item.isIsdoubleweight()));
			data.add(dataItem);
		}
		jsonReturn.put("schemeinfo", data);
		// 获取强制分布
		return jsonReturn;
	}
	
	/**
	 * 检查一个方案是否符合强分
	 * 
	 * @param schemeid
	 * @return 是否强分通过
	 */
	private boolean checkDistributionByScheme(String schemeid) {
		JSONArray jsonArray = new JSONArray();
		jsonArray = queryGradeStaffByScheme(schemeid, 0, null).getJSONObject(
				"detail").getJSONArray(schemeid);
		for (int i = 0; i < jsonArray.size(); i++) {
			JSONObject job = jsonArray.getJSONObject(i);
			// 存在distdiff，说明强分不通过
			if (job.get("distdiff") != null)
				return false;
		}
		return true;
	}

	/**
	 * 检查一个多方案是否符合强分
	 * @param schemegroupid
	 * @return
	 */
	private boolean checkDistributionBySchemeGroup(String schemegroupid) {
		JSONArray jsonArray = new JSONArray();
		jsonArray = queryGradeStaffByScheme(schemegroupid, 0, null).getJSONObject(
				"detail").getJSONArray(schemegroupid);
		for (int i = 0; i < jsonArray.size(); i++) {
			JSONObject job = jsonArray.getJSONObject(i);
			// 存在distdiff，说明强分不通过
			if (job.get("distdiff") != null)
				return false;
		}
		return true;
	}
	
	/**
	 * 检查一个考核组是否符合强分
	 * 
	 * @param schemeid
	 * @param groupid
	 * @return
	 */
	private boolean checkDistributionByGroup(String schemeid, String groupid) {
		JSONArray jsonArray = new JSONArray();
		jsonArray = queryGradeStaffByScheme(schemeid, 0, null).getJSONObject(
				"detail").getJSONArray(groupid);
		for (int i = 0; i < jsonArray.size(); i++) {
			JSONObject job = jsonArray.getJSONObject(i);
			if (job.get("distdiff") != null)
				return false;
		}
		return true;
	}

	/**
	 * 批量将结果审核人数据添加等级子项id
	 * 
	 * @param grade
	 * @param appScoreList
	 */
	private void addGradeItemIdForApproveScore(Grade grade,
			List<ApproveScore> appScoreList) {
		/*Map<String, String> gradeItemMap = grade
				.getOGradeItem()
				.stream()
				.collect(
						Collectors.toMap(GradeItem::getGradeitemname,
								GradeItem::getId));*/
		Map<String, String> gradeItemMap = ListHelper.toMap(grade.getOGradeItem(), "getGradeitemname", "getId");
		for (ApproveScore item : appScoreList) {
			if (item.getGradeitemname() != null) {
				String strGradeItemID = gradeItemMap.get(item
						.getGradeitemname());
				item.setGradeitemid(strGradeItemID);
			}
		}
	}

	/**
	 * 根据审核人集合获得按强分等级归类的人员集合
	 * 
	 * @param grade
	 *            考核等级
	 * @param distid
	 *            强分id，可空
	 * @param appScoreList
	 *            需要强分人员集合，不要求排序
	 * @return
	 */
	private JSONArray getDistributionPsn(Grade grade, String distid, List<ApproveScore> appScoreList) {
		JSONArray jsonArray = new JSONArray();
		Map<String, DistributionItem> distItemMap = new Hashtable<String, DistributionItem>();
		int distway = 1;
		if (distid != null) {
			Distribution distObj = rsService.queryDistributionByCondition(distid);
			if (distObj != null) {
				distway = distObj.getDistway();
				// 处理尾数
				if (distObj.getDistcalc() == CommonValue.EnumDistCalc.way1.getIndex())
					rsService.doDistCalc(appScoreList.size(), distObj);
				else
					rsService.doDistCalc2(appScoreList.size(), distObj);
			/*distItemMap = distObj.getODistributionItem().stream()
					.collect(Collectors.toMap(DistributionItem::getGradeitemid, Function.identity()));*/
				distItemMap = ListHelper.toMap(distObj.getODistributionItem(), "getGradeitemid");
				// 如果是按人数强分，需要计算出人数百分比， 用于展示。
				if(distObj.getDisttype() == EnumDistType.way2.getIndex() && distObj.getDistsum() != 0){
					int distotalsum = distObj.getDistsum();
					BigDecimal decimal = new BigDecimal(distotalsum+"");
					List<DistributionItem> disitems = distObj.getODistributionItem();
					for(int i = 0 ; i < disitems.size(); i ++){
						Integer itemdistnum = disitems.get(i).getDistnum();
						if(itemdistnum.equals(0))
							continue;
						if(distotalsum > itemdistnum){
							BigDecimal divide = new BigDecimal(itemdistnum+"").divide(decimal, 2,
									BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100+""));
							disitems.get(i).setDistscale(divide.intValue());
						} else {
							BigDecimal divide = new BigDecimal(itemdistnum+"").divide(decimal, 2,
									BigDecimal.ROUND_HALF_DOWN).multiply(new BigDecimal(100+""));
							disitems.get(i).setDistscale(divide.intValue());
						}
						distotalsum -= itemdistnum;
					}
				}
			}
		}
		//获取最大轮次 用于显示。 获取所在组 或所在方案实际最大轮次和实际当前轮次
		HashMap<String,Integer> actualturn = new HashMap();
		int maxTurnConut = getMaxTrunCountByApproveScore(appScoreList.get(0), actualturn);
		int appScoreTotal = appScoreList.size();
		// 循环每一个等级，把分组人员分类
		for (GradeItem item : grade.getOGradeItem()) {
			JSONObject json = new JSONObject();
			json.put("gradeitemid", item.getId());
			json.put("gradeitemname", item.getGradeitemname());
			json.put("maxturnconut", maxTurnConut);
			json.put("actualturn", actualturn.get("actualturn")); //实际轮次
			json.put("distway", distway);
			json.put("distid", distid);
			List<ApproveScore> appScoreGradeList = new ArrayList<ApproveScore>();/*appScoreList.stream()
					.filter(obj -> obj.getGradeitemid() != null && obj.getGradeitemid().equals(item.getId()))
					.collect(Collectors.toList());*/
			for(ApproveScore obj : appScoreList){
				if(obj.getGradeitemid() != null && obj.getGradeitemid().equals(item.getId())){
					appScoreGradeList.add(obj);
				}
			}
			json.put("isShow",appScoreGradeList.size() == 0 ?  0 :appScoreGradeList.get(0).getIsShow());
			json.put("data", appScoreGradeList);
			json.put("distsum", appScoreGradeList.size());
			// 强制分布人数
			if (distItemMap.containsKey(item.getId())) {
				DistributionItem distItem = distItemMap.get(item.getId());
				json.put("distscale", distItem.getDistscale()+"%"); // 强制百分比	
				if(appScoreTotal > appScoreGradeList.size()){
					BigDecimal divide = new BigDecimal(appScoreGradeList.size()+"").divide(new BigDecimal(appScoreList.size()+""), 2,
			                 BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal(100+""));
					json.put("actualscale", divide.intValue()+"%"); // 实际百分比
					appScoreTotal -= appScoreGradeList.size();
				} else {
					BigDecimal divide = new BigDecimal(appScoreGradeList.size()+"").divide(new BigDecimal(appScoreList.size()+""), 2,
			                 BigDecimal.ROUND_HALF_DOWN).multiply(new BigDecimal(100+""));
					json.put("actualscale", divide.intValue()+"%"); // 实际百分比
					appScoreTotal -= appScoreGradeList.size();
				}
				
				json.put("distnum", distItem.getDistnum()); // 强制人数
				json.put("actualnum", appScoreGradeList.size()); // 实际强制人数
				int distdiff = appScoreGradeList.size() - distItem.getDistnum();
				json.put("diffnum", distdiff);
				if (distdiff > 0)
					json.put("distdiff", "多" + distdiff + "人");
				else if (distdiff < 0)
					json.put("distdiff", "少" + Math.abs(distdiff) + "人");
			}
			jsonArray.add(json);
		}
		return jsonArray;
	}

	/**
	 * 获取最大审核轮次
	 * @param approveScore
	 * @return
	 */
	private int getMaxTrunCountByApproveScore(ApproveScore approveScore, HashMap<String,Integer> actualturn) {
		String userId = AppContext.getContext().getUserId();
		String staffid = StaffHelper.getStaffByUserId(userId);
		actualturn.put("actualturn", approveScore.getTurn());
		int maxTurnConut = 1;
		if(approveScore.getAudittype() == CommonValue.EnumAuditType.type1.getIndex()){ // 考核组
			Condition maxCountCndt = new Condition();
			maxCountCndt.addExpression("groupid", approveScore.getGroupid());
			maxCountCndt.addExpression("workstep", EnumWorkStep.step3.getIndex());
			List<EvaAppraiser> find = daoex.find(EvaAppraiser.class, maxCountCndt, new Sorter(Direction.ASC, Arrays.asList("turn")));
			maxTurnConut = find.size();
			actualturn.put("actualturn", approveScore.getTurn());
		} else if(approveScore.getAudittype() == CommonValue.EnumAuditType.type2.getIndex()){ // 方案
			Condition maxCountCndt = new Condition();
			maxCountCndt.addExpression("schemeid", approveScore.getSchemeid());
			maxCountCndt.addExpression("groupid", null, Operator.ISNULL);
			maxCountCndt.addExpression("schemegroupid", null, Operator.ISNULL);
			maxCountCndt.addExpression("workstep", EnumWorkStep.step3.getIndex());
			List<EvaAppraiser> find = daoex.find(EvaAppraiser.class, maxCountCndt, new Sorter(Direction.ASC, Arrays.asList("turn")));
			maxTurnConut = find.size();
			for(int i = 0 ; i< find.size() ; i++){  // 不能使用approveScore里的当前轮次(是考核组和方案总得轮次),  只取方案上得轮次
				EvaAppraiser evaAppraiser = find.get(i);
				if(staffid.endsWith(evaAppraiser.getStaffid())){
					actualturn.put("actualturn", (i+1));
					break;
				}
			}
		} else { // 多方案 TODO
			Condition maxCountCndt = new Condition();
			maxCountCndt.addExpression("schemegroupid", approveScore.getGroupid());
			maxCountCndt.addExpression("workstep", EnumWorkStep.step3.getIndex());
			List<EvaAppraiser> find = daoex.find(EvaAppraiser.class, maxCountCndt, new Sorter(Direction.ASC, Arrays.asList("turn")));
			for(int i = 0 ; i< find.size() ; i++){  // 不能使用approveScore里的当前轮次(是考核组和方案总得轮次),  只取方案上得轮次
				EvaAppraiser evaAppraiser = find.get(i);
				if(staffid.endsWith(evaAppraiser.getStaffid())){
					actualturn.put("actualturn", (i+1));
					break;
				}
			}
			maxTurnConut = find.size();
		}
		return maxTurnConut;
	}

	/**
	 * 查看审核历史
	 * @param id 是ApproveScore 的id。
	 * @return
	 */
	@Override
	public HashMap<String,Object> queryAuditHistory(String id){
		ApproveScore approveScore = daoex.load(ApproveScore.class,id);
		List<ApproveScore> apprScoreList = new ArrayList();
		if(approveScore.getAudittype() == CommonValue.EnumAuditType.type1.getIndex()){
			Condition maxCountCndt = new Condition();
			maxCountCndt.addExpression("groupid", approveScore.getGroupid());
			maxCountCndt.addExpression("audittype", approveScore.getAudittype());
			maxCountCndt.addExpression("sheetid", approveScore.getSheetid());
			apprScoreList = daoex.find(ApproveScore.class, maxCountCndt, new Sorter(Direction.ASC, Arrays.asList("turn")));
			
		} else if(approveScore.getAudittype() == CommonValue.EnumAuditType.type2.getIndex()){ // 方案
			Condition maxCountCndt = new Condition();
			maxCountCndt.addExpression("schemeid", approveScore.getSchemeid());
			maxCountCndt.addExpression("audittype", approveScore.getAudittype());
			maxCountCndt.addExpression("sheetid", approveScore.getSheetid());
			apprScoreList = daoex.find(ApproveScore.class, maxCountCndt, new Sorter(Direction.ASC, Arrays.asList("turn")));
			
		} else { // 多方案
			Condition maxCountCndt = new Condition();
			maxCountCndt.addExpression("schemegroupid", approveScore.getGroupid());
			maxCountCndt.addExpression("audittype", approveScore.getAudittype());
			maxCountCndt.addExpression("sheetid", approveScore.getSheetid());
			apprScoreList = daoex.find(ApproveScore.class, maxCountCndt, new Sorter(Direction.ASC, Arrays.asList("turn")));
		}
		List<String> staffidList = apprScoreList.stream().map(ApproveScore::getAuditor).collect(Collectors.toList());
		Map<String, PmStaff> staffList = StaffHelper.queryStaffByIds(staffidList);
		StaffHelper.simplifyStaff(staffList);
		for (int i = 0 ; i < apprScoreList.size() ; i++) {
			ApproveScore item = apprScoreList.get(i);
			item.setStaff(staffList.get(item.getAuditor()));
			item.setStatusname(CommonValue.EnumMarkState30.values()[item
					.getMarkStatus() - 1].getDescription());
			item.setTurn(i+1);
		}
		
        HashMap<String,Object> restMp = new HashMap<String,Object>();
		restMp.put("hstryApprList", apprScoreList);
		Score scoreScr = getLastApproveScore(approveScore.getSheetid());
		restMp.put("scoreScr", scoreScr);
		return restMp;
	}
	/**
	 * 获取最终评分得分
	 * @param sheetid
	 * @return
	 */
	@Override
	public Score getLastApproveScore(String sheetid){
		Condition scoreCondition = new Condition();
        scoreCondition.addExpression("sheetid",sheetid);
        scoreCondition.addExpression("columncode",CommonValue.EnumSchemeScoreColumnCode.CODE002.getCode());
        List<Score> scoreList = daoex.find(Score.class, scoreCondition, null);
        Score scoreScr = scoreList.get(0);
        Condition gradeCondition = new Condition();
        gradeCondition.addExpression("sheetid",sheetid);
        gradeCondition.addExpression("columncode",CommonValue.EnumSchemeScoreColumnCode.CODE004.getCode());
        Score score2 = daoex.find(Score.class, gradeCondition, null).get(0);
        scoreScr.setText(score2.getText());
        return scoreScr;
	}
	/**
	 * 获取指标明细
	 * @param id
	 * @return
	 */
	public Map<String, Object> getIndiDetail(String id){
		SheetIndicator sheetIndi = daoex.load(SheetIndicator.class, id);
		Indicator indicator = daoex.load(Indicator.class, sheetIndi.getIndicatorid());
		HashMap<String,Object> hashMap = new HashMap<String,Object>();
		String orgid = indicator.getOrgid();
		if(StringUtils.isEmpty(orgid)){
			hashMap.put("orgname", "");
		} else {
			String queryDeptName = OrgHelper.queryDeptName(orgid);
			hashMap.put("orgname", queryDeptName);
		}
		return hashMap;
		
	}
	
	/**
	 * 根据流程获取量表id集合，并获取审核人数据
	 * 
	 * @param staffid
	 *            当前人员
	 * @param flag
	 *            页签分类
	 * @param markFlag
	 *            结果审核状态
	 * @param wfList
	 *            代办工作流
	 * @param appScoreList
	 *            返回的审核人数据
	 * @return 待处理的量表id
	 */
	private List<String> getApproveScoreByWF(String staffid, int flag, Integer markFlag, List<WorkflowEngine> wfList,
			List<ApproveScore> appScoreList) {
		List<String> sheetids = new ArrayList<String>();
		// flag是未处理轮次从前到后，已处理是从后到前，wfList已经是按轮次排序过
		int turn = 0;
		for (WorkflowEngine wf : wfList) {
			if (flag == 0) {
				if (turn == 0)
					turn = wf.getStepserial();
			} else
				turn = wf.getStepserial();
		}
		// 多个考核组同一人审，一个组审过了，状态为已审核要排除掉，查询出另外一个组
		for (WorkflowEngine wf : wfList) {
			if (wf.getStepserial() == turn && !sheetids.contains(wf.getBizid()))
				sheetids.add(wf.getBizid());
		}
		// 根据量表获取结果审核人数据
		Condition condObj = new Condition();
		condObj.addExpression("sheetid", sheetids, Operator.IN);
		condObj.addExpression("auditor", staffid);
		condObj.addExpression("turn", turn);
		if (markFlag != null) {
			if (markFlag == 2)
				condObj.addExpression("mark_status", CommonValue.EnumMarkState30.State3.getIndex());
			else
				condObj.addExpression("mark_status", Arrays.asList(CommonValue.EnumMarkState30.State1.getIndex(),
						CommonValue.EnumMarkState30.State2.getIndex(), CommonValue.EnumMarkState30.State4.getIndex()),
						Operator.IN);
		}
		// 考核组和方案都有同一人时排序
		Sorter sortObj = new Sorter(Direction.ASC, Arrays.asList("gradeitemname"));
		appScoreList.addAll(daoex.find(ApproveScore.class, condObj, sortObj));
		return sheetids;
	}

	/**
	 * 根据工作流查询结果审核待处理方案列表
	 * 
	 * @param wfList
	 * @param flag
	 *            0未处理1已处理
	 * @return
	 */
	private List<Object> getMultiSchemeList(List<WorkflowEngine> wfList, Integer flag) {
		List<Object> retList = new ArrayList<Object>();
		if (wfList.isEmpty())
			return retList;
		List<String> schemeids = new ArrayList<String>();
		Condition condObj = new Condition();
		// 考核组的流程，按方案分组
		/*Map<String, List<WorkflowEngine>> wfGroupMap = wfList.stream()
				.filter(obj -> obj.getDefine2() != null
						&& obj.getDefine2().equals(String.valueOf(CommonValue.EnumAuditType.type1.getIndex())))
				.collect(Collectors.groupingBy(WorkflowEngine::getBizinfo));*/
		// 方案级
		/*Map<String, List<WorkflowEngine>> wfSchemeMap = wfList.stream()
				.filter(obj -> obj.getDefine2() != null
						&& obj.getDefine2().equals(String.valueOf(CommonValue.EnumAuditType.type2.getIndex())))
				.collect(Collectors.groupingBy(WorkflowEngine::getBizinfo));*/
		// 多方案
		/*Map<String, List<WorkflowEngine>> wfMultiMap = wfList.stream()
				.filter(obj -> obj.getDefine2() != null
						&& obj.getDefine2().equals(String.valueOf(CommonValue.EnumAuditType.type3.getIndex())))
				.collect(Collectors.groupingBy(WorkflowEngine::getBizinfo));*/
		// 考核组级
		Map<String, List<WorkflowEngine>> wfGroupMap = new HashMap<String, List<WorkflowEngine>>();
		// 方案级
		Map<String, List<WorkflowEngine>> wfSchemeMap = new HashMap<String, List<WorkflowEngine>>();
		// 多方案
		Map<String, List<WorkflowEngine>> wfMultiMap = new HashMap<String, List<WorkflowEngine>>();
		for(WorkflowEngine obj : wfList){
			if(obj.getDefine2() != null){ 
				// 考核组
				if(obj.getDefine2().equals(String.valueOf(CommonValue.EnumAuditType.type1.getIndex()))){
					List<WorkflowEngine> list = wfGroupMap.get(obj.getBizinfo());
					if(list == null){
						list = new ArrayList<WorkflowEngine>();
						wfGroupMap.put(obj.getBizinfo(), list);
					}
					list.add(obj);
				}
				// 方案级
				if(obj.getDefine2().equals(String.valueOf(CommonValue.EnumAuditType.type2.getIndex()))){
					List<WorkflowEngine> list = wfSchemeMap.get(obj.getBizinfo());
					if(list == null){
						list = new ArrayList<WorkflowEngine>();
						wfSchemeMap.put(obj.getBizinfo(), list);
					}
					list.add(obj);
				}
				// 多方案
				if(obj.getDefine2().equals(String.valueOf(CommonValue.EnumAuditType.type3.getIndex()))){
					List<WorkflowEngine> list = wfMultiMap.get(obj.getBizinfo());
					if(list == null){
						list = new ArrayList<WorkflowEngine>();
						wfMultiMap.put(obj.getBizinfo(), list);
					}
					list.add(obj);
				}
			}
		}
		
		List<String> multiSchemeids = new ArrayList<String>();
		if (!wfMultiMap.isEmpty())
			multiSchemeids.addAll(wfMultiMap.keySet());
		// validMultiSchemeMap记录方案组和人数
		Map<String, Map<String, Object>> validMultiSchemeMap = new Hashtable<String, Map<String, Object>>();
		// 得到待处理的方案id集合
		for (WorkflowEngine wf : wfList) {
			String schemeid = wf.getBizinfo();
			if (!schemeids.contains(schemeid))
				schemeids.add(schemeid);
		}
		if (schemeids.size() > 0) {
			// 待处理的方案状态不一定是结果审核中的
			condObj.addExpression("id", schemeids, Operator.IN);
			// edit by nijb 2020-12-17 查询中包含历史结果审核
			condObj.addExpression("schemestate", CommonValue.EnumSchemeState.State7.ordinal(), Operator.GREATEREQUAL);
			Sorter sortObj = new Sorter(Direction.DESC, "fdate");
			List<Scheme> schemeList = daoex.find(Scheme.class, condObj, sortObj);
			schemeids.clear();
			for (Scheme item : schemeList) {
				if (!schemeids.contains(item.getId()))
					schemeids.add(item.getId());
			}
			for (String item : multiSchemeids) {
				// 查询的方案组中方案没有出现在schemeList中要去除
				if (!schemeids.contains(item))
					multiSchemeids.remove(item);
			}
			// 重点：循环查询出的符合条件方案，再根据审核类型处理显示内容
			List<Map<String, List<WorkflowEngine>>> list = new ArrayList<>();
			if (flag == 0) {
				list.add(wfGroupMap);
				list.add(wfSchemeMap);
				list.add(wfMultiMap);
			} else {
				list.add(wfMultiMap);
				list.add(wfSchemeMap);
				list.add(wfGroupMap);
			}
			for (Scheme item : schemeList) {
				Period p = periodSrv.queryPeriodByID(item.getPeriodid());
				item.setPeriodname(p.getPeriodname());
				Map<String, Object> data = new Hashtable<String, Object>();
				if (list.get(0).containsKey(item.getId())) {
					List<WorkflowEngine> wfListTmp = list.get(0).get(item.getId());
					if (flag == 0)
						dowfGroupMap(wfListTmp, data);
					else
						dowfMultiMap(wfListTmp, validMultiSchemeMap, multiSchemeids, data);
				} else if (list.get(1).containsKey(item.getId())) {
					List<WorkflowEngine> wfListTmp = list.get(1).get(item.getId());
					data.put("sum", wfListTmp.size());
					data.put("audittype", CommonValue.EnumAuditType.type2.getIndex());
				} else if (list.get(2).containsKey(item.getId())) {
					List<WorkflowEngine> wfListTmp = list.get(2).get(item.getId());
					if (flag == 0)
						dowfMultiMap(wfListTmp, validMultiSchemeMap, multiSchemeids, data);
					else
						dowfGroupMap(wfListTmp, data);
				} else {
					// 旧的方案数据
					data.put("sum", 0);
					data.put("audittype", CommonValue.EnumAuditType.type2.getIndex());
				}
				if (!wfMultiMap.containsKey(item.getId())) {
					data.put("id", item.getId());
					data.put("name", item.getSchemename());
				}
				// edit by nijb 2020-12-17 增加了orgid isend periodcode等字段，用于考核结果审核参照（显示）
				data.put("orgid", item.getOrgid());
				data.put("isend", item.isIsend());
				data.put("periodname", item.getPeriodname());
				data.put("schemestate", item.getSchemestate());
				data.put("periodid", p.getId());
				data.put("periodcode", p.getPeriodcode());
				data.put("schememode", item.getSchememode());
				data.put("isdoubleweight", item.isIsdoubleweight());
				data.put("applyobj", item.getApplyobj());
				retList.add(data);
			}
		}
		return retList;
	}

	private void dowfGroupMap(List<WorkflowEngine> wfListTmp, Map<String, Object> data) {
		String groupName = "";
		List<String> groupidList = new ArrayList<String>();
		for (WorkflowEngine item2 : wfListTmp) {
			if (!groupidList.contains(item2.getDefine3())) {
				// 获取多个组的名称
				groupName += groupService.queryEvaGroupByID(item2.getDefine3(), false).getGroupname() + "　";
				groupidList.add(item2.getDefine3());
			}
		}
		data.put("groupname", groupName);
		data.put("groupidList", groupidList);
		data.put("sum", wfListTmp.size());
		data.put("audittype", CommonValue.EnumAuditType.type1.getIndex());
	}

	private void dowfMultiMap(List<WorkflowEngine> wfListTmp, Map<String, Map<String, Object>> validMultiSchemeMap,
			List<String> multiSchemeids, Map<String, Object> data) {
		String schemegroupid = wfListTmp.get(0).getDefine3();
		if (validMultiSchemeMap.containsKey(schemegroupid)) {
			// 方案组相同的方案合计人数
			int sum = Integer.parseInt(validMultiSchemeMap.get(schemegroupid).get("sum").toString());
			validMultiSchemeMap.get(schemegroupid).put("sum", sum + wfListTmp.size());
		} else {
			Condition condObj = new Condition();
			condObj.addExpression("schemegroupid", schemegroupid);
			List<ApproverGroup> appGroup = daoex.find(ApproverGroup.class, condObj, null);
			// 判断方案组下方案是否都在有效的multiSchemeids里
			for (ApproverGroup item2 : appGroup) {
				if (!multiSchemeids.contains(item2.getSchemeid()))
					continue;
			}
			data.put("id", schemegroupid);
			data.put("name", appGroup.get(0).getSchemegroupname());
			data.put("sum", wfListTmp.size());
			validMultiSchemeMap.put(schemegroupid, data);
		}
		data.put("audittype", CommonValue.EnumAuditType.type3.getIndex());
	}
	
	/**
	 * 带考核对象详细信息的结果审核人数据集合
	 * 
	 * @param schemeids
	 * @param flag
	 * @param markFlag
	 * @return
	 */
	private List<ApproveScore> getAppScoreWithStaff(List<String> schemeids, Integer flag, Integer markFlag) {
		String userid = AppContext.getContext().getUserId();
		String staffid = StaffHelper.getStaffByUserId(userid);
		BaseParam param = new BaseParam();
		param.setBiztype(EnumWorkflowType.performance);
		param.setWorkstep(EnumWorkStep.step3);
		param.setCurrentOperator(staffid);
		param.setBizinfo(schemeids);
		// 评价那评价人没有重复，结果审核可以重复，所以要加待处理状态
		if (flag == null || flag == 0) {
			flag = 0;
			param.setWorkflowState(CommonValue.EnumWorkflowState.PENDING);
		}
		else
			param.setWorkflowState(CommonValue.EnumWorkflowState.PASS_AUDIT);
		List<WorkflowEngine> wfList = wfService.queryWorkflowEngine(param);
		if (wfList.size() == 0)
			return new ArrayList<ApproveScore>();
		// 如果是已审核，则只显示轮次最大的审核人数据
		if (flag == 1) {
			int maxTurn = 1;
			for (WorkflowEngine item : wfList) {
				if (item.getStepserial() > maxTurn)
					maxTurn = item.getStepserial();
			}
			for (int i = wfList.size() - 1; i >= 0; i--) {
				if (wfList.get(i).getStepserial() != maxTurn)
					wfList.remove(i);
			}
		}
		// 根据流程获取量表id集合
		List<ApproveScore> appScoreList = new ArrayList<ApproveScore>();
		List<String> sheetids = getApproveScoreByWF(staffid, flag, markFlag, wfList, appScoreList);
		// 根据量表获取考核对象
		Condition condObj = new Condition();
		condObj.addExpression("id", sheetids, Operator.IN);
		List<Sheet> sheetList = daoex.find(Sheet.class, condObj, null);
		Map<String, String> sheetMap = new Hashtable<String, String>();
		for (Sheet item : sheetList) {
			sheetMap.put(item.getId(), item.getStaffid());
		}

		// 设置结果审核人的考核对象详细信息
		setApproveScoreInfo(sheetids, sheetMap, appScoreList);
		return appScoreList;
	}
	
	/**
	 * 判断方案组的强分规则是否是不严格控制
	 * 
	 * @param groupid
	 * @return
	 */
	private boolean isDistributeWay2(String groupid, int audittype) {
		String distid = null;
		if(audittype == 1){
			EvaGroup group = daoex.load(EvaGroup.class, groupid);
			if (group == null){
				return false;
			}
			distid = group.getDistid();
		}else{
			//20210428多方案
			Condition condObj = new Condition();
			condObj.addExpression("schemegroupid", groupid);
			List<ApproverGroup> appGroup = daoex.find(ApproverGroup.class, condObj, null);
			if (appGroup == null || appGroup.isEmpty()) {
				return false;
			}
			distid = appGroup.get(0).getDistid();
		}
		if (distid == null) {
			return false;
		}
		Distribution distObj = rsService.queryDistributionByCondition(distid);
		if (distid != null && distObj.getDistway() == CommonValue.EnumDistWay.way2.getIndex())
			return true;
		else
			return false;
	}

	/**
	 * 查询具体考核组下的考核人信息
	 * @param schemeid
	 * @param evagroupid
	 * @param flag
	 * @param markFlag
	 * @return
	 */
	private List<ApproveScore> queryStaffScoreByGroup(String schemeid, String evagroupid, Integer flag, Integer markFlag){
		String userid = AppContext.getContext().getUserId();
		String staffid = StaffHelper.getStaffByUserId(userid);
		BaseParam param = new BaseParam();
		param.setBiztype(EnumWorkflowType.performance);
		param.setWorkstep(EnumWorkStep.step3);
		param.setCurrentOperator(staffid);
		param.setBizinfo(Arrays.asList(schemeid));
		// 评价那评价人没有重复，结果审核可以重复，所以要加待处理状态
		if (flag == null || flag == 0) {
			flag = 0;
			param.setWorkflowState(CommonValue.EnumWorkflowState.PENDING);
		} else
			param.setWorkflowState(CommonValue.EnumWorkflowState.PASS_AUDIT);
		List<WorkflowEngine> wfList = wfService.queryWorkflowEngine(param);
		if (wfList.size() == 0)
			return new ArrayList<ApproveScore>();
		// 根据考核组id 过滤。
		wfList = wfList.stream().filter(workengine -> evagroupid.equals(workengine.getDefine3())).collect(Collectors.toList());
		// 根据流程获取量表id集合
		List<ApproveScore> appScoreList = new ArrayList<ApproveScore>();
		List<String> sheetids = getApproveScoreByWF(staffid, flag, markFlag, wfList, appScoreList);
		// 根据量表获取考核对象
		Condition condObj = new Condition();
		condObj.addExpression("id", sheetids, Operator.IN);
		List<Sheet> sheetList = daoex.find(Sheet.class, condObj, null);
		Map<String, String> sheetMap = new Hashtable<String, String>();
		for (Sheet item : sheetList) {
			sheetMap.put(item.getId(), item.getStaffid());
		}
		// 设置结果审核人的考核对象详细信息
		setApproveScoreInfo(sheetids, sheetMap, appScoreList);
		sortApproveScore(schemeid, appScoreList);
		return appScoreList;
	}
	/**
	 * web端结果审核--强制分布情况查询及统计分析查询
	 * id 可能是考核组id，可能是方案id，也可能是结果审核组id
	 */
	@Override
	public List<Object> queryForceDistSituation(String id, Integer flag, Integer markFlag) {
		//考核组
		EvaGroup evaGroup = daoex.load(EvaGroup.class, id);
		if(evaGroup != null){
			//List<ApproveScore> appScoreList = queryStaffByScheme(evaGroup.getSchemeid(), flag, markFlag);
			List<ApproveScore> appScoreList = queryStaffScoreByGroup(evaGroup.getSchemeid(), evaGroup.getId(), flag, markFlag);
			if (appScoreList.isEmpty())
				throw new AdderBusinessException("未查询到结果审核数据","pm.i18n_pbc.result.002");
			Scheme scheme = daoex.load(Scheme.class, evaGroup.getSchemeid());
			Grade grade = gradeService.queryGradeByID(scheme.getGradeid(), true);
			
			for(ApproveScore score : appScoreList) {
				if(scheme.isIsaccount()) {
					score.setIsShow(1);
				}
			}
			
			JSONArray distributionPsn = getDistributionPsn(grade,evaGroup.getDistid(),
					appScoreList.stream().filter(obj -> obj.getGroupid().equals(evaGroup.getId()))
							.collect(Collectors.toList()));
			return distributionPsn;
		}
		// 考核方案
		Scheme scheme = daoex.load(Scheme.class, id);
		if(scheme != null){
			List<ApproveScore> appScoreList = queryStaffByScheme(scheme.getId(), flag, markFlag);
			/*for(int i = 0 ; i <appScoreList.size()  ; i++){
				appScoreList.get(i).setTurn(i+1);
			}*/
			if (appScoreList.isEmpty())
				throw new AdderBusinessException("未查询到结果审核数据","pm.i18n_pbc.result.002");
			
			for(ApproveScore score : appScoreList) {
				if(scheme.isIsaccount()) {
					score.setIsShow(1);
				}
			}
			
			Grade grade = gradeService.queryGradeByID(scheme.getGradeid(), true);
			JSONArray distributionPsn = getDistributionPsn(grade, scheme.getDistid(), appScoreList);
			return distributionPsn;
		}
		// 多方案
		Condition condObj = new Condition();
		condObj.addExpression("schemegroupid", id);
		List<ApproverGroup> appGroup = daoex.find(ApproverGroup.class, condObj, null);
		if (!appGroup.isEmpty()) {
			// 多方案id，查询多方案下人员
			List<ApproveScore> appScoreList = queryStaffBySchemeGroup(id, flag, markFlag);
			/*for(int i = 0 ; i <appScoreList.size()  ; i++){
				appScoreList.get(i).setTurn(i+1);
			}*/
			if (appScoreList.isEmpty())
				throw new AdderBusinessException("未查询到结果审核数据","pm.i18n_pbc.result.002");
			Scheme firstscheme = daoex.load(Scheme.class, appGroup.get(0).getSchemeid());
			Grade grade = gradeService.queryGradeByID(firstscheme.getGradeid(), true);
			JSONArray jsonArray = getDistributionPsn(grade, appGroup.get(0).getDistid(), appScoreList);
			return jsonArray;
		} 
		return null;
	}

	/**
	 * 对 我的待处理方案 进行再处理
	 * @param objs
	 * @param flag
	 */
	@Override
	public List<Map> packingMyAuditResult(List<Object> objs, Integer flag) {
		// flag 控制未审核和已审核展现形式不一样，处理逻辑是一样的。
		List<Map> packa = new ArrayList<Map>();
		for(int i = 0 ; i < objs.size() ; i++){
			Map<String,Object> audit = (Map)objs.get(i);
			CommonValue.EnumSchemeMode enumschememode = CommonValue.EnumSchemeMode.valueOf(Integer.parseInt(audit.get("schememode").toString()));
			if(enumschememode != null)
				audit.put("schememodename", enumschememode.getDescription());
			Integer audittype = (Integer)audit.get("audittype");
			if(!audittype.equals(EnumAuditType.type1.getIndex())){
				Scheme scheme = daoex.load(Scheme.class, (String)audit.get("id"));
				if(scheme != null && scheme.getDistid() != null){
					Distribution distObj = rsService.queryDistributionByCondition(scheme.getDistid());
					if (distObj == null) {
						audit.put("distway", 1); // 1=无强制分布，2=强制分布-不严格控制，3=强制分布-严格控制
					} else {
						audit.put("distid", scheme.getDistid());
						audit.put("disttype", distObj.getDisttype()); // 1按比例分布，2按人数分布
						audit.put("distsum", distObj.getDistsum()); // 汇总人数
						audit.put("gradeid", distObj.getGradeid()); // 考核等级id
						audit.put("distcalc", distObj.getDistcalc()); // 尾数处理方式 1=向下取整-正态分布，2=四舍五入-正向分布
						audit.put("distway", distObj.getDistway()); // 1=无强制分布，2=强制分布-不严格控制，3=强制分布-严格控制
					}
				} else {
					audit.put("distway", 1); // 1=无强制分布，2=强制分布-不严格控制，3=强制分布-严格控制
				}
				packa.add(audit);
				continue;
			}
			Condition condObj = new Condition();
			condObj.addExpression("schemeid", audit.get("id").toString());
			List<EvaGroup> find = daoex.find(EvaGroup.class, condObj, null);
			List<String> groupidList = (List<String>)audit.get("groupidList");
			List<Map> evaGroupList = new ArrayList<Map>();
			for(EvaGroup group : find){
				if(!groupidList.contains(group.getId())){
					continue;
				}
				Map<String,Object> newobj = new HashMap<String,Object>();
				newobj.put("audittype", audit.get("audittype"));
				newobj.put("id", audit.get("id"));
				newobj.put("groupname", group.getGroupname()); // 考核组名称
				newobj.put("groupid", group.getId());
				newobj.put("isdoubleweight", audit.get("isdoubleweight"));
				newobj.put("name", audit.get("name")); // 方案名称
				newobj.put("periodname", audit.get("periodname")); // 期间名称
				newobj.put("schememode", audit.get("schememode"));
				newobj.put("applyobj", audit.get("applyobj"));
				// edit by nijb 2020-12-17 增加了orgid isend periodcode等字段，用于考核结果审核参照（显示）
				newobj.put("isend", audit.get("isend"));
				newobj.put("orgid", audit.get("orgid"));
				newobj.put("periodcode", audit.get("periodcode"));
				newobj.put("schemestate", audit.get("schemestate"));
				CommonValue.EnumSchemeMode schememode = CommonValue.EnumSchemeMode.valueOf(Integer.parseInt(audit.get("schememode").toString()));
				if(schememode != null)
					newobj.put("schememodename", schememode.getDescription());
				newobj.put("sum", audit.get("sum")); //人数
				if(group.getDistid() != null){
					Distribution distObj = rsService.queryDistributionByCondition(group.getDistid());
					if (distObj == null) {
						newobj.put("distway", 1); // 1=无强制分布，2=强制分布-不严格控制，3=强制分布-严格控制
					} else {
						newobj.put("distid", group.getDistid());
						newobj.put("disttype", distObj.getDisttype()); // 1按比例分布，2按人数分布
						newobj.put("distsum", distObj.getDistsum()); // 汇总人数
						newobj.put("gradeid", distObj.getGradeid()); // 考核等级id
						newobj.put("distcalc", distObj.getDistcalc()); // 尾数处理方式 1=向下取整-正态分布，2=四舍五入-正向分布
						newobj.put("distway", distObj.getDistway()); // 1=无强制分布，2=强制分布-不严格控制，3=强制分布-严格控制
					}
				} else{
					newobj.put("distway", 1); // 1=无强制分布，2=强制分布-不严格控制，3=强制分布-严格控制
				}
				evaGroupList.add(newobj);
			} 
			if(flag == 0){
				packa.addAll(evaGroupList);
			} else {
				audit.put("evaGroupList", evaGroupList);
				packa.add(audit);
			}
		}
		return packa;
	}
}
