EvaluationResultJob.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  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. List<Integer> userIds = getUserIds(tenantId, companyOrgId);
  101. Map<Long, UserEntity> userEntityMap = toMap(userIds);
  102. String startTime = null;
  103. String endTime = null;
  104. List<EvaluationItemVo> itemEntityList = null;
  105. for (Integer userId : userIds) {
  106. UserEntity userEntity = userEntityMap.get(Long.parseLong(userId.toString()));
  107. if (userEntity == null) {
  108. continue;
  109. }
  110. itemEntityList = findItem(userEntity);
  111. // 1.获取部门考评项设置,如果未设置直接过滤
  112. // 2.判断部门考评项目设置里面有没有设置对应的考评周期,没有就直接过滤
  113. if (CollectionUtil.isEmpty(itemEntityList) || !EvaluationUtil.containsType(itemEntityList, cycle)) {
  114. continue;
  115. }
  116. try {
  117. // 根据类型(0月度 1季度 2年度)得到当前的开始时间和结束时间,如果是按季度,当月必须是1,4,7,10
  118. startTime = EvaluationUtil.getStartTime(cycle, null, null);
  119. endTime = EvaluationUtil.getEndTime(cycle, null,null);
  120. if (startTime == null || endTime == null) {
  121. continue;
  122. }
  123. // 保存用户考评结果
  124. saveEvaluationResultInfo(userEntity, itemEntityList , startTime, endTime ,cycle);
  125. } catch (Exception e) {
  126. log.error("保存用户考评信息出错->", e);
  127. }
  128. }
  129. }
  130. private List<Integer> getUserIds(String tenantId, Integer companyOrgId){
  131. String key = tenantId + "_" + companyOrgId;
  132. List<Integer> result = userIdsMap.get(key);
  133. if (result == null){
  134. result = userCenterClient.findUserIdsByPermissonOrg(tenantId, companyOrgId, null);
  135. userIdsMap.put(key, result);
  136. }
  137. return result;
  138. }
  139. /**
  140. * @Author lihui
  141. * @Description 保存用户考评结果
  142. * @Date 10:26 2021/5/11
  143. * @Param [userEntity, itemEntityList, startTime, endTime, cycle]
  144. * @return void
  145. **/
  146. @Transactional
  147. public void saveEvaluationResultInfo(UserEntity userEntity, List<EvaluationItemVo> itemEntityList, String startTime, String endTime, Integer cycle){
  148. Calendar calendar = EvaluationUtil.getCalendar(endTime);
  149. // 计算用户完成任务情况
  150. EvaluationResultTaskEntity taskDetailsVo = calculationTaskInfo(userEntity.getId().intValue(), userEntity.getTenantId(), startTime, endTime, getValueCondition(itemEntityList));
  151. // 组装考评结果数据
  152. EvaluationResultEntity resultEntity = packagesEvaluationResultEntity(userEntity, calendar, cycle, startTime, endTime);
  153. // 保存考评结果
  154. if (evaluationResultMapper.insertEvaluationResult(resultEntity) != 1) {
  155. throw new ServiceException(500, "保存考评结果出错,退出。");
  156. }
  157. Integer resultId = resultEntity.getId().intValue();
  158. taskDetailsVo.setEvaluationResultId(resultId);
  159. // 保存考评结果任务详情
  160. evaluationResultTaskMapper.insertEvaluationResultTask(taskDetailsVo);
  161. BigDecimal completeCount = new BigDecimal(taskDetailsVo.getCompleteCount()) ;
  162. BigDecimal completionRate = taskDetailsVo.getCompletionRate();
  163. BigDecimal evaluationValue = null;
  164. for (EvaluationItemVo item : itemEntityList) {
  165. // 不是当前季度的,过滤
  166. if (item.getCycle().indexOf(cycle.toString()) == -1 || item.getType() == null) {
  167. continue;
  168. }
  169. evaluationValue = item.getType() == 1 ? completeCount : completionRate;
  170. EvaluationResultDetailsEntity detailsEntity = new EvaluationResultDetailsEntity();
  171. detailsEntity.setEvaluationResultId(resultId);
  172. detailsEntity.setEvaluationItemId(item.getItemId());
  173. detailsEntity.setValue(getScore(item.getType(), item.getEvaluationItemValueVoList(), evaluationValue));
  174. detailsEntity.setDateCreate(new Date());
  175. detailsEntity.setDateUpdate(new Date());
  176. detailsEntity.setTenantId(userEntity.getTenantId());
  177. detailsEntity.setStatus(1);
  178. evaluationResultDetailsMapper.insertEvaluationResultDetails(detailsEntity);
  179. }
  180. }
  181. /**
  182. * @Author lihui
  183. * @Description 计算用户完成任务情况
  184. * @Date 17:38 2021/5/10
  185. * @Param [userId, tenantId, startTime, endTime,valueCondition:延期时间多少分钟内算正常]
  186. * @return void
  187. **/
  188. private EvaluationResultTaskEntity calculationTaskInfo(Integer userId, String tenantId, String startTime, String endTime, BigDecimal valueCondition) {
  189. int page = 1;
  190. IPage<WorkOrderManageDto> iPage = null;
  191. EvaluationResultTaskEntity taskEntity = new EvaluationResultTaskEntity();
  192. boolean completedBoolean = false;
  193. while (true) {
  194. iPage = new Page<>(page, 200);
  195. // 查询该用户的工单和任务
  196. Page<WorkOrderManageDto> pageList = workOrderManageMapper.selectByTime(iPage, userId, tenantId, startTime, endTime);
  197. if (pageList == null || CollectionUtil.isEmpty(pageList.getRecords())) {
  198. break;
  199. }
  200. for (WorkOrderManageDto dto : pageList.getRecords()) {
  201. completedBoolean = EvaluationUtil.completed(dto.getOrderStatus());
  202. taskEntity.setTotalCount(taskEntity.getTotalCount() + 1);
  203. taskEntity.setCompleteCount(taskEntity.getCompleteCount() + (completedBoolean ? 1 : 0));
  204. taskEntity.setNoCompleteCount(taskEntity.getNoCompleteCount() + (!completedBoolean ? 1 : 0));
  205. int addMinute = valueCondition == null ? EvaluationUtil.minute(dto.getDateLimit()) : valueCondition.intValue();
  206. // 计算完成的是否属于延期完成
  207. if (completedBoolean && EvaluationUtil.isDelay(dto.getFinishDate(), dto.getPlanFinishDate(), addMinute)) {
  208. taskEntity.setDelayCompleteCount(taskEntity.getDelayCompleteCount() + 1);
  209. }
  210. }
  211. page ++;
  212. }
  213. // 计算完成率和延期率
  214. taskEntity.setCompletionRate(EvaluationUtil.divide(taskEntity.getCompleteCount(),taskEntity.getTotalCount()));
  215. taskEntity.setDelayRate(EvaluationUtil.divide(taskEntity.getDelayCompleteCount(),taskEntity.getTotalCount()));
  216. taskEntity.setTenantId(tenantId);
  217. taskEntity.setStatus(1);
  218. taskEntity.setDateCreate(new Date());
  219. return taskEntity;
  220. }
  221. /**
  222. * @Author lihui
  223. * @Description 获取部门考评项
  224. * @Date 17:36 2021/5/10
  225. * @Param [userEntity]
  226. * @return java.util.List<com.huaxu.evaluation.entity.EvaluationItemEntity>
  227. **/
  228. private List<EvaluationItemVo> findItem(UserEntity userEntity){
  229. Integer companyOrgId = EvaluationUtil.toInteger(userEntity.getCompanyOrgId());
  230. Integer deptOrgId = EvaluationUtil.toInteger(userEntity.getDeptOrgId());
  231. String tenantId = userEntity.getTenantId();
  232. String key = tenantId + "_" + companyOrgId + "_" + deptOrgId;
  233. List<EvaluationItemVo> itemVos = itemMap.get(key);
  234. if (itemVos != null) {
  235. return itemVos;
  236. }
  237. EvaluationItemEntity queryItem = new EvaluationItemEntity();
  238. queryItem.setCompanyOrgId(companyOrgId);
  239. queryItem.setDeptOrgId(deptOrgId);
  240. queryItem.setTenantId(tenantId);
  241. itemVos = evaluationItemMapper.findListItem(queryItem);
  242. itemMap.put(key, itemVos);
  243. return itemVos;
  244. }
  245. /**
  246. * @Author lihui
  247. * @Description 组装考评结果数据
  248. * @Date 15:03 2021/5/11
  249. * @Param [userEntity, calendar, cycle, startTime, endTime]
  250. * @return com.huaxu.evaluation.entity.EvaluationResultEntity
  251. **/
  252. private EvaluationResultEntity packagesEvaluationResultEntity(UserEntity userEntity, Calendar calendar, Integer cycle, String startTime, String endTime){
  253. EvaluationResultEntity resultEntity = new EvaluationResultEntity();
  254. resultEntity.setYear(calendar.get(Calendar.YEAR));
  255. resultEntity.setMonth(calendar.get(Calendar.MONTH) + 1);
  256. resultEntity.setEvaluationBe(userEntity.getUsername());
  257. resultEntity.setEvaluationBeUserId(userEntity.getId());
  258. resultEntity.setCycle(cycle);
  259. resultEntity.setState(0);
  260. resultEntity.setDateStart(DatesUtil.parseDate(startTime, "yyyy-MM-dd HH:mm:ss"));
  261. resultEntity.setDateEnd(DatesUtil.parseDate(endTime, "yyyy-MM-dd HH:mm:ss"));
  262. resultEntity.setTenantId(userEntity.getTenantId());
  263. resultEntity.setCompanyOrgId(EvaluationUtil.toInteger(userEntity.getCompanyOrgId()));
  264. resultEntity.setDeptOrgId(EvaluationUtil.toInteger(userEntity.getDeptOrgId()));
  265. resultEntity.setDateCreate(new Date());
  266. resultEntity.setStatus(1);
  267. return resultEntity;
  268. }
  269. private Map<Long, UserEntity> toMap(List<Integer> userIds){
  270. List<UserEntity> userEntities = userCenterClient.findUserIdsByUserIds(EvaluationUtil.toLong(userIds));
  271. if (CollectionUtil.isEmpty(userEntities)){
  272. return null;
  273. }
  274. return userEntities.stream().collect(Collectors.toMap(UserEntity::getId, a -> a,(k1, k2)->k1));
  275. }
  276. private BigDecimal getScore (Integer type, List<EvaluationItemValueVo> list, BigDecimal evaluationValue){
  277. if (type != 1 && type != 2) {
  278. return null;
  279. }
  280. Integer itemType = null;
  281. BigDecimal itemValue = null;
  282. BigDecimal valueOne = null;
  283. BigDecimal valueTwo = null;
  284. for (EvaluationItemValueVo evaluationItemValueVo: list) {
  285. itemType = evaluationItemValueVo.getItemType();
  286. itemValue = evaluationItemValueVo.getItemValue();
  287. valueOne = evaluationItemValueVo.getValueOne();
  288. valueTwo = evaluationItemValueVo.getValueTwo();
  289. // 大于等于 0大于等于 2小于 1介于
  290. if (itemType == 0 && evaluationValue.compareTo(valueOne) > -1) {
  291. return itemValue;
  292. }
  293. // 小于
  294. if (itemType == 2 && evaluationValue.compareTo(valueOne) == -1) {
  295. return itemValue;
  296. }
  297. // 介于 : 比如取8-10,就是≥8,<10
  298. if (itemType == 1 && evaluationValue.compareTo(valueOne) > -1 && evaluationValue.compareTo(valueTwo) == -1) {
  299. return itemValue;
  300. }
  301. }
  302. return new BigDecimal("0");
  303. }
  304. /**
  305. * @Author lihui
  306. * @Description 获取任务按时完成率设定的条件值
  307. * @Date 9:40 2021/5/11
  308. * @Param [itemEntityList]
  309. * @return java.math.BigDecimal
  310. **/
  311. private BigDecimal getValueCondition(List<EvaluationItemVo> itemEntityList){
  312. for (EvaluationItemVo evaluationItemVo: itemEntityList) {
  313. if (evaluationItemVo.getType() == 2) {
  314. return evaluationItemVo.getValueCondition();
  315. }
  316. }
  317. return null;
  318. }
  319. }