EvaluationResultJob.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. package com.huaxu.evaluation.job;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import com.baomidou.mybatisplus.core.metadata.IPage;
  4. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  5. import com.huaxu.client.UserCenterClient;
  6. import com.huaxu.evaluation.dao.*;
  7. import com.huaxu.evaluation.entity.*;
  8. import com.huaxu.evaluation.enums.EvaluationCycleEnums;
  9. import com.huaxu.evaluation.vo.EvaluationItemValueVo;
  10. import com.huaxu.evaluation.vo.EvaluationItemVo;
  11. import com.huaxu.evaluation.vo.EvaluationResultTaskDetailsVo;
  12. import com.huaxu.exception.ServiceException;
  13. import com.huaxu.order.dao.WorkOrderManageMapper;
  14. import com.huaxu.order.dto.WorkOrderManageDto;
  15. import com.huaxu.task.entity.UserEntity;
  16. import com.huaxu.util.DatesUtil;
  17. import com.huaxu.utils.EvaluationUtil;
  18. import io.swagger.models.auth.In;
  19. import lombok.extern.slf4j.Slf4j;
  20. import org.springframework.beans.factory.annotation.Autowired;
  21. import org.springframework.scheduling.annotation.Async;
  22. import org.springframework.scheduling.annotation.EnableScheduling;
  23. import org.springframework.scheduling.annotation.Scheduled;
  24. import org.springframework.stereotype.Component;
  25. import org.springframework.transaction.annotation.Transactional;
  26. import java.math.BigDecimal;
  27. import java.math.RoundingMode;
  28. import java.util.*;
  29. import java.util.stream.Collectors;
  30. /**
  31. * @ClassName EvaluationResultJob
  32. * @Description: TODO
  33. * @Author lihui
  34. * @Date 2021/5/7
  35. * @Version V1.0
  36. **/
  37. @Component
  38. @Slf4j
  39. @EnableScheduling
  40. public class EvaluationResultJob {
  41. @Autowired
  42. private WorkOrderManageMapper workOrderManageMapper;
  43. @Autowired
  44. private UserCenterClient userCenterClient;
  45. @Autowired
  46. private EvaluationCycleMapper evaluationCycleMapper;
  47. @Autowired
  48. private EvaluationResultDetailsMapper evaluationResultDetailsMapper;
  49. @Autowired
  50. private EvaluationResultMapper evaluationResultMapper;
  51. @Autowired
  52. private EvaluationResultTaskMapper evaluationResultTaskMapper;
  53. @Autowired
  54. private EvaluationItemMapper evaluationItemMapper;
  55. private static boolean lock = false;
  56. // 保存考评项目设置
  57. static Map<String, List<EvaluationItemVo>> itemMap = new HashMap<>();
  58. static Map<String, List<Integer>> userIdsMap = new HashMap<>();
  59. @Scheduled(cron = "0/5 * * * * ?")
  60. @Async
  61. public void run(){
  62. if (lock){
  63. return;
  64. }
  65. lock = true;
  66. log.info("============绩效考评数据生成begin=====================");
  67. // 首先查询哪些公司设置了绩效考评
  68. List<EvaluationCycleEntity> evaluationCycleEntities = evaluationCycleMapper.findList(new EvaluationCycleEntity());
  69. try {
  70. for (EvaluationCycleEntity evaluationCycleEntity : evaluationCycleEntities) {
  71. // 查询公司设置的考评日期是否是今天
  72. if (!EvaluationUtil.isToday(evaluationCycleEntity.getEvaluationDay())) {
  73. continue;
  74. }
  75. // 如果是年度,需要检查当前日期是否是在1月份
  76. if (evaluationCycleEntity.getType() == EvaluationCycleEnums.YEAR.getType() &&
  77. !EvaluationUtil.sameMonth(1)) {
  78. continue;
  79. }
  80. userTask(evaluationCycleEntity.getTenantId(), evaluationCycleEntity.getCompanyOrgId(), evaluationCycleEntity.getType());
  81. }
  82. } catch (Exception e) {
  83. log.error("绩效考评定时任务出错->", e);
  84. } finally {
  85. // 用完直接clear
  86. itemMap.clear();
  87. //lock = false;
  88. }
  89. log.info("============绩效考评数据生成end=====================");
  90. }
  91. /**
  92. * @Author lihui
  93. * @Description 用户任务分解
  94. * @Date 18:19 2021/5/10
  95. * @Param [tenantId:租户ID, companyOrgId : 公司ID, cycle : 类型(0月度 1季度 2年度)]
  96. * @return void
  97. **/
  98. public void userTask(String tenantId, Integer companyOrgId, Integer cycle){
  99. // 查询该租户公司下的所有用户
  100. String startTime = null;
  101. String endTime = null;
  102. List<EvaluationItemVo> itemEntityList = null;
  103. List<Integer> userIds = getUserIds(tenantId, companyOrgId);
  104. Map<Long, UserEntity> userEntityMap = toMap(userIds);
  105. if (userEntityMap == null) {
  106. return;
  107. }
  108. for (Integer userId : userIds) {
  109. UserEntity userEntity = userEntityMap.get(Long.parseLong(userId.toString()));
  110. if (userEntity == null) {
  111. continue;
  112. }
  113. itemEntityList = findItem(userEntity);
  114. // 1.获取部门考评项设置,如果未设置直接过滤
  115. // 2.判断部门考评项目设置里面有没有设置对应的考评周期,没有就直接过滤
  116. if (CollectionUtil.isEmpty(itemEntityList) || !EvaluationUtil.containsType(itemEntityList, cycle)) {
  117. continue;
  118. }
  119. try {
  120. // 根据类型(0月度 1季度 2年度)得到当前的开始时间和结束时间,如果是按季度,当月必须是1,4,7,10
  121. startTime = EvaluationUtil.getStartTime(cycle, null, null);
  122. endTime = EvaluationUtil.getEndTime(cycle, null,null);
  123. if (startTime == null || endTime == null) {
  124. continue;
  125. }
  126. // 保存用户考评结果
  127. saveEvaluationResultInfo(userEntity, itemEntityList , startTime, endTime ,cycle);
  128. } catch (Exception e) {
  129. log.error("保存用户考评信息出错->", e);
  130. }
  131. }
  132. }
  133. private List<Integer> getUserIds(String tenantId, Integer companyOrgId){
  134. String key = tenantId + "_" + companyOrgId;
  135. List<Integer> result = userIdsMap.get(key);
  136. if (result == null){
  137. result = userCenterClient.findUserIdsByPermissonOrg(tenantId, companyOrgId, null);
  138. userIdsMap.put(key, result);
  139. }
  140. return result;
  141. }
  142. /**
  143. * @Author lihui
  144. * @Description 保存用户考评结果
  145. * @Date 10:26 2021/5/11
  146. * @Param [userEntity, itemEntityList, startTime, endTime, cycle]
  147. * @return void
  148. **/
  149. @Transactional
  150. public void saveEvaluationResultInfo(UserEntity userEntity, List<EvaluationItemVo> itemEntityList, String startTime, String endTime, Integer cycle){
  151. Calendar calendar = EvaluationUtil.getCalendar(endTime);
  152. // 计算用户完成任务情况
  153. EvaluationResultTaskEntity taskDetailsVo = calculationTaskInfo(userEntity.getId().intValue(), userEntity.getTenantId(), startTime, endTime, getValueCondition(itemEntityList));
  154. // 组装考评结果数据
  155. EvaluationResultEntity resultEntity = packagesEvaluationResultEntity(userEntity, calendar, cycle, startTime, endTime);
  156. // 保存考评结果
  157. if (evaluationResultMapper.insertEvaluationResult(resultEntity) != 1) {
  158. throw new ServiceException(500, "保存考评结果出错,退出。");
  159. }
  160. Integer resultId = resultEntity.getId().intValue();
  161. taskDetailsVo.setEvaluationResultId(resultId);
  162. // 保存考评结果任务详情
  163. evaluationResultTaskMapper.insertEvaluationResultTask(taskDetailsVo);
  164. BigDecimal completeCount = new BigDecimal(taskDetailsVo.getCompleteCount()) ;
  165. BigDecimal completionRate = taskDetailsVo.getCompletionRate();
  166. BigDecimal evaluationValue = null;
  167. for (EvaluationItemVo item : itemEntityList) {
  168. // 不是当前季度的,过滤
  169. if (item.getCycle().indexOf(cycle.toString()) == -1 || item.getType() == null) {
  170. continue;
  171. }
  172. evaluationValue = item.getType() == 1 ? completeCount : completionRate;
  173. EvaluationResultDetailsEntity detailsEntity = new EvaluationResultDetailsEntity();
  174. detailsEntity.setEvaluationResultId(resultId);
  175. detailsEntity.setEvaluationItemId(item.getItemId());
  176. detailsEntity.setValue(getScore(item.getType(), item.getEvaluationItemValueVoList(), evaluationValue));
  177. detailsEntity.setDateCreate(new Date());
  178. detailsEntity.setDateUpdate(new Date());
  179. detailsEntity.setTenantId(userEntity.getTenantId());
  180. detailsEntity.setStatus(1);
  181. evaluationResultDetailsMapper.insertEvaluationResultDetails(detailsEntity);
  182. }
  183. }
  184. /**
  185. * @Author lihui
  186. * @Description 计算用户完成任务情况
  187. * @Date 17:38 2021/5/10
  188. * @Param [userId, tenantId, startTime, endTime,valueCondition:延期时间多少分钟内算正常]
  189. * @return void
  190. **/
  191. private EvaluationResultTaskEntity calculationTaskInfo(Integer userId, String tenantId, String startTime, String endTime, BigDecimal valueCondition) {
  192. int page = 1;
  193. IPage<WorkOrderManageDto> iPage = null;
  194. EvaluationResultTaskEntity taskEntity = new EvaluationResultTaskEntity();
  195. boolean completedBoolean = false;
  196. while (true) {
  197. iPage = new Page<>(page, 200);
  198. // 查询该用户的工单和任务
  199. Page<WorkOrderManageDto> pageList = workOrderManageMapper.selectByTime(iPage, userId, tenantId, startTime, endTime);
  200. if (pageList == null || CollectionUtil.isEmpty(pageList.getRecords())) {
  201. break;
  202. }
  203. for (WorkOrderManageDto dto : pageList.getRecords()) {
  204. completedBoolean = EvaluationUtil.completed(dto.getOrderStatus());
  205. taskEntity.setTotalCount(taskEntity.getTotalCount() + 1);
  206. taskEntity.setCompleteCount(taskEntity.getCompleteCount() + (completedBoolean ? 1 : 0));
  207. taskEntity.setNoCompleteCount(taskEntity.getNoCompleteCount() + (!completedBoolean ? 1 : 0));
  208. int addMinute = valueCondition == null ? EvaluationUtil.minute(dto.getDateLimit()) : valueCondition.intValue();
  209. // 计算完成的是否属于延期完成
  210. if (completedBoolean && EvaluationUtil.isDelay(dto.getFinishDate(), dto.getPlanFinishDate(), addMinute)) {
  211. taskEntity.setDelayCompleteCount(taskEntity.getDelayCompleteCount() + 1);
  212. }
  213. }
  214. page ++;
  215. }
  216. // 计算完成率和延期率
  217. taskEntity.setCompletionRate(EvaluationUtil.divide(taskEntity.getCompleteCount(),taskEntity.getTotalCount()));
  218. taskEntity.setDelayRate(EvaluationUtil.divide(taskEntity.getDelayCompleteCount(),taskEntity.getTotalCount()));
  219. taskEntity.setTenantId(tenantId);
  220. taskEntity.setStatus(1);
  221. taskEntity.setDateCreate(new Date());
  222. return taskEntity;
  223. }
  224. /**
  225. * @Author lihui
  226. * @Description 获取部门考评项
  227. * @Date 17:36 2021/5/10
  228. * @Param [userEntity]
  229. * @return java.util.List<com.huaxu.evaluation.entity.EvaluationItemEntity>
  230. **/
  231. private List<EvaluationItemVo> findItem(UserEntity userEntity){
  232. Integer companyOrgId = EvaluationUtil.toInteger(userEntity.getCompanyOrgId());
  233. Integer deptOrgId = EvaluationUtil.toInteger(userEntity.getDeptOrgId());
  234. String tenantId = userEntity.getTenantId();
  235. String key = tenantId + "_" + companyOrgId + "_" + deptOrgId;
  236. List<EvaluationItemVo> itemVos = itemMap.get(key);
  237. if (itemVos != null) {
  238. return itemVos;
  239. }
  240. EvaluationItemEntity queryItem = new EvaluationItemEntity();
  241. queryItem.setCompanyOrgId(companyOrgId);
  242. queryItem.setDeptOrgId(deptOrgId);
  243. queryItem.setTenantId(tenantId);
  244. itemVos = evaluationItemMapper.findListItem(queryItem);
  245. itemMap.put(key, itemVos);
  246. return itemVos;
  247. }
  248. /**
  249. * @Author lihui
  250. * @Description 组装考评结果数据
  251. * @Date 15:03 2021/5/11
  252. * @Param [userEntity, calendar, cycle, startTime, endTime]
  253. * @return com.huaxu.evaluation.entity.EvaluationResultEntity
  254. **/
  255. private EvaluationResultEntity packagesEvaluationResultEntity(UserEntity userEntity, Calendar calendar, Integer cycle, String startTime, String endTime){
  256. EvaluationResultEntity resultEntity = new EvaluationResultEntity();
  257. resultEntity.setYear(calendar.get(Calendar.YEAR));
  258. resultEntity.setMonth(calendar.get(Calendar.MONTH) + 1);
  259. resultEntity.setEvaluationBe(userEntity.getUsername());
  260. resultEntity.setEvaluationBeUserId(userEntity.getId());
  261. resultEntity.setCycle(cycle);
  262. resultEntity.setState(0);
  263. resultEntity.setDateStart(DatesUtil.parseDate(startTime, "yyyy-MM-dd HH:mm:ss"));
  264. resultEntity.setDateEnd(DatesUtil.parseDate(endTime, "yyyy-MM-dd HH:mm:ss"));
  265. resultEntity.setTenantId(userEntity.getTenantId());
  266. resultEntity.setCompanyOrgId(EvaluationUtil.toInteger(userEntity.getCompanyOrgId()));
  267. resultEntity.setDeptOrgId(EvaluationUtil.toInteger(userEntity.getDeptOrgId()));
  268. resultEntity.setDateCreate(new Date());
  269. resultEntity.setStatus(1);
  270. return resultEntity;
  271. }
  272. private Map<Long, UserEntity> toMap(List<Integer> userIds){
  273. List<UserEntity> userEntities = userCenterClient.findUserIdsByUserIds(EvaluationUtil.toLong(userIds));
  274. if (CollectionUtil.isEmpty(userEntities)){
  275. return null;
  276. }
  277. return userEntities.stream().collect(Collectors.toMap(UserEntity::getId, a -> a,(k1, k2)->k1));
  278. }
  279. /**
  280. * @Author lihui
  281. * @Description 获取对应的分数
  282. * @Date 11:25 2021/5/14
  283. * @Param [type, list, evaluationValue]
  284. * @return java.math.BigDecimal
  285. **/
  286. private BigDecimal getScore (Integer type, List<EvaluationItemValueVo> list, BigDecimal evaluationValue){
  287. if (type != 1 && type != 2) {
  288. return null;
  289. }
  290. Integer itemType = null;
  291. BigDecimal itemValue = null;
  292. BigDecimal valueOne = null;
  293. BigDecimal valueTwo = null;
  294. for (EvaluationItemValueVo evaluationItemValueVo: list) {
  295. itemType = evaluationItemValueVo.getItemType();
  296. itemValue = evaluationItemValueVo.getItemValue();
  297. valueOne = evaluationItemValueVo.getValueOne();
  298. valueTwo = evaluationItemValueVo.getValueTwo();
  299. // 大于等于 0大于等于 2小于 1介于
  300. if (itemType == 0 && evaluationValue.compareTo(valueOne) > -1) {
  301. return itemValue;
  302. }
  303. // 小于
  304. if (itemType == 2 && evaluationValue.compareTo(valueOne) == -1) {
  305. return itemValue;
  306. }
  307. // 介于 : 比如取8-10,就是≥8,<10
  308. if (itemType == 1 && evaluationValue.compareTo(valueOne) > -1 && evaluationValue.compareTo(valueTwo) == -1) {
  309. return itemValue;
  310. }
  311. }
  312. return new BigDecimal("0");
  313. }
  314. /**
  315. * @Author lihui
  316. * @Description 获取任务按时完成率设定的条件值
  317. * @Date 9:40 2021/5/11
  318. * @Param [itemEntityList]
  319. * @return java.math.BigDecimal
  320. **/
  321. private BigDecimal getValueCondition(List<EvaluationItemVo> itemEntityList){
  322. for (EvaluationItemVo evaluationItemVo: itemEntityList) {
  323. if (evaluationItemVo.getType() == 2) {
  324. return evaluationItemVo.getValueCondition();
  325. }
  326. }
  327. return null;
  328. }
  329. }