Blame view

fw-morax-service/src/main/java/cn/fw/morax/service/biz/eval/EvalGroupUserBizService.java 14.3 KB
ac84063e   姜超   feature(*): 考评人员
1
2
3
  package cn.fw.morax.service.biz.eval;
  
  import cn.fw.ehr.sdk.api.enums.StaffStatusEnum;
ac84063e   姜超   feature(*): 考评人员
4
5
6
  import cn.fw.morax.common.utils.PublicUtil;
  import cn.fw.morax.domain.db.eval.EvalGroup;
  import cn.fw.morax.domain.db.eval.EvalGroupUser;
3cbc22e1   姜超   feature(*): 考评排名组修改
7
  import cn.fw.morax.domain.dto.query.ShopsPostsQueryDTO;
936e630c   姜超   feature(*): 门店奖惩分配
8
  import cn.fw.morax.domain.enums.EvalScopeEnum;
ac84063e   姜超   feature(*): 考评人员
9
  import cn.fw.morax.domain.enums.KpiIgnoreCauseEnum;
abf088aa   姜超   feature(*): 考评排名组
10
  import cn.fw.morax.domain.vo.eval.EvalGroupUserVO;
ac84063e   姜超   feature(*): 考评人员
11
12
13
  import cn.fw.morax.rpc.ehr.EhrRpcService;
  import cn.fw.morax.rpc.ehr.dto.PerformanceStaffDTO;
  import cn.fw.morax.service.data.eval.EvalGroupService;
ac84063e   姜超   feature(*): 考评人员
14
15
16
17
18
19
20
21
22
23
24
  import com.google.common.collect.Lists;
  import com.google.common.collect.Maps;
  import lombok.Getter;
  import lombok.RequiredArgsConstructor;
  import lombok.extern.slf4j.Slf4j;
  import org.springframework.beans.factory.annotation.Value;
  import org.springframework.data.redis.core.BoundValueOperations;
  import org.springframework.data.redis.core.StringRedisTemplate;
  import org.springframework.stereotype.Service;
  import org.springframework.transaction.annotation.Transactional;
  
ac84063e   姜超   feature(*): 考评人员
25
  import java.time.LocalDate;
936e630c   姜超   feature(*): 门店奖惩分配
26
  import java.time.format.DateTimeFormatter;
ac84063e   姜超   feature(*): 考评人员
27
  import java.util.*;
ac84063e   姜超   feature(*): 考评人员
28
29
  import java.util.stream.Collectors;
  
abf088aa   姜超   feature(*): 考评排名组
30
31
  import static cn.fw.common.businessvalidator.Validator.BV;
  
ac84063e   姜超   feature(*): 考评人员
32
33
34
35
36
37
38
39
40
41
  /**
   * @author jiangchao
   * @des: 考评组人员
   * @date 2023/1/12 14:40
   */
  @Service
  @Slf4j
  @RequiredArgsConstructor
  public class EvalGroupUserBizService {
  
936e630c   姜超   feature(*): 门店奖惩分配
42
43
44
      private final EvalGroupService evalGroupService;
      private final EhrRpcService ehrRpcService;
      private final StringRedisTemplate stringRedisTemplate;
ac84063e   姜超   feature(*): 考评人员
45
46
47
48
49
50
51
52
53
54
55
  
      @Value("${spring.cache.custom.global-prefix}:kpi:anticipated_date:")
      @Getter
      private String startKpiKey;
      @Value("${spring.cache.custom.global-prefix}:kpi:await_job:anticipated_date:")
      @Getter
      private String awaitJobAfterStartKpiKey;
  
      /**
       * 所有集团生效的绩效组配置
       */
f727712b   姜超   feature(*): 考评阶段指标上报
56
      public List<EvalGroup> postEffectEvalGroups(){
1a21d9d4   姜超   feature(*): 考评导入修改
57
          LocalDate queryDate = LocalDate.now().minusDays(1L);
ac84063e   姜超   feature(*): 考评人员
58
          List<EvalGroup> evalGroups = evalGroupService.getAllEffectGroups(queryDate);
f727712b   姜超   feature(*): 考评阶段指标上报
59
          if (PublicUtil.isEmpty(evalGroups)) {
936e630c   姜超   feature(*): 门店奖惩分配
60
              log.info("时间:{},没有正在生效中的考评组配置", DateTimeFormatter.ofPattern("yyyy-MM-dd").format(queryDate));
f727712b   姜超   feature(*): 考评阶段指标上报
61
              return new ArrayList<>();
ac84063e   姜超   feature(*): 考评人员
62
          }
f727712b   姜超   feature(*): 考评阶段指标上报
63
          return evalGroups;
ac84063e   姜超   feature(*): 考评人员
64
65
66
67
68
69
70
71
      }
  
      /**
       * 构建绩效组人员
       *
       * @return
       */
      @Transactional(rollbackFor = Exception.class)
6216249c   姜超   feature(*): 修改bug
72
73
      public List<EvalGroupUser> fetchBuildKpiUser(Long postId, EvalGroup evalGroup, LocalDate localDate){
          List<EvalGroupUser> evalGroupUsers = this.fetchPostUsers(postId, evalGroup.getShopIds(), localDate);
ac84063e   姜超   feature(*): 考评人员
74
  
abf088aa   姜超   feature(*): 考评排名组
75
76
          //构建考评组信息
          for (EvalGroupUser user : evalGroupUsers) {
8945afe5   姜超   feature(*): 考评保存修改
77
              user.setEvalGroupRankId(evalGroup.getEvalGroupRankId());
5e6a6922   姜超   feature(*): 筛选修改
78
              user.setEvalGroupRankStageId(evalGroup.getEvalGroupRankStageId());
abf088aa   姜超   feature(*): 考评排名组
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
              user.setEvalGroupId(evalGroup.getId());
              user.setEgc(evalGroup.getEgc());
          }
          return evalGroupUsers;
      }
  
      /**
       * 获取岗位人员
       *
       * @param postId
       * @param shopIds
       * @param dataDate
       * @return
       */
      public List<EvalGroupUser> fetchPostUsers(Long postId, List<Long> shopIds, LocalDate dataDate) {
          List<PerformanceStaffDTO> staffs = ehrRpcService.queryKpiStaff(postId, shopIds);
ac84063e   姜超   feature(*): 考评人员
95
96
97
98
99
          if (PublicUtil.isEmpty(staffs)) {
              return new ArrayList<>();
          }
          List<EvalGroupUser> result = Lists.newArrayListWithCapacity(staffs.size());
  
ac84063e   姜超   feature(*): 考评人员
100
          for (PerformanceStaffDTO staff : staffs) {
abf088aa   姜超   feature(*): 考评排名组
101
              EvalGroupUser evalGroupUser = this.convertToGroupUser(staff, dataDate);
ac84063e   姜超   feature(*): 考评人员
102
103
104
105
106
107
108
109
              //处理绩效考核数据
              this.handleStaffKpi(staff, evalGroupUser);
              result.add(evalGroupUser);
          }
          return result;
      }
  
      /**
f727712b   姜超   feature(*): 考评阶段指标上报
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
       * 获取岗位人员
       *
       * @param postIds
       * @param shopIds
       * @param dataDate
       * @return
       */
      public List<EvalGroupUser> fetchPostUsers(List<Long> postIds, List<Long> shopIds, LocalDate dataDate) {
          List<PerformanceStaffDTO> staffs = Lists.newArrayListWithCapacity(100);
          for (Long postId : postIds) {
              staffs.addAll(ehrRpcService.queryKpiStaff(postId, shopIds));
          }
          if (PublicUtil.isEmpty(staffs)) {
              return new ArrayList<>();
          }
          List<EvalGroupUser> result = Lists.newArrayListWithCapacity(staffs.size());
  
          for (PerformanceStaffDTO staff : staffs) {
              EvalGroupUser evalGroupUser = this.convertToGroupUser(staff, dataDate);
              //处理绩效考核数据
              this.handleStaffKpi(staff, evalGroupUser);
              result.add(evalGroupUser);
          }
          return result;
      }
  
      /**
8a90c0e6   姜超   feature(*): 导入修改
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
       * 构建绩效组人员
       *
       * @return
       */
      @Transactional(rollbackFor = Exception.class)
      public List<EvalGroupUser> fetchBuildImportUser(Long postId, List<Long> shopIds, LocalDate localDate){
          List<PerformanceStaffDTO> staffs = ehrRpcService.queryKpiStaff(postId, new ArrayList<>(shopIds));
          if (PublicUtil.isEmpty(staffs)) {
              return new ArrayList<>();
          }
          List<EvalGroupUser> result = Lists.newArrayListWithCapacity(staffs.size());
  
          for (PerformanceStaffDTO staff : staffs) {
              EvalGroupUser evalGroupUser = this.convertToGroupUser(staff, localDate);
              //处理绩效考核数据
              this.handleStaffKpi(staff, evalGroupUser);
              result.add(evalGroupUser);
          }
          return result;
      }
  
      /**
ac84063e   姜超   feature(*): 考评人员
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
       * 处理员工绩效考核数据
       * 试用期、转正两个月内、调岗两个月内、待岗两个月内、申请不进行绩效考核
       *
       * @param staff
       * @param evalUser
       */
      public void handleStaffKpi(PerformanceStaffDTO staff, EvalGroupUser evalUser) {
          LocalDate currentTime = LocalDate.now();
          KpiIgnoreCauseEnum ignoreCauseEnum = null;
          LocalDate startKpiDate = null;
          Long staffId = staff.getId();
          try {
              //试用期不计算绩效  绩效开始时间为试用期转正的两个月后
              if (StaffStatusEnum.PROBATION.getValue().equals(staff.getStaffStatus())) {
                  startKpiDate = PublicUtil.getKpiDateOfProbationStaff(PublicUtil.isNotEmpty(staff.getEntryDate()) ? staff.getEntryDate() : LocalDate.now());
                  ignoreCauseEnum = KpiIgnoreCauseEnum.PROBATION;
              }
  
              //转正两个月内不计算绩效  绩效开始时间为转正的两个月后
              if (StaffStatusEnum.REGULAR.getValue().equals(staff.getStaffStatus())) {
                  LocalDate regularDate = PublicUtil.isNotEmpty(staff.getRegularDate()) ? staff.getRegularDate() : staff.getEntryDate();
                  LocalDate newStartKpiDate = PublicUtil.getKpiDateOfRegularStaff(regularDate);
                  if (this.checkNewStartKpiDateValid(startKpiDate, newStartKpiDate, currentTime)) {
                      ignoreCauseEnum = KpiIgnoreCauseEnum.TURN_POSITIVE_AFTER;
                      startKpiDate = newStartKpiDate;
                  }
              }
  
              //绩效组变动不足完整2个月  绩效开始时间为获得岗位的两个月后
              LocalDate postChangeStartKpiDate = this.getStartKpiDate(staffId);
              if (PublicUtil.isNotEmpty(postChangeStartKpiDate)) {
                  if (this.checkNewStartKpiDateValid(startKpiDate, postChangeStartKpiDate, currentTime)) {
                      ignoreCauseEnum = KpiIgnoreCauseEnum.TRANSFER_NEW_POSITION_AFTER;
                      startKpiDate = postChangeStartKpiDate;
                  }
              }
  
              //主动申请不计算绩效  绩效开始时间为设置的申请开始绩效考核时间
  //            KpiStarSpecialRule specialRule = userRuleMap.get(staffId);
              //开始考核日期
  //            if (PublicUtil.isNotEmpty(specialRule) && PublicUtil.isNotEmpty(specialRule.getEarliestStartingMonthly())) {
  //                LocalDate newStartKpiDate = specialRule.getEarliestStartingMonthly();
  //                //当前时间在开始考核时间之之前    审批通过后,前面月份的绩效不纳入后续计算
  //                if (this.checkNewStartKpiDateValid(startKpiDate, newStartKpiDate, currentTime)) {
  //                    ignoreCauseEnum = KpiIgnoreCauseEnum.APPLY_NO_ASSESSMENT;
  //                    startKpiDate = newStartKpiDate;
  //                }
  //            }
  
              //待岗期间
              if (PublicUtil.isNotEmpty(staff.getAwaitJob()) && staff.getAwaitJob()) {
                  ignoreCauseEnum = KpiIgnoreCauseEnum.AWAIT_JOB_DURATION;
                  //@todo 人事系统待岗中人员没有待岗结束时间
                  startKpiDate = null;
              }
  
              //待岗结束两个月期间
              LocalDate afterAwaitJobStartKpiDate = this.getAfterAwaitJobStartKpiDate(staffId);
              if (PublicUtil.isNotEmpty(afterAwaitJobStartKpiDate) ) {
                  if (this.checkNewStartKpiDateValid(startKpiDate, afterAwaitJobStartKpiDate, currentTime)) {
                      ignoreCauseEnum = KpiIgnoreCauseEnum.AWAIT_JOB_AFTER;
                      startKpiDate = afterAwaitJobStartKpiDate;
                  }
              }
  
              if (PublicUtil.isNotEmpty(ignoreCauseEnum)) {
                  this.handleIgnoredKpiGroupUser(evalUser, ignoreCauseEnum, startKpiDate);
                  return;
              }
  
              //都未命中上面的条件就计算绩效,开始计算时间为转正两月后、获得新岗位两月后、申请开始考核时间任一
              evalUser.setIgnored(Boolean.FALSE);
          }catch (Exception e) {
              evalUser.setIgnored(Boolean.TRUE);
              log.error("处理绩效组人员数据异常,员工信息:{}", staff, e);
          }
      }
  
      /**
       * 判断新绩效生效日期 是否有效
       *
       * @param oldStartKpiDate
       * @param newStartKpiDate
       * @return
       */
      private Boolean checkNewStartKpiDateValid(LocalDate oldStartKpiDate, LocalDate newStartKpiDate, LocalDate currentTime) {
          //当前时间在生效日期之后,计算绩效
          if (currentTime.isAfter(newStartKpiDate)) {
              return Boolean.FALSE;
          }
          //旧生效时间为空  或者  新生效日期在旧生效日期之后
          if (PublicUtil.isEmpty(oldStartKpiDate) || newStartKpiDate.isAfter(oldStartKpiDate)) {
              return Boolean.TRUE;
          }
          return Boolean.FALSE;
      }
  
  
      /**
       * 处理绩效忽略数据
       *
       * @param evalUser
       * @param ignoreCauseEnum
       * @param anticipatedDate
       */
      private void handleIgnoredKpiGroupUser(EvalGroupUser evalUser, KpiIgnoreCauseEnum ignoreCauseEnum, LocalDate anticipatedDate) {
          evalUser.setIgnored(Boolean.TRUE);
          if (PublicUtil.isNotEmpty(anticipatedDate)) {
              evalUser.setAnticipatedDate(anticipatedDate);
          }
          evalUser.setIgnoreCause(ignoreCauseEnum);
          evalUser.setIgnoreCauseDesc(ignoreCauseEnum.getName());
      }
  
      /**
       * 检查员工是否在待岗保护期
       *
       * @param userId
       */
      public LocalDate getAfterAwaitJobStartKpiDate(Long userId) {
          String key = getAwaitJobAfterStartKpiKey() + userId;
          if (! stringRedisTemplate.hasKey(key)) {
              return null;
          }
          BoundValueOperations<String, String> strOps = stringRedisTemplate.boundValueOps(key);
          LocalDate startKpiDate = LocalDate.parse(strOps.get());
          LocalDate currentDate = LocalDate.now();
          //当前时间在开始计算绩效时间  之后,已经开始计算绩效
          if (currentDate.isAfter(startKpiDate)) {
              return null;
          }
          return startKpiDate;
      }
  
      /**
       * 获取开始计算绩效时间
       *
       * @param userId
       */
      public LocalDate getStartKpiDate(Long userId) {
          String key = getStartKpiKey() + userId;
          if (! stringRedisTemplate.hasKey(key)) {
              return null;
          }
          BoundValueOperations<String, String> strOps = stringRedisTemplate.boundValueOps(key);
          LocalDate startKpiDate = LocalDate.parse(strOps.get());
          LocalDate currentDate = LocalDate.now();
          //当前时间在开始计算绩效时间  之后,已经开始计算绩效
          if (currentDate.isAfter(startKpiDate)) {
              return null;
          }
          return startKpiDate;
      }
  
      /**
       * 转换员工基础信息
       *
       * @param staff
       * @return
       */
      private EvalGroupUser convertToGroupUser(PerformanceStaffDTO staff, LocalDate now){
          EvalGroupUser evalGroupUser = EvalGroupUser.builder()
                  .userId(staff.getId())
                  .userName(staff.getName())
                  .postId(staff.getPostId())
                  .postName(staff.getPostName())
                  .shopId(staff.getShopId())
                  .shopName(staff.getShopName())
                  .groupId(staff.getGroupId())
ac84063e   姜超   feature(*): 考评人员
328
                  .build();
abf088aa   姜超   feature(*): 考评排名组
329
330
331
          if (PublicUtil.isNotEmpty(now)) {
              evalGroupUser.setDataDate(now);
          }
ac84063e   姜超   feature(*): 考评人员
332
333
334
          return evalGroupUser;
      }
  
abf088aa   姜超   feature(*): 考评排名组
335
336
337
338
339
340
341
342
343
344
  
      /**
       * 查询考评组人员
       *
       * @param evalGroupId
       * @return
       */
      public List<EvalGroupUserVO> queryEvalGroupStaffs(Long evalGroupId) {
          EvalGroup evalGroup = evalGroupService.getById(evalGroupId);
          BV.notNull(evalGroup, "考评配置不存在,请重试");
f727712b   姜超   feature(*): 考评阶段指标上报
345
          List<EvalGroupUser> evalGroupUsers = this.fetchPostUsers(evalGroup.getPostIds(), evalGroup.getShopIds(), null);
abf088aa   姜超   feature(*): 考评排名组
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
          List<EvalGroupUserVO> evalGroupUserVOS = PublicUtil.copyList(evalGroupUsers, EvalGroupUserVO.class);
          return evalGroupUserVOS;
      }
  
  
      /**
       * 查询考评组排名所有人员
       *
       * @param kpiGroupIds
       * @return
       */
      public List<EvalGroupUserVO> queryRankStaffs(List<Long> kpiGroupIds) {
          List<EvalGroupUserVO> evalGroupUserVOS = Lists.newArrayListWithCapacity(100);
          for (Long kpiGroupId : kpiGroupIds) {
              evalGroupUserVOS.addAll(this.queryEvalGroupStaffs(kpiGroupId));
          }
          return evalGroupUserVOS;
      }
  
3cbc22e1   姜超   feature(*): 考评排名组修改
365
366
367
368
369
370
371
372
373
374
375
376
      /**
       * 查询考评组排名人员
       *
       * @param dto
       * @return
       */
      public List<EvalGroupUserVO> queryShopPostStaffs(ShopsPostsQueryDTO dto) {
          List<EvalGroupUser> evalGroupUsers = this.fetchPostUsers(dto.getPostIds(), dto.getShopIds(), null);
          List<EvalGroupUserVO> evalGroupUserVOS = PublicUtil.copyList(evalGroupUsers, EvalGroupUserVO.class);
          return evalGroupUserVOS;
      }
  
ac84063e   姜超   feature(*): 考评人员
377
  }