package cn.fw.morax.service.biz.calculator.kpi; import cn.fw.morax.domain.bo.kpi.KpiIndicatorBO; import cn.fw.morax.domain.db.kpi.*; import cn.fw.morax.domain.enums.IndicatorTypeEnum; import cn.fw.morax.domain.enums.ScoreWayEnum; import cn.fw.morax.domain.enums.TargetCalcTypeEnum; import cn.fw.morax.domain.enums.TargetTypeEnum; import cn.fw.morax.service.biz.calculator.Calculator; import cn.fw.morax.service.data.kpi.*; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; import com.google.common.base.Strings; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.LocalDate; import java.util.*; import java.util.function.Consumer; /** * @author : kurisu * @version : 1.0 * @className : KpiBaseCalculator * @description : 绩效计算器 * @date : 2022-04-18 11:28 */ @Slf4j public abstract class KpiAbsBaseCalculator implements Calculator { @Autowired protected KpiGroupIndicatorHitLogService kpiGroupIndicatorHitLogService; @Autowired protected IndicatorUserValueService indicatorUserValueService; @Autowired protected KpiGroupIndicatorParamService kpiGroupIndicatorParamService; @Autowired protected KpiGroupIndicatorPreconditionService kpiGroupIndicatorPreconditionService; @Autowired protected KpiGroupIndicatorPreconditionHitLogService preconditionHitLogService; @Autowired protected KpiGroupIndicatorPreconditionLaddersService preconditionLaddersService; @Autowired protected KpiGroupIndicatorTargetHitLogService kpiGroupIndicatorTargetHitLogService; public static void main(String[] args) { Set set = new HashSet<>(); set.add(1L); set.add(2L); set.add(3L); String json = JSON.toJSONString(set); System.out.println(json); List set2 = JSON.parseArray(json, Long.class); System.out.println(set2.toString()); System.out.println(Arrays.toString(set2.toArray())); String join = StringUtils.join(",", set); System.out.println(join); } /** * 获取设置类型 * * @return */ public abstract ScoreWayEnum getCalMethod(); /** * 查询前置条件 * * @param kpiGroupIndicatorId * @param kpiGroupId * @return */ protected List queryPrecondition(Long kpiGroupIndicatorId, Long kpiGroupId) { List preList = kpiGroupIndicatorPreconditionService.list(Wrappers.lambdaQuery() .eq(KpiGroupIndicatorPrecondition::getKpiGroupIndicatorId, kpiGroupIndicatorId) .eq(KpiGroupIndicatorPrecondition::getKpiGroupId, kpiGroupId) .eq(KpiGroupIndicatorPrecondition::getYn, Boolean.TRUE) .orderByAsc(KpiGroupIndicatorPrecondition::getSort) ); return Optional.ofNullable(preList).orElse(new ArrayList<>()); } /** * 查询指标配置 * * @param kpiGroupIndicatorId * @param kpiGroupId * @return */ protected List queryParam(Long kpiGroupIndicatorId, Long kpiGroupId) { List list = kpiGroupIndicatorParamService.list(Wrappers.lambdaQuery() .eq(KpiGroupIndicatorParam::getKpiGroupIndicatorId, kpiGroupIndicatorId) .eq(KpiGroupIndicatorParam::getKpiGroupId, kpiGroupId) .eq(KpiGroupIndicatorParam::getYn, Boolean.TRUE) ); return Optional.ofNullable(list).orElse(new ArrayList<>()); } /** * 查询指标值 * * @param userId * @param groupId * @param dataDate * @param indicatorCode * @return */ protected IndicatorUserValue queryValue(Long userId, Long groupId, LocalDate dataDate, String indicatorCode) { return indicatorUserValueService.getOne(Wrappers.lambdaQuery() .eq(IndicatorUserValue::getUserId, userId) .eq(IndicatorUserValue::getIndicatorCode, indicatorCode) .eq(IndicatorUserValue::getDataDate, dataDate) .eq(IndicatorUserValue::getYn, Boolean.TRUE) .eq(IndicatorUserValue::getGroupId, groupId) , Boolean.FALSE ); } /** * 查询具体指标值 * * @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; } /** * 通过前置条件计算绩效得分系数 * * @param list * @return */ protected BigDecimal calcCoefficient(KpiGroupUser user, List list) { BigDecimal coefficient = BigDecimal.ONE; if (CollectionUtils.isEmpty(list)) { return coefficient; } final Long userId = user.getUserId(); for (int i = 0; i < list.size(); i++) { KpiGroupIndicatorPrecondition precondition = list.get(i); TargetTypeEnum targetType = precondition.getTargetType(); IndicatorUserValue userValue = queryValue(userId, user.getGroupId(), user.getDataDate(), precondition.getIndicatorCode()); if (Objects.isNull(userValue)) { return BigDecimal.ZERO; } final BigDecimal originValue = queryIndicatorValue(userValue.getIndicatorCode(), userValue.getIndicatorValue()); BigDecimal indicatorValue = originValue; if (!TargetTypeEnum.NO.equals(targetType)) { BigDecimal targetValue = precondition.getTargetValue(); TargetCalcTypeEnum targetCalcType = precondition.getTargetCalcType(); if (TargetCalcTypeEnum.TARGET_VALUE.equals(targetCalcType)) { indicatorValue = indicatorValue.divide(targetValue, 4, RoundingMode.HALF_UP); } else { 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(user, precondition.getId(), IndicatorTypeEnum.PRE, originValue, indicatorValue); } coefficient = coefficient.multiply(coefficient(user, precondition.getId(), indicatorValue)) .divide(BigDecimal.ONE, 2, RoundingMode.HALF_UP); } return coefficient; } protected BigDecimal coefficient(KpiGroupUser user, Long preconditionId, BigDecimal value) { KpiGroupIndicatorPreconditionLadders ladder = preconditionLaddersService.getOne(Wrappers.lambdaQuery() .eq(KpiGroupIndicatorPreconditionLadders::getPreconditionId, preconditionId) .gt(KpiGroupIndicatorPreconditionLadders::getUpper, value) .le(KpiGroupIndicatorPreconditionLadders::getLower, value) .eq(KpiGroupIndicatorPreconditionLadders::getYn, Boolean.TRUE), Boolean.FALSE ); if (Objects.isNull(ladder)) { savePreconditionHitLog(user, preconditionId, hitLog -> { hitLog.setPreconditionLaddersId(-1L); hitLog.setValue(value); }); return BigDecimal.ZERO; } savePreconditionHitLog(user, preconditionId, hitLog -> { hitLog.setPreconditionLaddersId(ladder.getId()); hitLog.setValue(value); }); return ladder.getScorePercent(); } /** * 计算最终的指标值 * * @param paramList * @param user * @param kpiGroupIndicatorId * @return */ protected BigDecimal calculateFinalIndValue(List paramList, KpiGroupUser user, Long kpiGroupIndicatorId) { BigDecimal rate = BigDecimal.ZERO; if (CollectionUtils.isEmpty(paramList)) { log.info("指标[{}]配置不存在", kpiGroupIndicatorId); return rate; } for (KpiGroupIndicatorParam param : paramList) { IndicatorUserValue userValue = queryValue(user.getUserId(), user.getGroupId(), user.getDataDate(), param.getIndicatorCode()); if (Objects.isNull(userValue)) { log.info("用户[{}]指标[{}]值不存在", user.getUserId(), kpiGroupIndicatorId); continue; } TargetTypeEnum targetType = param.getTargetType(); final BigDecimal originValue = queryIndicatorValue(userValue.getIndicatorCode(), userValue.getIndicatorValue()); BigDecimal indicatorValue = originValue; if (!TargetTypeEnum.NO.equals(targetType)) { BigDecimal targetValue = param.getTargetValue(); TargetCalcTypeEnum targetCalcType = param.getTargetCalcType(); if (TargetCalcTypeEnum.TARGET_VALUE.equals(targetCalcType)) { indicatorValue = indicatorValue.divide(targetValue, 4, RoundingMode.HALF_UP); } else { 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(user, 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; } protected void savePreconditionHitLog(KpiGroupUser user, Long preconditionId, Consumer consumer) { preconditionHitLogService.remove(Wrappers.lambdaQuery() .eq(KpiGroupIndicatorPreconditionHitLog::getUserId, user.getUserId()) .eq(KpiGroupIndicatorPreconditionHitLog::getPreconditionId, preconditionId) .eq(KpiGroupIndicatorPreconditionHitLog::getDataDate, user.getDataDate()) .eq(KpiGroupIndicatorPreconditionHitLog::getGroupId, user.getGroupId()) ); KpiGroupIndicatorPreconditionHitLog hitLog = new KpiGroupIndicatorPreconditionHitLog(); hitLog.setPreconditionId(preconditionId); hitLog.setUserId(user.getUserId()); hitLog.setDataDate(user.getDataDate()); hitLog.setGroupId(user.getGroupId()); if (consumer != null) { consumer.accept(hitLog); } preconditionHitLogService.save(hitLog); } protected void saveTargetHitLog(KpiGroupUser user, Long referId, IndicatorTypeEnum targetType, BigDecimal value, BigDecimal reachValue) { kpiGroupIndicatorTargetHitLogService.remove(Wrappers.lambdaQuery() .eq(KpiGroupIndicatorTargetHitLog::getUserId, user.getUserId()) .eq(KpiGroupIndicatorTargetHitLog::getTargetType, targetType) .eq(KpiGroupIndicatorTargetHitLog::getDataDate, user.getDataDate()) .eq(KpiGroupIndicatorTargetHitLog::getReferId, referId) ); KpiGroupIndicatorTargetHitLog log = new KpiGroupIndicatorTargetHitLog(); log.setReferId(referId); log.setTargetType(targetType); log.setUserId(user.getUserId()); log.setValue(value); log.setReachValue(reachValue); log.setDataDate(user.getDataDate()); log.setGroupId(user.getGroupId()); log.setYn(Boolean.TRUE); kpiGroupIndicatorTargetHitLogService.save(log); } /** * 储存命中记录 * * @param kpiGroupIndicatorId * @param kpiGroupIndicatorLaddersId * @param kpiValue * @param user */ protected void saveParamHitLog(Long kpiGroupIndicatorId, Long kpiGroupIndicatorLaddersId, BigDecimal kpiValue, KpiGroupUser user) { KpiGroupIndicatorHitLog hitLog = new KpiGroupIndicatorHitLog(); hitLog.setKpiGroupIndicatorId(kpiGroupIndicatorId); hitLog.setKpiGroupIndicatorLaddersId(kpiGroupIndicatorLaddersId); hitLog.setUserId(user.getUserId()); hitLog.setKpiValue(kpiValue); hitLog.setDataDate(user.getDataDate()); hitLog.setGroupId(user.getGroupId()); hitLog.setYn(Boolean.TRUE); kpiGroupIndicatorHitLogService.saveUnique(hitLog); } }