package cn.fw.morax.service.biz.kpi; import cn.fw.morax.common.constant.Constant; import cn.fw.morax.common.utils.DateUtil; import cn.fw.morax.common.utils.PublicUtil; import cn.fw.morax.domain.db.kpi.*; import cn.fw.morax.domain.dto.kpi.KpiGroupIndicatorRankDTO; import cn.fw.morax.domain.enums.*; import cn.fw.morax.domain.vo.kpi.*; import cn.fw.morax.service.biz.CommonService; import cn.fw.morax.service.data.kpi.*; import com.alibaba.fastjson.JSON; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.google.common.collect.Lists; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.time.LocalDate; import java.time.YearMonth; import java.util.*; import java.util.function.Function; import java.util.stream.Collectors; import static cn.fw.common.businessvalidator.Validator.BV; @RequiredArgsConstructor @Service @Slf4j public class KpiGroupIndicatorBizService { private final KpiGroupIndicatorLaddersService kpiGroupIndicatorLaddersService; private final KpiGroupIndicatorService kpiGroupIndicatorService; private final KpiGroupIndicatorHitLogService kpiGroupIndicatorHitLogService; private final KpiGroupIndicatorParamService kpiGroupIndicatorParamService; private final KpiGroupIndicatorPreconditionService kpiGroupIndicatorPreconditionService; private final KpiGroupIndicatorTargetHitLogService kpiGroupIndicatorTargetHitLogService; private final KpiGroupIndicatorPreconditionLaddersService kpiGroupIndicatorPreconditionLaddersService; private final KpiPoolIndicatorValueService kpiPoolIndicatorValueService; private final IndicatorUserValueService indicatorUserValueService; private final KpiGroupUserService kpiGroupUserService; private final IndicatorsService indicatorsService; private final KpiGroupService kpiGroupService; private final CommonService commonService; private final KpiPoolService kpiPoolService; /** * 绩效组指标详情 * * @param kpiIndicatorId * @return */ public KpiGroupIndicatorVO kpiGroupIndicatorDetail(Long kpiIndicatorId) { KpiGroupIndicator kpiGroupIndicator = kpiGroupIndicatorService.getById(kpiIndicatorId); BV.isNull(kpiGroupIndicator, "绩效指标配置不存在,请重试"); KpiGroupIndicatorVO kpiGroupIndicatorVo = PublicUtil.copy(kpiGroupIndicator, KpiGroupIndicatorVO.class); List kpiGroupIndicatorLadders = kpiGroupIndicatorLaddersService.list(Wrappers.lambdaQuery() .eq(KpiGroupIndicatorLadders::getKpiGroupIndicatorId, kpiIndicatorId) .eq(KpiGroupIndicatorLadders::getYn, Boolean.TRUE) ); if (PublicUtil.isNotEmpty(kpiGroupIndicatorLadders)) { List indicatorLaddersVos = PublicUtil.copyList(kpiGroupIndicatorLadders, KpiGroupIndicatorLaddersVO.class); kpiGroupIndicatorVo.setIndicatorLadders(indicatorLaddersVos); } return kpiGroupIndicatorVo; } /** * 获取正在使用指标的绩效组 * * @param indicatorCode * @return */ public List getKpiGroupByIndicatorCode(String indicatorCode) { List kpiGroupIndicatorParams = kpiGroupIndicatorParamService.list(Wrappers.lambdaQuery() .eq(KpiGroupIndicatorParam::getIndicatorCode, indicatorCode) .eq(KpiGroupIndicatorParam::getYn, Boolean.TRUE) ); List preconditions = kpiGroupIndicatorPreconditionService.list(Wrappers.lambdaQuery() .eq(KpiGroupIndicatorPrecondition::getIndicatorCode, indicatorCode) .eq(KpiGroupIndicatorPrecondition::getYn, Boolean.TRUE) ); Set kpiGroupIds = new HashSet<>(); if (PublicUtil.isNotEmpty(kpiGroupIndicatorParams)) { kpiGroupIds.addAll(kpiGroupIndicatorParams.stream().map(KpiGroupIndicatorParam::getKpiGroupId).collect(Collectors.toSet())); } if (PublicUtil.isNotEmpty(preconditions)) { kpiGroupIds.addAll(preconditions.stream().map(KpiGroupIndicatorPrecondition::getKpiGroupId).collect(Collectors.toSet())); } if (PublicUtil.isEmpty(kpiGroupIds)) { return new ArrayList<>(); } List status = new ArrayList() {{ add(SettingStatusEnum.APPROVING); add(SettingStatusEnum.BE_EFFECTIVE); add(SettingStatusEnum.EFFECTIVE); }}; List kpiGroups = kpiGroupService.list(Wrappers.lambdaQuery() .in(KpiGroup::getId, kpiGroupIds) .in(KpiGroup::getStatus, status) .eq(KpiGroup::getYn, Boolean.TRUE) ); return kpiGroups; } /** * 绩效项目阶梯详情 * * @param kpiPoolId * @param kpiGroupIndicatorId * @param yearMonth * @return */ public KpiGroupIndicatorDetailVO getHitIndicatorLadder(Long kpiPoolId, Long kpiGroupIndicatorId, YearMonth yearMonth) { KpiPool kpiPool = kpiPoolService.getById(kpiPoolId); BV.notNull(kpiPool, "绩效池不存在"); LocalDate localDate = this.getPoolLastData(kpiPool); Long userId = kpiPool.getUserId(); KpiGroupIndicator kpiGroupIndicator = kpiGroupIndicatorService.getById(kpiGroupIndicatorId); BV.notNull(kpiGroupIndicator, "指标不存在"); KpiGroup kpiGroup = kpiGroupService.getAllDataById(kpiGroupIndicator.getKpiGroupId()); BV.notNull(kpiGroup, "绩效组不存在"); KpiGroupIndicatorDetailVO detailVO = new KpiGroupIndicatorDetailVO(); this.setIndicatorsVo(kpiGroupIndicatorId, userId, localDate, detailVO); detailVO.setKpiGroupId(kpiGroup.getId()); detailVO.setKpiTime(localDate.atTime(23, 59, 59)); detailVO.setPostId(kpiGroup.getPostId()); detailVO.setPostName(kpiGroup.getPostName()); detailVO.setKpiGroupShopIds(kpiGroup.getShopIds()); detailVO.setKpiGroupShopNames(kpiGroup.getShopNames()); return detailVO; } /** * 获取绩效池详情最近日期 * * @param kpiPool * @return */ public LocalDate getPoolLastData(KpiPool kpiPool) { KpiGroupUser kpiGroupUser = kpiGroupUserService.getMonthLastData(kpiPool.getKgc(), kpiPool.getUserId(), kpiPool.getMonthly()); if (PublicUtil.isEmpty(kpiGroupUser)) { log.error("员工绩效池:{},不存在绩效组人员", JSON.toJSONString(kpiPool)); return PublicUtil.getYesterdayOrEndOfMonthDay(kpiPool.getMonthly()); } return kpiGroupUser.getDataDate(); } /** * 设置指标 * * @param */ public void setIndicatorsVo(Long kpiGroupIndicatorId, Long userId, LocalDate localDate, KpiGroupIndicatorDetailVO detailVO) { KpiGroupIndicator kpiGroupIndicator = kpiGroupIndicatorService.getById(kpiGroupIndicatorId); BV.notNull(kpiGroupIndicator, "绩效组指标不存在"); detailVO.setScoreWay(kpiGroupIndicator.getScoreWay()); detailVO.setBaseScore(kpiGroupIndicator.getBaseScore()); detailVO.setParamAlias(kpiGroupIndicator.getParamAlias()); if (PublicUtil.isNotEmpty(kpiGroupIndicator.getLaddersType())) { detailVO.setLaddersType(kpiGroupIndicator.getLaddersType()); } //命中记录 KpiGroupIndicatorHitLog kpiGroupIndicatorHitLog = kpiGroupIndicatorHitLogService.getOne(Wrappers.lambdaQuery() .eq(KpiGroupIndicatorHitLog::getKpiGroupIndicatorId, kpiGroupIndicatorId) .eq(KpiGroupIndicatorHitLog::getDataDate, localDate) .eq(KpiGroupIndicatorHitLog::getUserId, userId) .eq(KpiGroupIndicatorHitLog::getYn, Boolean.TRUE) ); if (ScoreWayEnum.LADDER.equals(kpiGroupIndicator.getScoreWay())) { Long hitKpiIndicatorLaddersId = kpiGroupIndicatorHitLog.getKpiGroupIndicatorLaddersId(); List ladderVos = kpiGroupIndicatorLaddersService.getVos(kpiGroupIndicatorId, kpiGroupIndicator.getLaddersType()); for (KpiGroupIndicatorLaddersVO laddersVO : ladderVos) { if (PublicUtil.isNotEmpty(hitKpiIndicatorLaddersId)) { laddersVO.setHit((hitKpiIndicatorLaddersId.equals(laddersVO.getId()) ? Boolean.TRUE : Boolean.FALSE)); } } detailVO.setLadders(ladderVos); } if (PublicUtil.isNotEmpty(kpiGroupIndicatorHitLog) && DataTypeEnum.RATIO.equals(kpiGroupIndicator.getLaddersType())) { detailVO.setParamsValue(kpiGroupIndicatorHitLog.getKpiValue().multiply(Constant.ONE_HUNDRED)); } //参数 Map> paramMap = this.getKpiGroupIndicatorParamMap(kpiGroupIndicatorId, userId, localDate); detailVO.setLadderParams(paramMap.getOrDefault(ParamTypeEnum.LADDER, new ArrayList<>())); detailVO.setCommissionParams(paramMap.getOrDefault(ParamTypeEnum.COMMISSION, new ArrayList<>())); //条件 List preconditionVOS = kpiGroupIndicatorPreconditionService.getHitVos(kpiGroupIndicatorId, userId, localDate); detailVO.setConds(preconditionVOS); for (KpiGroupIndicatorPreconditionVO preconditionVO : preconditionVOS) { //条件目标记录 if (! TargetTypeEnum.NO.equals(preconditionVO.getTargetType())) { KpiGroupIndicatorTargetHitLog kpiGroupIndicatorTargetHitLog = kpiGroupIndicatorTargetHitLogService.getOne(Wrappers.lambdaQuery() .eq(KpiGroupIndicatorTargetHitLog::getReferId, preconditionVO.getId()) .eq(KpiGroupIndicatorTargetHitLog::getTargetType, IndicatorTypeEnum.PRE) .eq(KpiGroupIndicatorTargetHitLog::getDataDate, localDate) .eq(KpiGroupIndicatorTargetHitLog::getUserId, userId) .eq(KpiGroupIndicatorTargetHitLog::getYn, Boolean.TRUE) ); preconditionVO.processTargetPercent(kpiGroupIndicatorTargetHitLog); } else { //无条件目标记录 preconditionVO.processNoTargetPercent(); } //条件阶梯 List preconditionLaddersVOS = kpiGroupIndicatorPreconditionLaddersService.getVOS( preconditionVO.getId(), preconditionVO.getTargetType(), preconditionVO.getDataType()); for (KpiGroupIndicatorPreconditionLaddersVO preconditionLaddersVO : preconditionLaddersVOS) { if (PublicUtil.isNotEmpty(preconditionVO.getHitLaddersId()) && preconditionLaddersVO.getId().equals(preconditionVO.getHitLaddersId())) { preconditionLaddersVO.setHit(Boolean.TRUE); } } preconditionVO.setCondLadders(preconditionLaddersVOS); } } /** * 获取绩效参数 * * @param kpiGroupIndicatorId * @param userId * @param localDate * @return */ public Map> getKpiGroupIndicatorParamMap(Long kpiGroupIndicatorId, Long userId, LocalDate localDate) { List paramVos = kpiGroupIndicatorParamService.getKpiGroupIndicatorParamVos(kpiGroupIndicatorId); List indicatorCodes = paramVos.stream() .filter(param -> TargetTypeEnum.NO.equals(param.getTargetType())) .map(KpiGroupIndicatorParamVO::getIndicatorCode).collect(Collectors.toList()); Map indicatorCodeValueMap = new HashMap<>(); if (PublicUtil.isNotEmpty(indicatorCodes)) { List indicatorUserValues = indicatorUserValueService.list(Wrappers.lambdaQuery() .in(IndicatorUserValue::getIndicatorCode, indicatorCodes) .eq(IndicatorUserValue::getDataDate, localDate) .eq(IndicatorUserValue::getUserId, userId) .eq(IndicatorUserValue::getYn, Boolean.TRUE) ); indicatorCodeValueMap = indicatorUserValues.stream() .collect(Collectors.toMap(IndicatorUserValue::getIndicatorCode, Function.identity(), (v1, v2) -> v1)); } List paramIds = paramVos.stream() .filter(param -> !TargetTypeEnum.NO.equals(param.getTargetType())) .map(KpiGroupIndicatorParamVO::getId).collect(Collectors.toList()); Map paramTargetHitLogMap = new HashMap<>(); if (PublicUtil.isNotEmpty(paramIds)) { List targetHitLogs = kpiGroupIndicatorTargetHitLogService.list(Wrappers.lambdaQuery() .in(KpiGroupIndicatorTargetHitLog::getReferId, paramIds) .eq(KpiGroupIndicatorTargetHitLog::getDataDate, localDate) .eq(KpiGroupIndicatorTargetHitLog::getUserId, userId) .eq(KpiGroupIndicatorTargetHitLog::getYn, Boolean.TRUE) ); paramTargetHitLogMap = targetHitLogs.stream() .collect(Collectors.toMap(KpiGroupIndicatorTargetHitLog::getReferId, Function.identity(), (v1, v2) -> v1)); } for (KpiGroupIndicatorParamVO paramVO : paramVos) { //有目标 if (paramTargetHitLogMap.containsKey(paramVO.getId())) { KpiGroupIndicatorTargetHitLog targetHitLog = paramTargetHitLogMap.get(paramVO.getId()); if (DataTypeEnum.RATIO.equals(paramVO.getDataType())) { paramVO.setIndicatorValue(targetHitLog.getValue().multiply(Constant.ONE_HUNDRED)); } else { paramVO.setIndicatorValue(targetHitLog.getValue()); } paramVO.setReachValue(targetHitLog.getReachValue().multiply(Constant.ONE_HUNDRED)); continue; } //无目标 if (indicatorCodeValueMap.containsKey(paramVO.getIndicatorCode())) { IndicatorUserValue indicatorUserValue = indicatorCodeValueMap.get(paramVO.getIndicatorCode()); BigDecimal indicatorOriginValue = commonService.queryIndicatorValue(paramVO.getIndicatorCode(), indicatorUserValue); switch (indicatorUserValue.getValueType()) { case WORK_AGE: case QUANTITY: { paramVO.setIndicatorValue(indicatorOriginValue); break; } case RATIO: { paramVO.setIndicatorValue(indicatorOriginValue.multiply(Constant.ONE_HUNDRED)); break; } } } } Map> indicatorParamMap = paramVos.stream() .collect(Collectors.groupingBy(KpiGroupIndicatorParamVO::getParamType)); return indicatorParamMap; } /** * 查询指标排名 * * @param dto * @return */ public KpiIndicatorRankVO queryKpiIndicatorRank(KpiGroupIndicatorRankDTO dto) { LocalDate localDate = PublicUtil.getYesterdayOrEndOfMonthDay(dto.getMonthly()); List pools = kpiPoolService.list(Wrappers.lambdaQuery() .eq(KpiPool::getKpiGroupId, dto.getKpiGroupId()) .eq(KpiPool::getMonthly, YearMonth.from(localDate)) // .eq(KpiPool::getInclusion, Boolean.TRUE) .eq(KpiPool::getYn, Boolean.TRUE) ); Long referId = null; BigDecimal targetValue = null; String indicatorCode = null; TargetTypeEnum targetType = null; TargetCalcTypeEnum targetCalcType = null; IndicatorTypeEnum indicatorTypeEnum = null; if (PublicUtil.isNotEmpty(dto.getKpiGroupIndicatorParamId())) { referId = dto.getKpiGroupIndicatorParamId(); indicatorTypeEnum = IndicatorTypeEnum.EXAMINE; KpiGroupIndicatorParam param = kpiGroupIndicatorParamService.getById(dto.getKpiGroupIndicatorParamId()); BV.isTrue(PublicUtil.isNotEmpty(param), "绩效组指标参数不存在"); indicatorCode = param.getIndicatorCode(); targetType = param.getTargetType(); targetValue = param.getTargetValue(); targetCalcType = param.getTargetCalcType(); } else { referId = dto.getKpiGroupIndicatorPreconditionId(); indicatorTypeEnum = IndicatorTypeEnum.PRE; KpiGroupIndicatorPrecondition precondition = kpiGroupIndicatorPreconditionService.getById(dto.getKpiGroupIndicatorPreconditionId()); BV.isTrue(PublicUtil.isNotEmpty(precondition), "绩效组指标条件不存在"); indicatorCode = precondition.getIndicatorCode(); targetType = precondition.getTargetType(); targetValue = precondition.getTargetValue(); targetCalcType = precondition.getTargetCalcType(); } Indicators indicators = indicatorsService.queryByCode(indicatorCode, Boolean.FALSE); BV.isTrue(PublicUtil.isNotEmpty(indicators), "指标不存在"); KpiIndicatorRankVO kpiIndicatorRankVO = KpiIndicatorRankVO.builder() .indicatorName(indicators.getIndicatorName()) .indicatorCode(indicators.getIndicatorCode()) .dataType(indicators.getDataType()) .targetType(targetType) .deadlineDate(DateUtil.localDate2Date(localDate)) .build(); if (PublicUtil.isEmpty(pools)) { log.error("绩效指标查无数据,指标:[{}] [{}] [{}]", indicatorCode, dto.getKpiGroupId(), localDate); return kpiIndicatorRankVO; } //无目标指标排名 if (TargetTypeEnum.NO.equals(targetType)) { kpiIndicatorRankVO.setStaffs(getNoTargetIndicatorRanks(indicatorCode, localDate, pools)); return kpiIndicatorRankVO; } //有目标指标排名 kpiIndicatorRankVO.setStaffs(getTargetIndicatorRanks(referId, localDate, pools, indicatorTypeEnum, indicators)); kpiIndicatorRankVO.setTargetValue((TargetTypeEnum.RATIO.equals(targetType) ? targetValue.multiply(Constant.ONE_HUNDRED) : targetValue)); kpiIndicatorRankVO.setTargetCalcType(targetCalcType); return kpiIndicatorRankVO; } /** * 无目标指标排名 * * @param indicatorCode * @param localDate * @param pools * @return */ public List getNoTargetIndicatorRanks(String indicatorCode, LocalDate localDate, List pools) { Set userIds = pools.stream().map(KpiPool::getUserId).collect(Collectors.toSet()); List indicatorUserValues = indicatorUserValueService.getStaffReportData(indicatorCode, YearMonth.from(localDate), userIds); Map indicatorUserValueMap = indicatorUserValues.stream() .collect(Collectors.toMap(IndicatorUserValueVO::getUserId, Function.identity(), (v1, v2) -> v1)); List staffRanks = Lists.newArrayListWithCapacity(indicatorUserValues.size()); for (KpiPool kpiPool : pools) { KpiIndicatorRankStaffVO rankStaffVO = new KpiIndicatorRankStaffVO(); rankStaffVO.setUserId(kpiPool.getUserId()); rankStaffVO.setUserName(kpiPool.getUserName()); rankStaffVO.setPostId(kpiPool.getPostId()); rankStaffVO.setPostName(kpiPool.getPostName()); rankStaffVO.setShopId(kpiPool.getShopId()); rankStaffVO.setShopName(kpiPool.getShopName()); rankStaffVO.setInclusion(kpiPool.getInclusion()); if (indicatorUserValueMap.containsKey(kpiPool.getUserId())) { IndicatorUserValueVO indicatorUserValueVO = indicatorUserValueMap.get(kpiPool.getUserId()); rankStaffVO.setOriginValue(commonService.queryIndicatorValueVO(indicatorCode, indicatorUserValueVO)); } staffRanks.add(rankStaffVO); } Collections.sort(staffRanks); calcRank(staffRanks); return staffRanks; } /** * 有目标指标排名 * * @param referId * @param localDate * @param pools * @param indicatorTypeEnum * @return */ public List getTargetIndicatorRanks(Long referId, LocalDate localDate, List pools, IndicatorTypeEnum indicatorTypeEnum, Indicators indicators) { Set userIds = pools.stream().map(KpiPool::getUserId).collect(Collectors.toSet()); List indicatorTargetHitLogs = kpiGroupIndicatorTargetHitLogService.getIndicatorData(referId, YearMonth.from(localDate), indicatorTypeEnum, userIds); Map indicatorTargetMap = indicatorTargetHitLogs.stream() .collect(Collectors.toMap(KpiGroupIndicatorTargetHitLogVO::getUserId, Function.identity(), (v1, v2) -> v1)); List staffRanks = Lists.newArrayListWithCapacity(indicatorTargetMap.size()); for (KpiPool kpiPool : pools) { KpiIndicatorRankStaffVO rankStaffVO = new KpiIndicatorRankStaffVO(); rankStaffVO.setUserId(kpiPool.getUserId()); rankStaffVO.setUserName(kpiPool.getUserName()); rankStaffVO.setPostId(kpiPool.getPostId()); rankStaffVO.setPostName(kpiPool.getPostName()); rankStaffVO.setShopId(kpiPool.getShopId()); rankStaffVO.setShopName(kpiPool.getShopName()); rankStaffVO.setInclusion(kpiPool.getInclusion()); if (indicatorTargetMap.containsKey(kpiPool.getUserId())) { KpiGroupIndicatorTargetHitLogVO targetHitLogVO = indicatorTargetMap.get(kpiPool.getUserId()); rankStaffVO.setOriginValue(targetHitLogVO.getValue()); rankStaffVO.setReachValue(targetHitLogVO.getReachValue()); rankStaffVO.convertReportValueToPercent(indicators.getDataType()); } staffRanks.add(rankStaffVO); } Collections.sort(staffRanks); calcRank(staffRanks); return staffRanks; } /** * 设置排名序号 * * @return */ public void calcRank(List staffs) { int rank = 1; Optional lastIndicatorValueOp = staffs.stream() .filter(staff -> Boolean.TRUE.equals(staff.getInclusion())) .findFirst().map(KpiIndicatorRankStaffVO::getOriginValue); if (Boolean.FALSE.equals(lastIndicatorValueOp.isPresent())) { return; } BigDecimal lastIndicatorValue = lastIndicatorValueOp.get(); for (KpiIndicatorRankStaffVO staff : staffs) { if (! staff.getInclusion()) { continue; } //原始值为空,无排名 if (PublicUtil.isEmpty(staff.getOriginValue())) { continue; } if (lastIndicatorValue.compareTo(staff.getOriginValue()) != 0) { rank++; } staff.setIndicatorRank(rank); lastIndicatorValue = staff.getOriginValue(); } } }