Commit 5ff2c5252d6b641ed1a15d7a19da8e5f197ca991

Authored by 姜超
1 parent d833d181

feature(*): 并列排名计算

并列排名计算
fw-morax-dao/src/main/java/cn/fw/morax/dao/eval/EvalGroupRewardRankLogDao.java 0 → 100644
  1 +package cn.fw.morax.dao.eval;
  2 +
  3 +
  4 +import cn.fw.morax.domain.db.eval.EvalGroupRewardRankLog;
  5 +import com.baomidou.mybatisplus.core.mapper.BaseMapper;
  6 +
  7 +/**
  8 + * <p>
  9 + * 考评指标达成目标记录 Mapper 接口
  10 + * </p>
  11 + *
  12 + * @author jiangchao
  13 + * @since 2022-12-09
  14 + */
  15 +public interface EvalGroupRewardRankLogDao extends BaseMapper<EvalGroupRewardRankLog> {
  16 +
  17 +
  18 +}
... ...
fw-morax-domain/src/main/java/cn/fw/morax/domain/db/eval/EvalGroupRewardRankLog.java 0 → 100644
  1 +package cn.fw.morax.domain.db.eval;
  2 +
  3 +import cn.fw.common.data.entity.BaseAuditableTimeEntity;
  4 +import cn.fw.morax.domain.dto.eval.EvalGroupIndicatorPreconditionLaddersDTO;
  5 +import cn.fw.morax.domain.enums.EvalScopeEnum;
  6 +import cn.fw.morax.domain.enums.IndicatorTypeEnum;
  7 +import cn.fw.morax.domain.enums.RankIndicatorTypeEnum;
  8 +import com.baomidou.mybatisplus.annotation.TableName;
  9 +import lombok.*;
  10 +
  11 +import java.math.BigDecimal;
  12 +import java.time.LocalDate;
  13 +
  14 +/**
  15 + * <p>
  16 + * 奖惩排名日志
  17 + * </p>
  18 + *
  19 + * @author jiangchao
  20 + * @since 2022-12-13
  21 + */
  22 +@Data
  23 +@EqualsAndHashCode(callSuper = false)
  24 +@TableName(autoResultMap = true)
  25 +@AllArgsConstructor
  26 +@NoArgsConstructor
  27 +@Builder
  28 +public class EvalGroupRewardRankLog extends BaseAuditableTimeEntity<EvalGroupRewardRankLog, Long>
  29 + implements Comparable<EvalGroupRewardRankLog>{
  30 +
  31 + private static final long serialVersionUID = 1L;
  32 +
  33 + /**
  34 + * 员工id
  35 + */
  36 + private Long poolId;
  37 +
  38 + /**
  39 + * 考评范围; 1:门店考评 2:人员考评
  40 + */
  41 + private EvalScopeEnum scopeType;
  42 +
  43 + /**
  44 + * 考评奖惩 前置条件 配置id
  45 + */
  46 + private Long referId;
  47 + /**
  48 + * 指标类型 1.奖惩提成 2.前置条件指标
  49 + */
  50 + private RankIndicatorTypeEnum targetType;
  51 + /**
  52 + * 原始值
  53 + */
  54 + private BigDecimal value;
  55 + /**
  56 + * 达成目标
  57 + */
  58 + private BigDecimal reachValue;
  59 + /**
  60 + * 排名
  61 + */
  62 + private Integer rank;
  63 +
  64 + /**
  65 + * 数据日期
  66 + */
  67 + private LocalDate dataDate;
  68 +
  69 + /**
  70 + * 集团
  71 + */
  72 + private Long groupId;
  73 +
  74 + private Boolean yn;
  75 +
  76 + @Override
  77 + public int compareTo(EvalGroupRewardRankLog other) {
  78 + return other.reachValue.compareTo(this.reachValue);
  79 + }
  80 +}
... ...
fw-morax-domain/src/main/java/cn/fw/morax/domain/enums/RankIndicatorTypeEnum.java 0 → 100644
  1 +package cn.fw.morax.domain.enums;
  2 +
  3 +import com.baomidou.mybatisplus.core.enums.IEnum;
  4 +import com.fasterxml.jackson.annotation.JsonCreator;
  5 +import com.fasterxml.jackson.annotation.JsonValue;
  6 +import lombok.Getter;
  7 +
  8 +/**
  9 + * 指标类型
  10 + *
  11 + * @author kurisu
  12 + */
  13 +public enum RankIndicatorTypeEnum implements IEnum<Integer> {
  14 + /**
  15 + * 指标类型 1.奖惩提成 2.前置条件指标
  16 + */
  17 + REWARD_COMMISSION(1, "奖惩提成"),
  18 + PRE(2, "前置条件指标"),
  19 + ;
  20 +
  21 + /**
  22 + * 值
  23 + */
  24 + private final Integer value;
  25 + /**
  26 + * 名称
  27 + */
  28 + @Getter
  29 + private final String name;
  30 +
  31 + RankIndicatorTypeEnum(final Integer value, final String name) {
  32 + this.value = value;
  33 + this.name = name;
  34 + }
  35 +
  36 + /**
  37 + * 根据枚举值获取枚举对象
  38 + */
  39 + @JsonCreator
  40 + public static RankIndicatorTypeEnum ofValue(final Integer value) {
  41 + for (final RankIndicatorTypeEnum _enum : RankIndicatorTypeEnum.values()) {
  42 + if (_enum.value.equals(value)) {
  43 + return _enum;
  44 + }
  45 + }
  46 + return null;
  47 + }
  48 +
  49 + /**
  50 + * 获取值
  51 + *
  52 + * @return 值
  53 + */
  54 + @JsonValue
  55 + @Override
  56 + public Integer getValue() {
  57 + return value;
  58 + }
  59 +
  60 + /**
  61 + * 获取描述
  62 + *
  63 + * @return 值
  64 + */
  65 + @JsonCreator
  66 + public static String getNameByVale(final Integer value) {
  67 + for (final RankIndicatorTypeEnum _enum : RankIndicatorTypeEnum.values()) {
  68 + if (_enum.value.equals(value)) {
  69 + return _enum.getName();
  70 + }
  71 + }
  72 + return "";
  73 + }
  74 +}
... ...
fw-morax-domain/src/main/java/cn/fw/morax/domain/vo/eval/EvalGroupRewardRankLogVO.java 0 → 100644
  1 +package cn.fw.morax.domain.vo.eval;
  2 +
  3 +import cn.fw.morax.common.constant.Constant;
  4 +import cn.fw.morax.common.utils.PublicUtil;
  5 +import cn.fw.morax.domain.enums.DataTypeEnum;
  6 +import cn.fw.morax.domain.enums.EvalScopeEnum;
  7 +import cn.fw.morax.domain.enums.RankIndicatorTypeEnum;
  8 +import cn.fw.morax.domain.enums.TargetTypeEnum;
  9 +import lombok.Data;
  10 +import lombok.EqualsAndHashCode;
  11 +
  12 +import java.math.BigDecimal;
  13 +import java.time.LocalDate;
  14 +
  15 +/**
  16 + * <p>
  17 + * 奖惩排名日志
  18 + * </p>
  19 + *
  20 + * @author jiangchao
  21 + * @since 2022-12-13
  22 + */
  23 +@Data
  24 +@EqualsAndHashCode(callSuper = false)
  25 +public class EvalGroupRewardRankLogVO {
  26 +
  27 + private static final long serialVersionUID = 1L;
  28 + /**
  29 + * id
  30 + */
  31 + private Long id;
  32 +
  33 + /**
  34 + * 员工id
  35 + */
  36 + private Long poolId;
  37 +
  38 + /**
  39 + * 考评范围; 1:门店考评 2:人员考评
  40 + */
  41 + private EvalScopeEnum scopeType;
  42 +
  43 + /**
  44 + * 考评奖惩 前置条件 配置id
  45 + */
  46 + private Long referId;
  47 + /**
  48 + * 指标类型 1.奖惩提成 2.前置条件指标
  49 + */
  50 + private RankIndicatorTypeEnum targetType;
  51 + /**
  52 + * 原始值
  53 + */
  54 + private BigDecimal value;
  55 + /**
  56 + * 达成目标
  57 + */
  58 + private BigDecimal reachValue;
  59 + /**
  60 + * 排名
  61 + */
  62 + private Integer rank;
  63 +
  64 + /**
  65 + * 数据日期
  66 + */
  67 + private LocalDate dataDate;
  68 +
  69 + /**
  70 + * 集团
  71 + */
  72 + private Long groupId;
  73 +
  74 + /**
  75 + * 转换为百分数展示
  76 + */
  77 + public void convertValueToPercent(DataTypeEnum dataType, TargetTypeEnum targetType){
  78 + if (DataTypeEnum.RATIO.equals(dataType)) {
  79 + this.setValue(this.getValue().multiply(Constant.ONE_HUNDRED));
  80 + }
  81 + //有目标
  82 + if (! TargetTypeEnum.NO.equals(targetType)) {
  83 + this.setReachValue(this.getReachValue().multiply(Constant.ONE_HUNDRED));
  84 + }
  85 + }
  86 +
  87 +}
... ...
fw-morax-server/src/main/java/cn/fw/morax/server/controller/app/EvalPoolController.java
... ... @@ -31,9 +31,11 @@ import java.time.YearMonth;
31 31 import java.time.temporal.ChronoField;
32 32 import java.time.temporal.TemporalAdjuster;
33 33 import java.time.temporal.TemporalAdjusters;
  34 +import java.util.List;
34 35 import java.util.Objects;
35 36 import java.util.Set;
36 37  
  38 +import static cn.fw.common.businessvalidator.Validator.BV;
37 39 import static cn.fw.common.web.util.ResultBuilder.success;
38 40  
39 41 /**
... ... @@ -195,6 +197,36 @@ public class EvalPoolController {
195 197 return success(evalGroupPoolService.queryIndicatorRank(dto, EvalScopeEnum.SHOP));
196 198 }
197 199  
  200 + /**
  201 + * 门店、人员考评条件指标排名
  202 + *
  203 + * @param preconditionId
  204 + * @param dataDate
  205 + * @return
  206 + */
  207 + @GetMapping("/reward-cond-rank")
  208 + @ControllerMethod("门店、人员考评条件指标排名")
  209 + public Message<List<EvalGroupRewardRankLogVO>> queryRewardCondRank(Long preconditionId,
  210 + @NotNull(message = "日期不能为空") @RequestParam("dataDate") LocalDate dataDate) {
  211 + return success(evalGroupPoolService.getRewardCondRankLogs(preconditionId, dataDate));
  212 + }
  213 +
  214 + /**
  215 + * 门店、人员考评提成指标排名
  216 + *
  217 + * @param commissionId
  218 + * @param dataDate
  219 + * @return
  220 + */
  221 + @GetMapping("/reward-commission-rank")
  222 + @ControllerMethod("门店、人员考评提成指标排名")
  223 + public Message<List<EvalGroupRewardRankLogVO>> queryRewardCommissionRank(Long commissionId,
  224 + @NotNull(message = "日期不能为空") @RequestParam("dataDate") LocalDate dataDate) {
  225 + return success(evalGroupPoolService.getRewardCondRankLogs(commissionId, dataDate));
  226 + }
  227 +
  228 +
  229 +
198 230  
199 231 /**
200 232 * 门店考评池列表
... ...
fw-morax-service/src/main/java/cn/fw/morax/service/biz/CommonService.java
... ... @@ -6,6 +6,7 @@ import cn.fw.morax.common.constant.Constant;
6 6 import cn.fw.morax.common.utils.ExcelDataUtil;
7 7 import cn.fw.morax.common.utils.PublicUtil;
8 8 import cn.fw.morax.domain.db.SettingDraft;
  9 +import cn.fw.morax.domain.db.eval.EvalGroupRewardRankLog;
9 10 import cn.fw.morax.domain.db.eval.EvalIndicatorValue;
10 11 import cn.fw.morax.domain.db.kpi.IndicatorUserValue;
11 12 import cn.fw.morax.domain.db.kpi.KpiGroup;
... ... @@ -15,6 +16,7 @@ import cn.fw.morax.domain.enums.IndicatorValueTypeEnum;
15 16 import cn.fw.morax.domain.enums.SettingDraftStatusEnum;
16 17 import cn.fw.morax.domain.enums.SettingDraftTypeEnum;
17 18 import cn.fw.morax.domain.vo.kpi.IndicatorUserValueVO;
  19 +import cn.fw.morax.domain.vo.kpi.KpiIndicatorRankStaffVO;
18 20 import cn.fw.morax.rpc.ehr.EhrRpcService;
19 21 import cn.fw.morax.rpc.ehr.dto.StaffBaseInfoDTO;
20 22 import cn.fw.morax.service.data.SettingDraftService;
... ... @@ -368,4 +370,27 @@ public class CommonService {
368 370 return settingDrafts;
369 371 }
370 372  
  373 + /**
  374 + * 设置排名序号
  375 + *
  376 + * @return
  377 + */
  378 + public void calcRank(List<EvalGroupRewardRankLog> rankLogs) {
  379 + int rank = 1;
  380 + BigDecimal lastIndicatorValue = null;
  381 + for (EvalGroupRewardRankLog rankLog : rankLogs) {
  382 + //初始化
  383 + if (PublicUtil.isEmpty(lastIndicatorValue)) {
  384 + rankLog.setRank(rank);
  385 + lastIndicatorValue = rankLog.getReachValue();
  386 + continue;
  387 + }
  388 + if (lastIndicatorValue.compareTo(rankLog.getReachValue()) != 0) {
  389 + rank++;
  390 + }
  391 + rankLog.setRank(rank);
  392 + lastIndicatorValue = rankLog.getReachValue();
  393 + }
  394 + }
  395 +
371 396 }
... ...
fw-morax-service/src/main/java/cn/fw/morax/service/biz/calculator/eval/reward/EvalRewardBaseCalculator.java
... ... @@ -6,12 +6,15 @@ import cn.fw.morax.domain.bo.eval.EvalGroupUserShop;
6 6 import cn.fw.morax.domain.db.eval.*;
7 7 import cn.fw.morax.domain.db.kpi.IndicatorUserValue;
8 8 import cn.fw.morax.domain.enums.*;
  9 +import cn.fw.morax.service.biz.CommonService;
9 10 import cn.fw.morax.service.biz.calculator.Calculator;
10 11 import cn.fw.morax.service.data.eval.*;
11 12 import cn.fw.morax.service.data.kpi.IndicatorUserValueService;
  13 +import com.alibaba.fastjson.JSON;
12 14 import com.alibaba.fastjson.JSONObject;
13 15 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
14 16 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  17 +import com.google.common.collect.Lists;
15 18 import lombok.Getter;
16 19 import lombok.extern.slf4j.Slf4j;
17 20 import org.springframework.beans.factory.annotation.Autowired;
... ... @@ -29,7 +32,6 @@ import java.time.LocalDateTime;
29 32 import java.time.temporal.ChronoUnit;
30 33 import java.util.*;
31 34 import java.util.concurrent.atomic.AtomicInteger;
32   -import java.util.concurrent.atomic.AtomicReference;
33 35 import java.util.function.Consumer;
34 36 import java.util.function.Function;
35 37 import java.util.stream.Collectors;
... ... @@ -47,6 +49,8 @@ import java.util.stream.Collectors;
47 49 public abstract class EvalRewardBaseCalculator implements Calculator<EvalGroupUserShop, EvalGroupReward, BigDecimal> {
48 50  
49 51 @Autowired
  52 + protected EvalGroupRewardRankLogService evalGroupRewardRankLogService;
  53 + @Autowired
50 54 protected EvalGroupRewardHitLogService evalGroupRewardHitLogService;
51 55 @Autowired
52 56 protected EvalGroupRewardPreconditionHitLogService evalGroupRewardPreconditionHitLogService;
... ... @@ -68,6 +72,8 @@ public abstract class EvalRewardBaseCalculator implements Calculator&lt;EvalGroupUs
68 72 protected EvalGroupRewardService evalGroupRewardService;
69 73 @Autowired
70 74 private StringRedisTemplate stringRedisTemplate;
  75 + @Autowired
  76 + private CommonService commonService;
71 77 @Value("${spring.cache.custom.global-prefix}:eval:reward:cond:rank")
72 78 @Getter
73 79 private String preconditionRank;
... ... @@ -173,49 +179,43 @@ public abstract class EvalRewardBaseCalculator implements Calculator&lt;EvalGroupUs
173 179 return;
174 180 }
175 181 for (EvalGroupRewardPrecondition precondition : preconditions) {
176   - final String indicatorCode = precondition.getCode();
177 182 final Long preconditionId = precondition.getId();
178   - final TargetTypeEnum targetType = precondition.getTargetType();
179   - final BigDecimal targetValue = precondition.getTargetValue();
180   - final TargetCalcTypeEnum targetCalcType = precondition.getTargetCalcType();
181 183 final BigDecimal personCount = BigDecimal.valueOf(userShops.size());
182   - final Integer startIndex = 0;
183 184 final BigDecimal condValue = precondition.getCondValue();
  185 + final Integer startIndex = 0;
184 186 final Integer endIndex = condValue.multiply(personCount).divide(BigDecimal.ONE, 0, RoundingMode.FLOOR).intValue() - 1;
185 187  
186   - String key = getPreconditionRank() + ":" + precondition.getId();
187   - BoundZSetOperations<String, String> zSetOps = stringRedisTemplate.boundZSetOps(key);
188   - stringRedisTemplate.expireAt(key, DateUtil.localDateTime2Date(LocalDateTime.now().plus(2L, ChronoUnit.HOURS)));
189   - for (EvalGroupUserShop userShop : userShops) {
190   - final BigDecimal indicatorValue = queryValue(userShop, precondition.getCodeType(), indicatorCode).orElse(BigDecimal.ZERO);
191   - BigDecimal reachValue = indicatorValue;
192   - if (!TargetTypeEnum.NO.equals(targetType)) {
193   - reachValue = calculateTargetValue(targetCalcType, targetValue, indicatorValue);
194   - }
195   - saveTargetHitLog(userShop, preconditionId, IndicatorTypeEnum.PRE, indicatorValue, reachValue);
196   - zSetOps.add(userShop.getPoolId().toString(), reachValue.doubleValue());
197   - }
  188 + //计算排名
  189 + List<EvalGroupRewardRankLog> rankLogs = calculateRankPreconditionValue(userShops, precondition);
  190 + Collections.sort(rankLogs);
  191 + commonService.calcRank(rankLogs);
  192 + saveRankLogs(preconditionId, rankLogs, RankIndicatorTypeEnum.PRE);
  193 + Map<Long, EvalGroupUserShop> poolUserShopMap = userShops.stream().collect(Collectors.toMap(EvalGroupUserShop::getPoolId,
  194 + Function.identity(), (v1, v2) -> v1));
198 195  
199 196 if (startIndex > endIndex) {
200 197 continue;
201 198 }
202 199  
203   - Map<Long, EvalGroupUserShop> userShopMap = userShops.stream().collect(Collectors.toMap(EvalGroupUserShop::getPoolId, Function.identity(), (v1, v2) -> v1));
204   - Set<ZSetOperations.TypedTuple<String>> referIdStrs = zSetOps.reverseRangeWithScores(startIndex, endIndex);
  200 + Integer _startIndex = startIndex, _endIndex = endIndex;;
  201 + List<EvalGroupRewardRankLog> matchRankLogs = rankLogs.stream().filter(rankLog -> {
  202 + return rankLog.getRank() > _startIndex && rankLog.getRank() <= _endIndex;
  203 + }).collect(Collectors.toList());
  204 +
205 205 AtomicInteger rank = new AtomicInteger(0);
206   - referIdStrs.stream().forEach(stringTypedTuple -> {
207   - EvalGroupUserShop userShop = userShopMap.get(Long.parseLong(stringTypedTuple.getValue()));
  206 + for (EvalGroupRewardRankLog rankLog : matchRankLogs) {
  207 + EvalGroupUserShop userShop = poolUserShopMap.get(rankLog.getPoolId());
208 208 if (PublicUtil.isNotEmpty(userShop)) {
209 209 List<Long> meetRankCondIds = Optional.ofNullable(userShop.getMeetRankCondIds()).orElse(new ArrayList<>());
210 210 meetRankCondIds.add(preconditionId);
211 211 userShop.setMeetRankCondIds(meetRankCondIds);
212 212 savePreHitLog(userShop, precondition, log -> {
213   - log.setReachValue(new BigDecimal(stringTypedTuple.getScore().toString()));
  213 + log.setReachValue(rankLog.getReachValue());
214 214 log.setCondValue(new BigDecimal(endIndex + 1));
215 215 log.setRank(rank.incrementAndGet());
216 216 });
217 217 }
218   - });
  218 + }
219 219 }
220 220 }
221 221  
... ... @@ -435,6 +435,100 @@ public abstract class EvalRewardBaseCalculator implements Calculator&lt;EvalGroupUs
435 435 }
436 436  
437 437 /**
  438 + * 计算排名提成参数最终值
  439 + *
  440 + * @param userShops
  441 + * @param evalGroupRewardId
  442 + * @param params
  443 + * @return
  444 + */
  445 + protected List<EvalGroupRewardRankLog> calculateRankParamValue(List<EvalGroupUserShop> userShops, Long evalGroupRewardId, List<EvalGroupRewardParam> params) {
  446 + List<EvalGroupRewardRankLog> rankLogs = Lists.newArrayListWithCapacity(userShops.size());
  447 + for (EvalGroupUserShop userShop : userShops) {
  448 + BigDecimal commissionValue = BigDecimal.ZERO;
  449 + for (EvalGroupRewardParam param: params) {
  450 + String indicatorCode = param.getCode();
  451 + boolean isCap = Boolean.TRUE.equals(param.getCap());
  452 + BigDecimal proportion = param.getProportion();
  453 + TargetTypeEnum targetType = param.getTargetType();
  454 + final BigDecimal userOriginValue = queryValue(userShop, param.getCodeType(), indicatorCode).orElse(BigDecimal.ZERO);
  455 + BigDecimal _calcValue = userOriginValue;
  456 + if (!TargetTypeEnum.NO.equals(targetType)) {
  457 + _calcValue = calculateTargetValue(param.getTargetCalcType(), param.getTargetValue(), _calcValue);
  458 + saveTargetHitLog(userShop, param.getId(), IndicatorTypeEnum.EXAMINE, userOriginValue, _calcValue);
  459 + }
  460 + if (isCap) {
  461 + _calcValue = _calcValue.compareTo(BigDecimal.ONE) > 0 ? BigDecimal.ONE : _calcValue;
  462 + }
  463 + commissionValue = commissionValue.add(proportion.multiply(_calcValue));
  464 + }
  465 + EvalGroupRewardRankLog rankLog = EvalGroupRewardRankLog.builder()
  466 + .poolId(userShop.getPoolId())
  467 + .scopeType(userShop.getScopeType())
  468 + .referId(evalGroupRewardId)
  469 + .targetType(RankIndicatorTypeEnum.REWARD_COMMISSION)
  470 + .value(commissionValue)
  471 + .reachValue(commissionValue)
  472 + .dataDate(userShop.getDataDate())
  473 + .groupId(userShop.getGroupId())
  474 + .build();
  475 + rankLogs.add(rankLog);
  476 + }
  477 + return rankLogs;
  478 + }
  479 +
  480 + /**
  481 + * 计算排名条件最终值
  482 + *
  483 + * @param userShops
  484 + * @param precondition
  485 + * @return
  486 + */
  487 + protected List<EvalGroupRewardRankLog> calculateRankPreconditionValue(List<EvalGroupUserShop> userShops, EvalGroupRewardPrecondition precondition) {
  488 + final String indicatorCode = precondition.getCode();
  489 + final Long preconditionId = precondition.getId();
  490 + final TargetTypeEnum targetType = precondition.getTargetType();
  491 + final BigDecimal targetValue = precondition.getTargetValue();
  492 + final TargetCalcTypeEnum targetCalcType = precondition.getTargetCalcType();
  493 +
  494 + List<EvalGroupRewardRankLog> rankLogs = Lists.newArrayListWithCapacity(userShops.size());
  495 + for (EvalGroupUserShop userShop : userShops) {
  496 + final BigDecimal indicatorValue = queryValue(userShop, precondition.getCodeType(), indicatorCode).orElse(BigDecimal.ZERO);
  497 + BigDecimal reachValue = indicatorValue;
  498 + if (!TargetTypeEnum.NO.equals(targetType)) {
  499 + reachValue = calculateTargetValue(targetCalcType, targetValue, indicatorValue);
  500 + }
  501 +
  502 + EvalGroupRewardRankLog rankLog = EvalGroupRewardRankLog.builder()
  503 + .poolId(userShop.getPoolId())
  504 + .scopeType(userShop.getScopeType())
  505 + .referId(preconditionId)
  506 + .targetType(RankIndicatorTypeEnum.PRE)
  507 + .value(indicatorValue)
  508 + .reachValue(reachValue)
  509 + .dataDate(userShop.getDataDate())
  510 + .groupId(userShop.getGroupId())
  511 + .build();
  512 + rankLogs.add(rankLog);
  513 + }
  514 + return rankLogs;
  515 + }
  516 +
  517 + public void saveRankLogs(Long evalGroupRewardId, List<EvalGroupRewardRankLog> rankLogs, RankIndicatorTypeEnum targetType) {
  518 + Set<Long> poolIds = rankLogs.stream().map(EvalGroupRewardRankLog::getPoolId).collect(Collectors.toSet());
  519 + EvalGroupRewardRankLog rankLog = rankLogs.stream().findFirst().get();
  520 + evalGroupRewardRankLogService.remove(Wrappers.<EvalGroupRewardRankLog>lambdaQuery()
  521 + .in(EvalGroupRewardRankLog::getPoolId, poolIds)
  522 + .eq(EvalGroupRewardRankLog::getScopeType, rankLog.getScopeType())
  523 + .eq(EvalGroupRewardRankLog::getReferId, evalGroupRewardId)
  524 + .eq(EvalGroupRewardRankLog::getTargetType, targetType)
  525 + .eq(EvalGroupRewardRankLog::getGroupId, rankLog.getGroupId())
  526 + );
  527 +
  528 + evalGroupRewardRankLogService.saveBatch(rankLogs);
  529 + }
  530 +
  531 + /**
438 532 * 初始化奖惩值
439 533 *
440 534 * @param userShops
... ...
fw-morax-service/src/main/java/cn/fw/morax/service/biz/calculator/eval/reward/EvalRewardRankCalculator.java
1 1 package cn.fw.morax.service.biz.calculator.eval.reward;
2 2  
3   -import cn.fw.morax.common.utils.DateUtil;
4 3 import cn.fw.morax.common.utils.PublicUtil;
5 4 import cn.fw.morax.domain.bo.eval.EvalGroupUserShop;
6   -import cn.fw.morax.domain.db.eval.EvalGroupReward;
7   -import cn.fw.morax.domain.db.eval.EvalGroupRewardLadders;
8   -import cn.fw.morax.domain.db.eval.EvalGroupRewardParam;
9   -import cn.fw.morax.domain.db.eval.EvalGroupRewardPrecondition;
  5 +import cn.fw.morax.domain.db.eval.*;
10 6 import cn.fw.morax.domain.enums.EvalRewardCalMethodEnum;
11 7 import cn.fw.morax.domain.enums.ParamTypeEnum;
  8 +import cn.fw.morax.domain.enums.RankIndicatorTypeEnum;
12 9 import cn.fw.morax.domain.enums.RankTypeEnum;
  10 +import cn.fw.morax.service.biz.CommonService;
13 11 import lombok.Getter;
14 12 import lombok.RequiredArgsConstructor;
15 13 import lombok.extern.slf4j.Slf4j;
16 14 import org.springframework.beans.factory.annotation.Value;
17   -import org.springframework.data.redis.core.BoundZSetOperations;
18 15 import org.springframework.data.redis.core.StringRedisTemplate;
19 16 import org.springframework.stereotype.Component;
20 17 import org.springframework.util.CollectionUtils;
21 18  
22 19 import java.math.BigDecimal;
23 20 import java.math.RoundingMode;
24   -import java.time.LocalDate;
25   -import java.time.LocalDateTime;
26   -import java.time.temporal.ChronoUnit;
27   -import java.util.HashMap;
28   -import java.util.List;
29   -import java.util.Map;
30   -import java.util.Set;
  21 +import java.util.*;
  22 +import java.util.function.Function;
  23 +import java.util.stream.Collectors;
31 24  
32 25 /**
33 26 * @author jiangchao
... ... @@ -40,6 +33,7 @@ import java.util.Set;
40 33 public class EvalRewardRankCalculator extends EvalRewardBaseCalculator {
41 34  
42 35 private final StringRedisTemplate stringRedisTemplate;
  36 + private final CommonService commonService;
43 37  
44 38 @Value("${spring.cache.custom.global-prefix}:eval:reward:rank")
45 39 @Getter
... ... @@ -70,48 +64,45 @@ public class EvalRewardRankCalculator extends EvalRewardBaseCalculator {
70 64 return;
71 65 }
72 66  
73   - BoundZSetOperations<String, String> zSetOps = stringRedisTemplate.boundZSetOps(key);
74   - stringRedisTemplate.expireAt(key, DateUtil.localDateTime2Date(LocalDateTime.now().plus(2L, ChronoUnit.HOURS)));
75   -
76   - Map<String, EvalGroupUserShop> rewardObjectBOMap = new HashMap<>();
77   - Map<String, BigDecimal> referCommonMap = new HashMap<>();
78   - for (EvalGroupUserShop rewardObject : userShops) {
79   - BigDecimal commissionValue = calculateParamValue(rewardObject, params);
80   - zSetOps.add(rewardObject.getReferId().toString(), commissionValue.doubleValue());
81   -
82   - referCommonMap.put(rewardObject.getReferId().toString(), commissionValue);
83   - rewardObjectBOMap.put(rewardObject.getReferId().toString(), rewardObject);
84   - }
  67 + //计算排名
  68 + List<EvalGroupRewardRankLog> rankLogs = calculateRankParamValue(userShops, evalGroupRewardId, params);
  69 + Collections.sort(rankLogs);
  70 + commonService.calcRank(rankLogs);
  71 + saveRankLogs(evalGroupRewardId, rankLogs, RankIndicatorTypeEnum.REWARD_COMMISSION);
  72 + Map<Long, EvalGroupUserShop> poolUserShopMap = userShops.stream().collect(Collectors.toMap(EvalGroupUserShop::getPoolId,
  73 + Function.identity(), (v1, v2) -> v1));
85 74  
  75 + //计算金额
86 76 final BigDecimal personCount = BigDecimal.valueOf(userShops.size());
87 77 List<EvalGroupRewardLadders> ladders = queryRewardLadders(evalGroupRewardId);
88 78 for (EvalGroupRewardLadders ladder : ladders) {
89 79 final BigDecimal money = ladder.getMoney();
90   - Integer startIndex = null;
91   - Integer endIndex = null;
  80 + Integer startIndex = ladder.getLower().intValue() - 1;
  81 + Integer endIndex = ladder.getUpper().intValue();
92 82  
93 83 if (RankTypeEnum.PERCENT.equals(rankType)) {
94 84 startIndex = ladder.getLower().multiply(personCount).divide(BigDecimal.ONE, 0, RoundingMode.FLOOR).intValue();
95   - endIndex = ladder.getUpper().multiply(personCount).divide(BigDecimal.ONE, 0, RoundingMode.FLOOR).intValue() - 1;
96   - } else {
97   - startIndex = ladder.getLower().intValue() - 1;
98   - endIndex = ladder.getUpper().intValue()- 1;
  85 + endIndex = ladder.getUpper().multiply(personCount).divide(BigDecimal.ONE, 0, RoundingMode.FLOOR).intValue();
99 86 }
100 87  
101 88 if (startIndex > endIndex) {
102 89 continue;
103 90 }
104 91  
105   - Set<String> referIdStrs = zSetOps.reverseRange(startIndex, endIndex);
106   - for (String referIdStr : referIdStrs) {
107   - EvalGroupUserShop userShop = rewardObjectBOMap.get(referIdStr);
  92 + Integer _startIndex = startIndex, _endIndex = endIndex;;
  93 + List<EvalGroupRewardRankLog> matchRankLogs = rankLogs.stream().filter(rankLog -> {
  94 + return rankLog.getRank() > _startIndex && rankLog.getRank() <= _endIndex;
  95 + }).collect(Collectors.toList());
  96 +
  97 + for (EvalGroupRewardRankLog rankLog : matchRankLogs) {
  98 + EvalGroupUserShop userShop = poolUserShopMap.get(rankLog.getPoolId());
108 99 boolean examined = examinePrecondition(userShop, preconditions);
109 100 if (!examined) {
110 101 userShop.setEvalGroupRewardAmount(BigDecimal.ZERO);
111 102 continue;
112 103 }
113 104 userShop.setEvalGroupRewardAmount(money);
114   - BigDecimal hitCommissionValue = referCommonMap.get(referIdStr);
  105 + BigDecimal hitCommissionValue = rankLog.getReachValue();
115 106 clearProjectHitLog(evalGroupRewardId, userShop);
116 107 saveProjectHitLog(evalGroupRewardId, userShop, log -> {
117 108 log.setRewardValue(money);
... ...
fw-morax-service/src/main/java/cn/fw/morax/service/biz/calculator/kpi/KpiAbsBaseCalculator.java
... ... @@ -8,19 +8,19 @@ import cn.fw.morax.domain.enums.TargetCalcTypeEnum;
8 8 import cn.fw.morax.domain.enums.TargetTypeEnum;
9 9 import cn.fw.morax.service.biz.calculator.Calculator;
10 10 import cn.fw.morax.service.data.kpi.*;
  11 +import com.alibaba.fastjson.JSON;
11 12 import com.alibaba.fastjson.JSONObject;
12 13 import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
13 14 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  15 +import com.google.common.base.Strings;
14 16 import lombok.extern.slf4j.Slf4j;
  17 +import org.apache.commons.lang3.StringUtils;
15 18 import org.springframework.beans.factory.annotation.Autowired;
16 19  
17 20 import java.math.BigDecimal;
18 21 import java.math.RoundingMode;
19 22 import java.time.LocalDate;
20   -import java.util.ArrayList;
21   -import java.util.List;
22   -import java.util.Objects;
23   -import java.util.Optional;
  23 +import java.util.*;
24 24 import java.util.function.Consumer;
25 25  
26 26 /**
... ... @@ -47,6 +47,20 @@ public abstract class KpiAbsBaseCalculator implements Calculator&lt;KpiGroupUser, K
47 47 @Autowired
48 48 protected KpiGroupIndicatorTargetHitLogService kpiGroupIndicatorTargetHitLogService;
49 49  
  50 + public static void main(String[] args) {
  51 + Set<Long> set = new HashSet<>();
  52 + set.add(1L);
  53 + set.add(2L);
  54 + set.add(3L);
  55 + String json = JSON.toJSONString(set);
  56 + System.out.println(json);
  57 + List<Long> set2 = JSON.parseArray(json, Long.class);
  58 + System.out.println(set2.toString());
  59 + System.out.println(Arrays.toString(set2.toArray()));
  60 + String join = StringUtils.join(",", set);
  61 + System.out.println(join);
  62 + }
  63 +
50 64 /**
51 65 * 获取设置类型
52 66 *
... ...
fw-morax-service/src/main/java/cn/fw/morax/service/biz/eval/EvalGroupPoolService.java
... ... @@ -60,6 +60,7 @@ public class EvalGroupPoolService {
60 60 private final EvalGroupRewardLaddersService evalGroupRewardLaddersService;
61 61 private final EvalPoolRewardDetailService evalPoolRewardDetailService;
62 62 private final EvalGroupRewardParamService evalGroupRewardParamService;
  63 + private final EvalGroupRewardRankLogService evalGroupRewardRankLogService;
63 64 private final EvalGroupRewardHitLogService evalGroupRewardHitLogService;
64 65 private final IndicatorUserValueService indicatorUserValueService;
65 66 private final EvalIndicatorValueService evalIndicatorValueService;
... ... @@ -1226,4 +1227,39 @@ public class EvalGroupPoolService {
1226 1227 }
1227 1228 }
1228 1229  
  1230 + public List<EvalGroupRewardRankLogVO> getRewardCondRankLogs(Long preconditionId, LocalDate dataDate) {
  1231 + EvalGroupRewardPrecondition precondition = evalGroupRewardPreconditionService.getById(preconditionId);
  1232 + BV.notNull(precondition, "奖惩条件不存在");
  1233 + final DataTypeEnum dataType = precondition.getDataType();
  1234 + final TargetTypeEnum targetType = precondition.getTargetType();
  1235 + List<EvalGroupRewardRankLog> rankLogs = evalGroupRewardRankLogService.list(Wrappers.<EvalGroupRewardRankLog>lambdaQuery()
  1236 + .eq(EvalGroupRewardRankLog::getDataDate, dataDate)
  1237 + .eq(EvalGroupRewardRankLog::getReferId, preconditionId)
  1238 + .eq(EvalGroupRewardRankLog::getTargetType, RankIndicatorTypeEnum.PRE)
  1239 + .eq(EvalGroupRewardRankLog::getYn, Boolean.TRUE)
  1240 + );
  1241 + Collections.sort(rankLogs);
  1242 +
  1243 + List<EvalGroupRewardRankLogVO> rankLogVOs = PublicUtil.copyList(rankLogs, EvalGroupRewardRankLogVO.class);
  1244 + rankLogVOs.stream().forEach(rankLog -> rankLog.convertValueToPercent(dataType, targetType));
  1245 + return rankLogVOs;
  1246 + }
  1247 +
  1248 + public List<EvalGroupRewardRankLogVO> queryRewardCommissionRank(Long commissionId, LocalDate dataDate) {
  1249 +// EvalGroupRewardPrecondition precondition = evalGroupRewardPreconditionService.getById(preconditionId);
  1250 +// BV.notNull(precondition, "奖惩条件不存在");
  1251 +// final DataTypeEnum dataType = precondition.getDataType();
  1252 +// final TargetTypeEnum targetType = precondition.getTargetType();
  1253 + List<EvalGroupRewardRankLog> rankLogs = evalGroupRewardRankLogService.list(Wrappers.<EvalGroupRewardRankLog>lambdaQuery()
  1254 + .eq(EvalGroupRewardRankLog::getDataDate, dataDate)
  1255 + .eq(EvalGroupRewardRankLog::getReferId, commissionId)
  1256 + .eq(EvalGroupRewardRankLog::getTargetType, RankIndicatorTypeEnum.REWARD_COMMISSION)
  1257 + .eq(EvalGroupRewardRankLog::getYn, Boolean.TRUE)
  1258 + );
  1259 + Collections.sort(rankLogs);
  1260 +
  1261 + List<EvalGroupRewardRankLogVO> rankLogVOs = PublicUtil.copyList(rankLogs, EvalGroupRewardRankLogVO.class);
  1262 +// rankLogVOs.stream().forEach(rankLog -> rankLog.convertValueToPercent(dataType, targetType));
  1263 + return rankLogVOs;
  1264 + }
1229 1265 }
... ...
fw-morax-service/src/main/java/cn/fw/morax/service/data/eval/EvalGroupRewardRankLogService.java 0 → 100644
  1 +package cn.fw.morax.service.data.eval;
  2 +
  3 +
  4 +import cn.fw.morax.domain.db.eval.EvalGroupRewardRankLog;
  5 +import cn.fw.morax.domain.db.eval.EvalGroupRewardTargetHitLog;
  6 +import cn.fw.morax.domain.enums.EvalScopeEnum;
  7 +import cn.fw.morax.domain.enums.IndicatorTypeEnum;
  8 +import cn.fw.morax.domain.vo.eval.EvalGroupRewardTargetHitLogVO;
  9 +import com.baomidou.mybatisplus.extension.service.IService;
  10 +
  11 +import java.time.YearMonth;
  12 +import java.util.List;
  13 +import java.util.Set;
  14 +
  15 +/**
  16 + * <p>
  17 + * 考评奖惩 服务类
  18 + * </p>
  19 + *
  20 + * @author jiangchao
  21 + * @since 2022-12-09
  22 + */
  23 +public interface EvalGroupRewardRankLogService extends IService<EvalGroupRewardRankLog> {
  24 +
  25 +
  26 +}
... ...
fw-morax-service/src/main/java/cn/fw/morax/service/data/eval/impl/EvalGroupRewardRankLogServiceImpl.java 0 → 100644
  1 +package cn.fw.morax.service.data.eval.impl;
  2 +
  3 +
  4 +import cn.fw.morax.dao.eval.EvalGroupRewardRankLogDao;
  5 +import cn.fw.morax.dao.eval.EvalGroupRewardTargetHitLogDao;
  6 +import cn.fw.morax.domain.db.eval.EvalGroupRewardRankLog;
  7 +import cn.fw.morax.domain.db.eval.EvalGroupRewardTargetHitLog;
  8 +import cn.fw.morax.domain.enums.EvalScopeEnum;
  9 +import cn.fw.morax.domain.enums.IndicatorTypeEnum;
  10 +import cn.fw.morax.domain.vo.eval.EvalGroupRewardTargetHitLogVO;
  11 +import cn.fw.morax.service.data.eval.EvalGroupRewardRankLogService;
  12 +import cn.fw.morax.service.data.eval.EvalGroupRewardTargetHitLogService;
  13 +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  14 +import org.springframework.stereotype.Service;
  15 +
  16 +import java.time.YearMonth;
  17 +import java.util.List;
  18 +import java.util.Set;
  19 +
  20 +/**
  21 + * <p>
  22 + * 考评指标达成目标记录 服务实现类
  23 + * </p>
  24 + *
  25 + * @author jiangchao
  26 + * @since 2022-12-09
  27 + */
  28 +@Service
  29 +public class EvalGroupRewardRankLogServiceImpl
  30 + extends ServiceImpl<EvalGroupRewardRankLogDao, EvalGroupRewardRankLog>
  31 + implements EvalGroupRewardRankLogService {
  32 +
  33 +}
... ...