Commit 97c9de51d61d4b4d3e7b5ba77718f36c1c22d261
1 parent
beac6c98
feature(*): 审批修改
审批修改
Showing
9 changed files
with
136 additions
and
71 deletions
fw-morax-domain/src/main/java/cn/fw/morax/domain/bo/eval/EvalGroupUserShop.java
... | ... | @@ -7,6 +7,7 @@ import lombok.*; |
7 | 7 | import java.math.BigDecimal; |
8 | 8 | import java.time.LocalDate; |
9 | 9 | import java.util.Date; |
10 | +import java.util.List; | |
10 | 11 | |
11 | 12 | /** |
12 | 13 | * @author : kurisu |
... | ... | @@ -81,4 +82,9 @@ public class EvalGroupUserShop { |
81 | 82 | */ |
82 | 83 | private BigDecimal evalGroupRewardAmount; |
83 | 84 | |
85 | + /** | |
86 | + * 满足排名条件的条件id | |
87 | + */ | |
88 | + private List<Long> meetRankCondIds; | |
89 | + | |
84 | 90 | } | ... | ... |
fw-morax-domain/src/main/java/cn/fw/morax/domain/db/eval/EvalGroupRewardPrecondition.java
... | ... | @@ -97,8 +97,12 @@ public class EvalGroupRewardPrecondition extends BaseAuditableTimeEntity<EvalGro |
97 | 97 | * 转换为小数 |
98 | 98 | */ |
99 | 99 | public void dividePercent() { |
100 | - if (PublicUtil.isNotEmpty(this.getDataType()) && DataTypeEnum.RATIO.equals(this.getDataType())) { | |
100 | + if (ConditionTypeEnum.RANK.equals(this.getCondType())) { | |
101 | 101 | this.setCondValue(this.getCondValue().divide(Constant.ONE_HUNDRED, 4, RoundingMode.HALF_UP)); |
102 | + } else { | |
103 | + if (PublicUtil.isNotEmpty(this.getDataType()) && DataTypeEnum.RATIO.equals(this.getDataType())) { | |
104 | + this.setCondValue(this.getCondValue().divide(Constant.ONE_HUNDRED, 4, RoundingMode.HALF_UP)); | |
105 | + } | |
102 | 106 | } |
103 | 107 | if (PublicUtil.isNotEmpty(this.getTargetType()) && TargetTypeEnum.RATIO.equals(this.getTargetType())) { |
104 | 108 | this.setTargetValue(this.getTargetValue().divide(Constant.ONE_HUNDRED, 4, RoundingMode.HALF_UP)); | ... | ... |
fw-morax-domain/src/main/java/cn/fw/morax/domain/vo/eval/EvalGroupRewardPreconditionVO.java
1 | 1 | package cn.fw.morax.domain.vo.eval; |
2 | 2 | |
3 | 3 | import cn.fw.morax.common.constant.Constant; |
4 | +import cn.fw.morax.common.utils.PublicUtil; | |
4 | 5 | import cn.fw.morax.domain.enums.*; |
5 | 6 | import com.baomidou.mybatisplus.annotation.TableLogic; |
6 | 7 | import com.baomidou.mybatisplus.annotation.TableName; |
... | ... | @@ -8,6 +9,7 @@ import lombok.Data; |
8 | 9 | import lombok.EqualsAndHashCode; |
9 | 10 | |
10 | 11 | import java.math.BigDecimal; |
12 | +import java.math.RoundingMode; | |
11 | 13 | |
12 | 14 | /** |
13 | 15 | * <p> |
... | ... | @@ -112,12 +114,18 @@ public class EvalGroupRewardPreconditionVO{ |
112 | 114 | * 转换为百分数展示 |
113 | 115 | */ |
114 | 116 | public void convertValueToPercent(){ |
117 | + if (ConditionTypeEnum.RANK.equals(this.getCondType())) { | |
118 | + this.setCondValue(this.getCondValue().multiply(Constant.ONE_HUNDRED)); | |
119 | + } else { | |
120 | + if (PublicUtil.isNotEmpty(this.getDataType()) && DataTypeEnum.RATIO.equals(this.getDataType())) { | |
121 | + this.setCondValue(this.getCondValue().multiply(Constant.ONE_HUNDRED)); | |
122 | + } | |
123 | + } | |
115 | 124 | if (TargetTypeEnum.RATIO.equals(this.getTargetType())) { |
116 | 125 | this.setTargetValue(this.getTargetValue().multiply(Constant.ONE_HUNDRED)); |
117 | 126 | } |
118 | 127 | if (DataTypeEnum.RATIO.equals(this.getDataType())) { |
119 | 128 | this.setIndicatorValue(this.getIndicatorValue().multiply(Constant.ONE_HUNDRED)); |
120 | - this.setCondValue(this.getCondValue().multiply(Constant.ONE_HUNDRED)); | |
121 | 129 | } |
122 | 130 | //有目标 |
123 | 131 | if (! TargetTypeEnum.NO.equals(this.getTargetType())) { | ... | ... |
fw-morax-service/src/main/java/cn/fw/morax/service/biz/calculator/Calculator.java
... | ... | @@ -27,4 +27,12 @@ public interface Calculator<T, P, R> { |
27 | 27 | * @param param2 |
28 | 28 | */ |
29 | 29 | default void calculateGroup(List<T> params, P param2){}; |
30 | + | |
31 | + /** | |
32 | + * 计算排名条件数据 | |
33 | + * | |
34 | + * @param params | |
35 | + * @param param2 | |
36 | + */ | |
37 | + default void calculateRankPrecondition(List<T> params, P param2){}; | |
30 | 38 | } | ... | ... |
fw-morax-service/src/main/java/cn/fw/morax/service/biz/calculator/eval/reward/EvalRewardBaseCalculator.java
1 | 1 | package cn.fw.morax.service.biz.calculator.eval.reward; |
2 | 2 | |
3 | +import cn.fw.morax.common.utils.DateUtil; | |
3 | 4 | import cn.fw.morax.common.utils.PublicUtil; |
4 | 5 | import cn.fw.morax.domain.bo.eval.EvalGroupUserShop; |
5 | 6 | import cn.fw.morax.domain.db.eval.*; |
... | ... | @@ -12,14 +13,20 @@ import cn.fw.morax.service.data.kpi.IndicatorUserValueService; |
12 | 13 | import com.alibaba.fastjson.JSONObject; |
13 | 14 | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
14 | 15 | import com.baomidou.mybatisplus.core.toolkit.Wrappers; |
16 | +import lombok.Getter; | |
15 | 17 | import lombok.extern.slf4j.Slf4j; |
16 | 18 | import org.springframework.beans.factory.annotation.Autowired; |
19 | +import org.springframework.beans.factory.annotation.Value; | |
20 | +import org.springframework.data.redis.core.BoundZSetOperations; | |
21 | +import org.springframework.data.redis.core.StringRedisTemplate; | |
17 | 22 | import org.springframework.transaction.annotation.Transactional; |
18 | 23 | import org.springframework.util.CollectionUtils; |
19 | 24 | |
20 | 25 | import java.math.BigDecimal; |
21 | 26 | import java.math.RoundingMode; |
22 | 27 | import java.time.LocalDate; |
28 | +import java.time.LocalDateTime; | |
29 | +import java.time.temporal.ChronoUnit; | |
23 | 30 | import java.util.*; |
24 | 31 | import java.util.function.Consumer; |
25 | 32 | |
... | ... | @@ -53,6 +60,11 @@ public abstract class EvalRewardBaseCalculator implements Calculator<EvalGroupUs |
53 | 60 | protected EvalGroupRewardLaddersService evalGroupRewardLaddersService; |
54 | 61 | @Autowired |
55 | 62 | protected EvalGroupRewardService evalGroupRewardService; |
63 | + @Autowired | |
64 | + private StringRedisTemplate stringRedisTemplate; | |
65 | + @Value("${spring.cache.custom.global-prefix}:eval:reward:cond:rank") | |
66 | + @Getter | |
67 | + private String preconditionRank; | |
56 | 68 | |
57 | 69 | /** |
58 | 70 | * 获取设置类型 |
... | ... | @@ -67,17 +79,6 @@ public abstract class EvalRewardBaseCalculator implements Calculator<EvalGroupUs |
67 | 79 | * @param evalGroupRewardId |
68 | 80 | * @return |
69 | 81 | */ |
70 | - protected EvalGroupReward queryEvalGroupReward(Long evalGroupRewardId) { | |
71 | - return evalGroupRewardService.getById(evalGroupRewardId); | |
72 | - } | |
73 | - | |
74 | - | |
75 | - /** | |
76 | - * 查询前置条件 | |
77 | - * | |
78 | - * @param evalGroupRewardId | |
79 | - * @return | |
80 | - */ | |
81 | 82 | protected List<EvalGroupRewardPrecondition> queryPrecondition(Long evalGroupRewardId) { |
82 | 83 | List<EvalGroupRewardPrecondition> preList = evalGroupRewardPreconditionService.list(Wrappers.<EvalGroupRewardPrecondition>lambdaQuery() |
83 | 84 | .eq(EvalGroupRewardPrecondition::getEvalGroupRewardId, evalGroupRewardId) |
... | ... | @@ -88,59 +89,19 @@ public abstract class EvalRewardBaseCalculator implements Calculator<EvalGroupUs |
88 | 89 | } |
89 | 90 | |
90 | 91 | /** |
91 | - * 查询指标配置 | |
92 | + * 查询前置条件 | |
92 | 93 | * |
93 | 94 | * @param evalGroupRewardId |
94 | 95 | * @return |
95 | 96 | */ |
96 | - protected List<EvalGroupRewardParam> queryParam(Long evalGroupRewardId) { | |
97 | - List<EvalGroupRewardParam> list = evalGroupRewardParamService.list(Wrappers.<EvalGroupRewardParam>lambdaQuery() | |
98 | - .eq(EvalGroupRewardParam::getEvalGroupRewardId, evalGroupRewardId) | |
99 | - .eq(EvalGroupRewardParam::getYn, Boolean.TRUE) | |
100 | - ); | |
101 | - return Optional.ofNullable(list).orElse(new ArrayList<>()); | |
102 | - } | |
103 | - | |
104 | - /** | |
105 | - * 查询人员指标值 | |
106 | - * | |
107 | - * @param userId | |
108 | - * @param groupId | |
109 | - * @param dataDate | |
110 | - * @param indicatorCode | |
111 | - * @return | |
112 | - */ | |
113 | - protected IndicatorUserValue queryUserValue(Long userId, Long groupId, LocalDate dataDate, String indicatorCode) { | |
114 | - return indicatorUserValueService.getOne(Wrappers.<IndicatorUserValue>lambdaQuery() | |
115 | - .eq(IndicatorUserValue::getUserId, userId) | |
116 | - .eq(IndicatorUserValue::getDimensionType, DimensionTypeEnum.STAFF) | |
117 | - .eq(IndicatorUserValue::getIndicatorCode, indicatorCode) | |
118 | - .eq(IndicatorUserValue::getDataDate, dataDate) | |
119 | - .eq(IndicatorUserValue::getYn, Boolean.TRUE) | |
120 | - .eq(IndicatorUserValue::getGroupId, groupId) | |
121 | - , Boolean.FALSE | |
122 | - ); | |
123 | - } | |
124 | - | |
125 | - /** | |
126 | - * 查询门店指标值 | |
127 | - * | |
128 | - * @param shopId | |
129 | - * @param groupId | |
130 | - * @param dataDate | |
131 | - * @param indicatorCode | |
132 | - * @return | |
133 | - */ | |
134 | - protected IndicatorUserValue queryShopValue(Long shopId, Long groupId, LocalDate dataDate, String indicatorCode) { | |
135 | - return indicatorUserValueService.getOne(Wrappers.<IndicatorUserValue>lambdaQuery() | |
136 | - .eq(IndicatorUserValue::getShopId, shopId) | |
137 | - .eq(IndicatorUserValue::getDimensionType, DimensionTypeEnum.SHOP) | |
138 | - .eq(IndicatorUserValue::getIndicatorCode, indicatorCode) | |
139 | - .eq(IndicatorUserValue::getDataDate, dataDate) | |
140 | - .eq(IndicatorUserValue::getYn, Boolean.TRUE) | |
141 | - .eq(IndicatorUserValue::getGroupId, groupId) | |
142 | - , Boolean.FALSE | |
97 | + protected List<EvalGroupRewardPrecondition> queryRankPrecondition(Long evalGroupRewardId) { | |
98 | + List<EvalGroupRewardPrecondition> preList = evalGroupRewardPreconditionService.list(Wrappers.<EvalGroupRewardPrecondition>lambdaQuery() | |
99 | + .eq(EvalGroupRewardPrecondition::getEvalGroupRewardId, evalGroupRewardId) | |
100 | + .eq(EvalGroupRewardPrecondition::getCondType, ConditionTypeEnum.RANK) | |
101 | + .eq(EvalGroupRewardPrecondition::getYn, Boolean.TRUE) | |
102 | + .orderByAsc(EvalGroupRewardPrecondition::getSort) | |
143 | 103 | ); |
104 | + return Optional.ofNullable(preList).orElse(new ArrayList<>()); | |
144 | 105 | } |
145 | 106 | |
146 | 107 | /** |
... | ... | @@ -169,6 +130,9 @@ public abstract class EvalRewardBaseCalculator implements Calculator<EvalGroupUs |
169 | 130 | return Boolean.TRUE; |
170 | 131 | } |
171 | 132 | for (EvalGroupRewardPrecondition precondition : preconditions) { |
133 | + if (ConditionTypeEnum.RANK.equals(precondition.getCondType())) { | |
134 | + return userShop.getMeetRankCondIds().contains(precondition.getId()); | |
135 | + } | |
172 | 136 | String indicatorCode = precondition.getCode(); |
173 | 137 | final BigDecimal indicatorValue = queryValue(userShop, precondition.getCodeType(), indicatorCode).orElse(BigDecimal.ZERO); |
174 | 138 | BigDecimal userValue = indicatorValue; |
... | ... | @@ -187,6 +151,61 @@ public abstract class EvalRewardBaseCalculator implements Calculator<EvalGroupUs |
187 | 151 | return Boolean.TRUE; |
188 | 152 | } |
189 | 153 | |
154 | + @Override | |
155 | + public void calculateRankPrecondition(List<EvalGroupUserShop> params, EvalGroupReward reward) { | |
156 | + List<EvalGroupRewardPrecondition> rankPreconditions = queryRankPrecondition(reward.getId()); | |
157 | + examineRankPreconditions(params, rankPreconditions); | |
158 | + } | |
159 | + | |
160 | + /** | |
161 | + * 校验前置条件 | |
162 | + * | |
163 | + * @return | |
164 | + */ | |
165 | + protected void examineRankPreconditions(List<EvalGroupUserShop> userShops, List<EvalGroupRewardPrecondition> preconditions) { | |
166 | + if (CollectionUtils.isEmpty(preconditions)) { | |
167 | + return; | |
168 | + } | |
169 | + for (EvalGroupRewardPrecondition precondition : preconditions) { | |
170 | + final String indicatorCode = precondition.getCode(); | |
171 | + final Long preconditionId = precondition.getId(); | |
172 | + final TargetTypeEnum targetType = precondition.getTargetType(); | |
173 | + final BigDecimal targetValue = precondition.getTargetValue(); | |
174 | + final TargetCalcTypeEnum targetCalcType = precondition.getTargetCalcType(); | |
175 | + | |
176 | + String key = getPreconditionRank() + ":" + precondition.getId(); | |
177 | + BoundZSetOperations<String, String> zSetOps = stringRedisTemplate.boundZSetOps(key); | |
178 | + stringRedisTemplate.expireAt(key, DateUtil.localDateTime2Date(LocalDateTime.now().plus(2L, ChronoUnit.HOURS))); | |
179 | + for (EvalGroupUserShop userShop : userShops) { | |
180 | + final BigDecimal indicatorValue = queryValue(userShop, precondition.getCodeType(), indicatorCode).orElse(BigDecimal.ZERO); | |
181 | + BigDecimal reachValue = indicatorValue; | |
182 | + if (!TargetTypeEnum.NO.equals(targetType)) { | |
183 | + reachValue = calculateTargetValue(targetCalcType, targetValue, indicatorValue); | |
184 | + saveTargetHitLog(userShop, preconditionId, IndicatorTypeEnum.PRE, indicatorValue, reachValue); | |
185 | + } | |
186 | + zSetOps.add(userShop.getPoolId().toString(), reachValue.doubleValue()); | |
187 | + } | |
188 | + BigDecimal condValue = precondition.getCondValue(); | |
189 | + final BigDecimal personCount = BigDecimal.valueOf(userShops.size()); | |
190 | + final Integer startIndex = 0; | |
191 | + final Integer endIndex = condValue.multiply(personCount).divide(BigDecimal.ONE, 0, RoundingMode.FLOOR).intValue() - 1; | |
192 | + | |
193 | + if (startIndex > endIndex) { | |
194 | + continue; | |
195 | + } | |
196 | + | |
197 | + Set<String> referIdStrs = zSetOps.reverseRange(startIndex, endIndex); | |
198 | + for (EvalGroupUserShop userShop : userShops) { | |
199 | + if (referIdStrs.contains(userShop.getPoolId().toString())) { | |
200 | + List<Long> meetRankCondIds = PublicUtil.isNotEmpty(userShop.getMeetRankCondIds()) ? | |
201 | + userShop.getMeetRankCondIds() : new ArrayList<>(); | |
202 | + meetRankCondIds.add(preconditionId); | |
203 | + userShop.setMeetRankCondIds(meetRankCondIds); | |
204 | + } | |
205 | + } | |
206 | + } | |
207 | + } | |
208 | + | |
190 | 209 | /** |
191 | 210 | * 查询提成指标项 |
192 | 211 | * | ... | ... |
fw-morax-service/src/main/java/cn/fw/morax/service/biz/calculator/eval/reward/EvalRewardFixationCalculator.java
fw-morax-service/src/main/java/cn/fw/morax/service/biz/calculator/eval/reward/EvalRewardProportionCalculator.java
... | ... | @@ -33,15 +33,6 @@ import java.util.Map; |
33 | 33 | @RequiredArgsConstructor |
34 | 34 | public class EvalRewardProportionCalculator extends EvalRewardBaseCalculator { |
35 | 35 | |
36 | - private final EvalGroupService evalGroupService; | |
37 | - private final EvalGroupUserService evalGroupUserService; | |
38 | - private final DistributedLocker distributedLocker; | |
39 | - private final StringRedisTemplate stringRedisTemplate; | |
40 | - | |
41 | - @Value("${spring.cache.custom.global-prefix}:eval:reward:totalCommission") | |
42 | - @Getter | |
43 | - private String commissionTotalValue; | |
44 | - | |
45 | 36 | @Override |
46 | 37 | public EvalRewardCalMethodEnum getCalMethod() { |
47 | 38 | return EvalRewardCalMethodEnum.TOTAL_PROPORTION; | ... | ... |
fw-morax-service/src/main/java/cn/fw/morax/service/biz/eval/EvalCalculateService.java
... | ... | @@ -303,6 +303,34 @@ public class EvalCalculateService { |
303 | 303 | userShop.setScore(totalScore); |
304 | 304 | } |
305 | 305 | |
306 | + /** | |
307 | + * 计算奖惩条件 | |
308 | + * | |
309 | + * @param rewardDetails | |
310 | + */ | |
311 | + private void calcRewardRankCond(List<EvalGroupReward> rewards, List<EvalGroupUserShop> userShops, List<EvalPoolRewardDetail> rewardDetails) { | |
312 | + List<EvalGroupReward> totalCalcuRewards = rewards.stream() | |
313 | + .filter(reward -> EvalRewardCalMethodEnum.RANK.equals(reward.getCalMethod()) || | |
314 | + EvalRewardCalMethodEnum.TOTAL_PROPORTION.equals(reward.getCalMethod())) | |
315 | + .collect(Collectors.toList()); | |
316 | + | |
317 | + for (EvalGroupReward evalGroupReward : totalCalcuRewards) { | |
318 | + final String rewardProjectName = evalGroupReward.getName(); | |
319 | + EvalRewardBaseCalculator calculator = calculatorRewardMap.get(evalGroupReward.getCalMethod()); | |
320 | + if (Objects.isNull(calculator)) { | |
321 | + log.error("[{}_{}]计算器不存在", evalGroupReward.getId(), rewardProjectName); | |
322 | + return; | |
323 | + } | |
324 | + calculator.calculateGroup(userShops, evalGroupReward); | |
325 | + for (EvalGroupUserShop userShop : userShops) { | |
326 | + EvalPoolRewardDetail detail = createDetail(userShop); | |
327 | + detail.setScopeType(userShop.getScopeType()); | |
328 | + detail.setEvalGroupRewardId(evalGroupReward.getId()); | |
329 | + detail.setAmount(Optional.ofNullable(userShop.getEvalGroupRewardAmount()).orElse(BigDecimal.ZERO)); | |
330 | + rewardDetails.add(detail); | |
331 | + } | |
332 | + } | |
333 | + } | |
306 | 334 | |
307 | 335 | /** |
308 | 336 | * 计算绩效金额 | ... | ... |
fw-morax-service/src/main/java/cn/fw/morax/service/biz/eval/EvalGroupBizService.java