package cn.fw.morax.service.biz.calculator.eval.kpi; import cn.fw.morax.common.utils.PublicUtil; import cn.fw.morax.domain.bo.eval.EvalGroupUserShop; import cn.fw.morax.domain.db.eval.*; import cn.fw.morax.domain.db.kpi.*; import cn.fw.morax.domain.enums.*; import cn.fw.morax.service.biz.calculator.Calculator; import cn.fw.morax.service.data.eval.*; import cn.fw.morax.service.data.kpi.*; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import java.math.BigDecimal; import java.math.RoundingMode; import java.util.ArrayList; import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; /** * 考评基础计算器 * * @author : kurisu * @version : 2.0 * @className : BaseCalculator * @description : 考评基础计算器 * @date : 2022-12-26 14:17 */ @Slf4j public abstract class EvalKpiBaseCalculator implements Calculator { @Autowired protected EvalGroupIndicatorHitLogService evalGroupIndicatorHitLogService; @Autowired protected IndicatorUserValueService indicatorUserValueService; @Autowired protected IndicatorUserStageValueService indicatorUserStageValueService; @Autowired protected EvalIndicatorValueService evalIndicatorValueService; @Autowired protected EvalGroupIndicatorParamService evalGroupIndicatorParamService; @Autowired protected EvalGroupIndicatorPreconditionService evalGroupIndicatorPreconditionService; @Autowired protected EvalGroupIndicatorPreconditionHitLogService preconditionHitLogService; @Autowired protected EvalGroupIndicatorPreconditionLaddersService preconditionLaddersService; @Autowired protected EvalGroupIndicatorTargetHitLogService evalGroupIndicatorTargetHitLogService; /** * 获取设置类型 * * @return */ public abstract ScoreWayEnum getCalMethod(); /** * 通过前置条件计算绩效得分系数 * * @param preconditions * @return */ protected BigDecimal calcCoefficient(EvalGroupUserShop obj, List preconditions) { BigDecimal coefficient = BigDecimal.ONE; if (CollectionUtils.isEmpty(preconditions)) { return coefficient; } for (int i = 0; i < preconditions.size(); i++) { EvalGroupIndicatorPrecondition precondition = preconditions.get(i); TargetCalcTypeEnum targetCalcType = precondition.getTargetCalcType(); TargetTypeEnum targetType = precondition.getTargetType(); Optional valueOptional = queryValue(obj, precondition.getCodeType(), precondition.getCode()); if (! valueOptional.isPresent()) { return BigDecimal.ZERO; } final BigDecimal originValue = valueOptional.get();//queryIndicatorValue(precondition.getCode(), valueOptional.get()); BigDecimal indicatorValue = originValue; if (!TargetTypeEnum.NO.equals(targetType)) { BigDecimal targetValue = precondition.getTargetValue(); if (TargetCalcTypeEnum.TARGET_VALUE.equals(targetCalcType) || TargetCalcTypeEnum.STAGE_TARGET.equals(targetCalcType)) { indicatorValue = indicatorValue.divide(targetValue, 4, RoundingMode.HALF_UP); } else if (TargetCalcTypeEnum.MINIMUM.equals(targetCalcType)){ BigDecimal difference = BigDecimal.ONE.subtract(targetValue); if (BigDecimal.ZERO.compareTo(difference) == 0) { difference = BigDecimal.ONE; } BigDecimal userDiffValue = indicatorValue.subtract(targetValue); if (userDiffValue.compareTo(BigDecimal.ZERO) <= 0) { indicatorValue = BigDecimal.ZERO; } else { indicatorValue = userDiffValue.divide(difference, 4, RoundingMode.HALF_UP); } } saveTargetHitLog(obj, precondition.getId(), IndicatorTypeEnum.PRE, originValue, indicatorValue); } coefficient = coefficient(obj, precondition.getId(), indicatorValue); } return coefficient; } protected BigDecimal coefficient(EvalGroupUserShop obj, Long preconditionId, BigDecimal value) { EvalGroupIndicatorPreconditionLadders ladder = preconditionLaddersService.getOne(Wrappers.lambdaQuery() .eq(EvalGroupIndicatorPreconditionLadders::getPreconditionId, preconditionId) .gt(EvalGroupIndicatorPreconditionLadders::getUpper, value) .le(EvalGroupIndicatorPreconditionLadders::getLower, value) .eq(EvalGroupIndicatorPreconditionLadders::getYn, Boolean.TRUE), Boolean.FALSE ); if (Objects.isNull(ladder)) { savePreconditionHitLog(obj, preconditionId, hitLog -> { hitLog.setPreconditionLaddersId(-1L); hitLog.setValue(value); }); return BigDecimal.ZERO; } savePreconditionHitLog(obj, preconditionId, hitLog -> { hitLog.setPreconditionLaddersId(ladder.getId()); hitLog.setValue(value); }); return ladder.getScorePercent(); } /** * 计算最终的指标值 * * @param params * @param userShop * @param evalGroupIndicatorId * @return */ protected BigDecimal calculateFinalIndValue(List params, EvalGroupUserShop userShop, Long evalGroupIndicatorId) { BigDecimal rate = BigDecimal.ZERO; if (CollectionUtils.isEmpty(params)) { log.info("指标[{}]配置不存在", evalGroupIndicatorId); return rate; } for (EvalGroupIndicatorParam param : params) { Optional valueOptional = queryValue(userShop, param.getCodeType(), param.getCode()); if (! valueOptional.isPresent()) { log.info("[{}] [{}]指标[{}]值不存在", userShop.getScopeType().getName(), userShop.getReferId(), param.getCode()); continue; } TargetTypeEnum targetType = param.getTargetType(); TargetTypeEnum extraTargetType = param.getExtraTargetType(); final BigDecimal originValue = valueOptional.get(); BigDecimal indicatorValue = null; BigDecimal extraIndicatorValue = null; if (!TargetTypeEnum.NO.equals(targetType)) { indicatorValue = calcTarget(param.getTargetCalcType(), originValue, param.getTargetValue()); } if (PublicUtil.isNotEmpty(extraTargetType) && (!TargetTypeEnum.NO.equals(extraTargetType))) { extraIndicatorValue = calcTarget(param.getExtraTargetCalcType(), originValue, param.getExtraTargetValue()); //额外计算类型值 原始计算类型值 用大的那个值 if (PublicUtil.isEmpty(indicatorValue) || (extraIndicatorValue.compareTo(indicatorValue) > 0)) { indicatorValue = extraIndicatorValue; } } saveTargetHitLog(userShop, param.getId(), IndicatorTypeEnum.EXAMINE, originValue, indicatorValue); boolean isCap = Boolean.TRUE.equals(param.getCap()); BigDecimal proportion = param.getProportion(); if (isCap) { indicatorValue = BigDecimal.ONE.compareTo(indicatorValue) > 0 ? indicatorValue : BigDecimal.ONE; } rate = rate.add(proportion.multiply(indicatorValue)); } return rate; } /** * 计算目标 */ public BigDecimal calcTarget(TargetCalcTypeEnum targetCalcType, BigDecimal indicatorValue, BigDecimal targetValue) { if (PublicUtil.isEmpty(targetValue) || BigDecimal.ZERO.compareTo(targetValue) == 0) { return BigDecimal.ZERO; } if (TargetCalcTypeEnum.MINIMUM.equals(targetCalcType)) { BigDecimal difference = BigDecimal.ONE.subtract(targetValue); if (BigDecimal.ZERO.compareTo(difference) == 0) { difference = BigDecimal.ONE; } BigDecimal userDiffValue = indicatorValue.subtract(targetValue); if (userDiffValue.compareTo(BigDecimal.ZERO) <= 0) { return BigDecimal.ZERO; } else { return userDiffValue.divide(difference, 4, RoundingMode.HALF_UP); } } return indicatorValue.divide(targetValue, 4, RoundingMode.HALF_UP); } /** * 查询指标值 * * @return */ protected Optional queryValue(EvalGroupUserShop obj, IndicatorCodeTypeEnum codeType, String indicatorCode) { DimensionTypeEnum dimensionType = EvalScopeEnum.STAFF.equals(obj.getScopeType()) ? DimensionTypeEnum.STAFF : DimensionTypeEnum.SHOP; if (IndicatorCodeTypeEnum.INDICATOR.equals(codeType)) { LambdaQueryWrapper queryWrapper = Wrappers.lambdaQuery() .eq(IndicatorUserStageValue::getIndicatorCode, indicatorCode) .eq(IndicatorUserStageValue::getBeginDate, obj.getBeginDate()) .eq(IndicatorUserStageValue::getEndDate, obj.getDataDate()) .eq(IndicatorUserStageValue::getDimensionType, dimensionType) .eq(IndicatorUserStageValue::getYn, Boolean.TRUE) .eq(IndicatorUserStageValue::getGroupId, obj.getGroupId()); if (EvalScopeEnum.STAFF.equals(obj.getScopeType())) { queryWrapper.eq(IndicatorUserStageValue::getUserId, obj.getReferId()); } else { queryWrapper.eq(IndicatorUserStageValue::getShopId, obj.getReferId()); } IndicatorUserStageValue indicatorUserStageValue = indicatorUserStageValueService.getOne(queryWrapper, Boolean.FALSE); return queryKpiIndicatorValue(indicatorUserStageValue); } EvalIndicatorValue evalIndicatorValue = evalIndicatorValueService.queryLastValue(obj.getReferId(), dimensionType, indicatorCode, obj.getDataDate()); return Optional.ofNullable(evalIndicatorValue).map(EvalIndicatorValue::getIndicatorValue); } /** * 查询前置条件 * * @param evalGroupIndicatorId * @return */ protected List queryPrecondition(Long evalGroupIndicatorId) { List preList = evalGroupIndicatorPreconditionService.list(Wrappers.lambdaQuery() .eq(EvalGroupIndicatorPrecondition::getEvalGroupIndicatorId, evalGroupIndicatorId) .eq(EvalGroupIndicatorPrecondition::getYn, Boolean.TRUE) .orderByAsc(EvalGroupIndicatorPrecondition::getSort) ); return Optional.ofNullable(preList).orElse(new ArrayList<>()); } /** * 查询指标配置 * * @param evalGroupIndicatorId * @return */ protected List queryParam(Long evalGroupIndicatorId) { List list = evalGroupIndicatorParamService.list(Wrappers.lambdaQuery() .eq(EvalGroupIndicatorParam::getEvalGroupIndicatorId, evalGroupIndicatorId) .eq(EvalGroupIndicatorParam::getYn, Boolean.TRUE) ); return Optional.ofNullable(list).orElse(new ArrayList<>()); } /** * 查询具体指标值 * * @param indicatorUserStageValue * @return */ protected Optional queryKpiIndicatorValue(IndicatorUserStageValue indicatorUserStageValue) { if (PublicUtil.isEmpty(indicatorUserStageValue) || PublicUtil.isEmpty(indicatorUserStageValue.getIndicatorValue())) { return Optional.empty(); } BigDecimal value = BigDecimal.ZERO; try { JSONObject jsonObject = JSONObject.parseObject(indicatorUserStageValue.getIndicatorValue()); value = Optional.ofNullable(jsonObject.getBigDecimal(indicatorUserStageValue.getIndicatorCode())).orElse(BigDecimal.ZERO); } catch (Exception e) { log.error("[{}]指标值转化失败", indicatorUserStageValue, e); } return Optional.of(value); } /** * 查询具体指标值 * * @param indicatorCode * @param originalValue * @return */ protected BigDecimal queryIndicatorValue(String indicatorCode, String originalValue) { BigDecimal value = BigDecimal.ZERO; try { JSONObject jsonObject = JSONObject.parseObject(originalValue); value = Optional.ofNullable(jsonObject.getBigDecimal(indicatorCode)).orElse(BigDecimal.ZERO); } catch (Exception e) { log.error("[{}]指标值转化失败", indicatorCode, e); } return value; } protected void savePreconditionHitLog(EvalGroupUserShop userShop, Long preconditionId, Consumer consumer) { Long poolId = userShop.getPoolId(); EvalScopeEnum evalScope = userShop.getScopeType(); preconditionHitLogService.remove(Wrappers.lambdaQuery() .eq(EvalGroupIndicatorPreconditionHitLog::getPoolId, poolId) .eq(EvalGroupIndicatorPreconditionHitLog::getPreconditionId, preconditionId) .eq(EvalGroupIndicatorPreconditionHitLog::getDataDate, userShop.getDataDate()) .eq(EvalGroupIndicatorPreconditionHitLog::getGroupId, userShop.getGroupId()) ); EvalGroupIndicatorPreconditionHitLog hitLog = new EvalGroupIndicatorPreconditionHitLog(); hitLog.setPreconditionId(preconditionId); hitLog.setPoolId(poolId); hitLog.setScopeType(evalScope); hitLog.setDataDate(userShop.getDataDate()); hitLog.setGroupId(userShop.getGroupId()); if (consumer != null) { consumer.accept(hitLog); } preconditionHitLogService.save(hitLog); } protected void saveTargetHitLog(EvalGroupUserShop userShop, Long referId, IndicatorTypeEnum targetType, BigDecimal value, BigDecimal reachValue) { evalGroupIndicatorTargetHitLogService.remove(Wrappers.lambdaQuery() .eq(EvalGroupIndicatorTargetHitLog::getPoolId, userShop.getPoolId()) .eq(EvalGroupIndicatorTargetHitLog::getScopeType, userShop.getScopeType()) .eq(EvalGroupIndicatorTargetHitLog::getTargetType, targetType) .eq(EvalGroupIndicatorTargetHitLog::getDataDate, userShop.getDataDate()) .eq(EvalGroupIndicatorTargetHitLog::getReferId, referId) ); EvalGroupIndicatorTargetHitLog log = new EvalGroupIndicatorTargetHitLog(); log.setPoolId(userShop.getPoolId()); log.setScopeType(userShop.getScopeType()); log.setReferId(referId); log.setTargetType(targetType); log.setValue(value); log.setReachValue(reachValue); log.setDataDate(userShop.getDataDate()); log.setGroupId(userShop.getGroupId()); log.setYn(Boolean.TRUE); evalGroupIndicatorTargetHitLogService.save(log); } /** * 储存命中记录 * * @param evalGroupIndicatorId * @param userShop */ protected void saveParamHitLog(Long evalGroupIndicatorId, EvalGroupUserShop userShop, Consumer consumer) { EvalGroupIndicatorHitLog hitLog = new EvalGroupIndicatorHitLog(); hitLog.setEvalGroupIndicatorId(evalGroupIndicatorId); hitLog.setPoolId(userShop.getPoolId()); hitLog.setScopeType(userShop.getScopeType()); hitLog.setDataDate(userShop.getDataDate()); hitLog.setGroupId(userShop.getGroupId()); hitLog.setYn(Boolean.TRUE); if (consumer != null) { consumer.accept(hitLog); } evalGroupIndicatorHitLogService.saveUnique(hitLog); } }