Blame view

fw-morax-service/src/main/java/cn/fw/morax/service/biz/eval/EvalGroupUserBizService.java 14.5 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;
  
      /**
       * 所有集团生效的绩效组配置
       */
c043db4c   姜超   feature(*): 查看考评详情
56
      public List<EvalGroup> postEffectEvalGroups(LocalDate queryDate){
ac84063e   姜超   feature(*): 考评人员
57
          List<EvalGroup> evalGroups = evalGroupService.getAllEffectGroups(queryDate);
f727712b   姜超   feature(*): 考评阶段指标上报
58
          if (PublicUtil.isEmpty(evalGroups)) {
936e630c   姜超   feature(*): 门店奖惩分配
59
              log.info("时间:{},没有正在生效中的考评组配置", DateTimeFormatter.ofPattern("yyyy-MM-dd").format(queryDate));
f727712b   姜超   feature(*): 考评阶段指标上报
60
              return new ArrayList<>();
ac84063e   姜超   feature(*): 考评人员
61
          }
c043db4c   姜超   feature(*): 查看考评详情
62
63
64
65
          //过滤岗位为空考评组
          List<EvalGroup> postEvalGroups = evalGroups.stream()
                  .filter(evalGroup -> PublicUtil.isNotEmpty(evalGroup.getPostIds())).collect(Collectors.toList());
          return postEvalGroups;
ac84063e   姜超   feature(*): 考评人员
66
67
68
69
70
71
72
73
      }
  
      /**
       * 构建绩效组人员
       *
       * @return
       */
      @Transactional(rollbackFor = Exception.class)
c043db4c   姜超   feature(*): 查看考评详情
74
75
      public List<EvalGroupUser> fetchBuildKpiUser(Long postId, EvalGroup evalGroup, LocalDate localDate){
          List<EvalGroupUser> evalGroupUsers = this.fetchPostUsers(postId, evalGroup.getShopIds(), localDate);
ac84063e   姜超   feature(*): 考评人员
76
  
abf088aa   姜超   feature(*): 考评排名组
77
78
          //构建考评组信息
          for (EvalGroupUser user : evalGroupUsers) {
8945afe5   姜超   feature(*): 考评保存修改
79
              user.setEvalGroupRankId(evalGroup.getEvalGroupRankId());
5e6a6922   姜超   feature(*): 筛选修改
80
              user.setEvalGroupRankStageId(evalGroup.getEvalGroupRankStageId());
abf088aa   姜超   feature(*): 考评排名组
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
              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(*): 考评人员
97
98
99
100
101
          if (PublicUtil.isEmpty(staffs)) {
              return new ArrayList<>();
          }
          List<EvalGroupUser> result = Lists.newArrayListWithCapacity(staffs.size());
  
ac84063e   姜超   feature(*): 考评人员
102
          for (PerformanceStaffDTO staff : staffs) {
abf088aa   姜超   feature(*): 考评排名组
103
              EvalGroupUser evalGroupUser = this.convertToGroupUser(staff, dataDate);
ac84063e   姜超   feature(*): 考评人员
104
105
106
107
108
109
110
111
              //处理绩效考核数据
              this.handleStaffKpi(staff, evalGroupUser);
              result.add(evalGroupUser);
          }
          return result;
      }
  
      /**
f727712b   姜超   feature(*): 考评阶段指标上报
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
137
138
       * 获取岗位人员
       *
       * @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(*): 导入修改
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
       * 构建绩效组人员
       *
       * @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(*): 考评人员
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
328
329
       * 处理员工绩效考核数据
       * 试用期、转正两个月内、调岗两个月内、待岗两个月内、申请不进行绩效考核
       *
       * @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(*): 考评人员
330
                  .build();
abf088aa   姜超   feature(*): 考评排名组
331
332
333
          if (PublicUtil.isNotEmpty(now)) {
              evalGroupUser.setDataDate(now);
          }
ac84063e   姜超   feature(*): 考评人员
334
335
336
          return evalGroupUser;
      }
  
abf088aa   姜超   feature(*): 考评排名组
337
338
339
340
341
342
343
344
345
346
  
      /**
       * 查询考评组人员
       *
       * @param evalGroupId
       * @return
       */
      public List<EvalGroupUserVO> queryEvalGroupStaffs(Long evalGroupId) {
          EvalGroup evalGroup = evalGroupService.getById(evalGroupId);
          BV.notNull(evalGroup, "考评配置不存在,请重试");
f727712b   姜超   feature(*): 考评阶段指标上报
347
          List<EvalGroupUser> evalGroupUsers = this.fetchPostUsers(evalGroup.getPostIds(), evalGroup.getShopIds(), null);
abf088aa   姜超   feature(*): 考评排名组
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
          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(*): 考评排名组修改
367
368
369
370
371
372
373
374
375
376
377
378
      /**
       * 查询考评组排名人员
       *
       * @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(*): 考评人员
379
  }