AttenDanceWarnNoticeTask.java 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. package com.xjrsoft.module.job;
  2. import cn.hutool.core.util.IdUtil;
  3. import cn.hutool.extra.spring.SpringUtil;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  6. import com.xjrsoft.common.utils.VoToColumnUtil;
  7. import com.xjrsoft.common.utils.WeChatUtil;
  8. import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails;
  9. import com.xjrsoft.module.attendance.entity.AttendanceUserRelation;
  10. import com.xjrsoft.module.attendance.mapper.AttendanceUserRelationMapper;
  11. import com.xjrsoft.module.attendance.service.IAttendanceRuleCategoryService;
  12. import com.xjrsoft.module.concat.service.IXjrUserService;
  13. import com.xjrsoft.module.organization.dto.WeChatSendMessageDto;
  14. import com.xjrsoft.module.organization.service.IWeChatService;
  15. import com.xjrsoft.module.system.entity.WechatMessageLog;
  16. import com.xjrsoft.module.system.service.IWechatMessageLogService;
  17. import com.xjrsoft.module.teacher.entity.XjrUser;
  18. import lombok.extern.slf4j.Slf4j;
  19. import org.springframework.beans.factory.annotation.Autowired;
  20. import org.springframework.scheduling.annotation.Scheduled;
  21. import org.springframework.stereotype.Component;
  22. import java.time.LocalDateTime;
  23. import java.time.format.DateTimeFormatter;
  24. import java.time.temporal.ChronoUnit;
  25. import java.util.ArrayList;
  26. import java.util.Collections;
  27. import java.util.Date;
  28. import java.util.HashMap;
  29. import java.util.List;
  30. import java.util.Map;
  31. import java.util.Set;
  32. import java.util.stream.Collectors;
  33. /**
  34. * 考勤预警通知,提醒教师和学生是否该上课等
  35. * @author dzx
  36. * @date 2024年5月21日
  37. */
  38. @Component
  39. @Slf4j
  40. public class AttenDanceWarnNoticeTask {
  41. @Autowired
  42. private IAttendanceRuleCategoryService categoryService;
  43. @Autowired
  44. private IXjrUserService userService;
  45. @Autowired
  46. private AttendanceUserRelationMapper relationMapper;
  47. @Autowired
  48. private IWeChatService weChatService;
  49. @Autowired
  50. private WeChatUtil weChatUtil;
  51. @Autowired
  52. private IWechatMessageLogService wechatMessageLogService;
  53. @Scheduled(cron = "0 */5 * * * ?")
  54. public void RefreshConnectionPool() {
  55. String active = SpringUtil.getActiveProfile();
  56. if("dev".equals(active)){
  57. log.info("测试环境,无法执行数据推送");
  58. return;
  59. }
  60. //获取当前时间
  61. LocalDateTime now = LocalDateTime.now();
  62. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  63. String timeStr = now.format(formatter);
  64. //查询今天所有的考勤规则
  65. List<AttendanceRuleDetails> ruleDetailsList = categoryService.getTodayRules();
  66. Map<Long, AttendanceRuleDetails> ruleDetailsMap = new HashMap<>();
  67. for (AttendanceRuleDetails ruleDetail : ruleDetailsList) {
  68. ruleDetailsMap.put(ruleDetail.getAttendanceRuleCategoryId(), ruleDetail);
  69. }
  70. //查询出所有人的考勤规则
  71. List<AttendanceUserRelation> relationList = relationMapper.selectList(
  72. new QueryWrapper<AttendanceUserRelation>().lambda()
  73. .eq(AttendanceUserRelation::getDeleteMark, 0)
  74. );
  75. Map<Long, AttendanceRuleDetails> allTodyRule = new HashMap<>();
  76. for (AttendanceUserRelation userRelation : relationList) {
  77. allTodyRule.put(userRelation.getUserId(), ruleDetailsMap.get(userRelation.getAttendanceRuleCategoryId()));
  78. }
  79. Map<Long, AttendanceUserRelation> allUserStatus = new HashMap<>();
  80. for (AttendanceUserRelation userRelation : relationList) {
  81. allUserStatus.put(userRelation.getUserId(), userRelation);
  82. }
  83. //根据规则中的用户id查询出所有绑定了微信的学生和教师
  84. if(allTodyRule.isEmpty()){
  85. log.info("未能查询出规则,不进行推送");
  86. return;
  87. }
  88. //获取最近的时间
  89. LocalDateTime recentlyTime = getRecentlyTime(ruleDetailsList, now);
  90. if(recentlyTime.getHour() != now.getHour() && Math.abs(recentlyTime.getMinute() - now.getMinute()) <= 2){
  91. log.info("未到时间,不进行推送");
  92. return;
  93. }
  94. String wechatTemplate = weChatUtil.getAttenDanceWarnTemplate();
  95. List<WechatMessageLog> list = wechatMessageLogService.list(
  96. new QueryWrapper<WechatMessageLog>().lambda()
  97. .select(WechatMessageLog.class, x -> VoToColumnUtil.fieldsToColumns(WechatMessageLog.class).contains(x.getProperty()))
  98. .eq(WechatMessageLog::getSendTime, recentlyTime)
  99. .eq(WechatMessageLog::getTemplateId, wechatTemplate)
  100. );
  101. if(!list.isEmpty()){//已经推送过,不再进行推送
  102. return;
  103. }
  104. //判断所有当前时间下,哪几条规则需要进行提醒
  105. Map<Long, Integer> ruleDetailsJudgeMap = judgeExecuteNotice(now, ruleDetailsList, recentlyTime);
  106. WechatMessageLog messageLog = new WechatMessageLog();
  107. messageLog.setTemplateId(wechatTemplate);
  108. messageLog.setSendTime(recentlyTime);
  109. List<XjrUser> userList = getUserList(allTodyRule.keySet());
  110. for (XjrUser xjrUser : userList) {
  111. AttendanceRuleDetails ruleDetails = allTodyRule.get(xjrUser.getId());
  112. Integer status = ruleDetailsJudgeMap.get(ruleDetails.getId());
  113. if(status == 0){
  114. continue;
  115. }
  116. WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
  117. weChatSendMessageDto.setUserId(xjrUser.getOpenId());
  118. weChatSendMessageDto.setTemplateId(wechatTemplate);
  119. weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
  120. JSONObject paramJson = new JSONObject();
  121. JSONObject time5 = new JSONObject();
  122. time5.put("value", recentlyTime.format(formatter));
  123. paramJson.put("time5", time5);
  124. JSONObject thing8 = new JSONObject();
  125. thing8.put("value", xjrUser.getName());
  126. paramJson.put("thing8", thing8);
  127. JSONObject time9 = new JSONObject();
  128. time9.put("value", timeStr);
  129. paramJson.put("time9", time9);
  130. JSONObject const12 = new JSONObject();
  131. if(status == 1){
  132. const12.put("value", "未打卡");
  133. }else{
  134. const12.put("value", "待打卡");
  135. }
  136. //查询这个用户最新的考勤状态
  137. AttendanceUserRelation userRelation = allUserStatus.get(xjrUser.getId());
  138. if(userRelation != null
  139. && userRelation.getAttendanceTime() !=null
  140. && userRelation.getAttendanceTime().toLocalDate().isEqual(now.toLocalDate())
  141. && "到校".equals(userRelation.getAttendanceStatus())){
  142. const12.put("value", "已打卡");
  143. }
  144. paramJson.put("const12", const12);
  145. weChatSendMessageDto.setContent(paramJson);
  146. weChatService.sendTemplateMessage(weChatSendMessageDto);
  147. }
  148. messageLog.setCreateDate(new Date());
  149. messageLog.setContent("消息推送人数:" + userList.size());
  150. wechatMessageLogService.save(messageLog);
  151. }
  152. /**
  153. * 判断所有规则,哪些需要发送
  154. * @param judgeTime
  155. * @param ruleDetailsList
  156. * @return 0:不需要提醒,1:未打卡,2:待打卡
  157. */
  158. Map<Long, Integer> judgeExecuteNotice(LocalDateTime judgeTime, List<AttendanceRuleDetails> ruleDetailsList, LocalDateTime recentlyTime){
  159. Map<Long, Integer> result = new HashMap<>();
  160. for (AttendanceRuleDetails ruleDetails : ruleDetailsList) {
  161. if(ruleDetails.getIsAllowInOutSchool() != null && ruleDetails.getIsAllowInOutSchool() == 1
  162. && ruleDetails.getIsAttendance() != null && ruleDetails.getIsAttendance() == 1){
  163. if(ruleDetails.getAmStartTime() != null){
  164. LocalDateTime amStartTime = judgeTime.with(ruleDetails.getAmStartTime().toLocalTime());
  165. if(recentlyTime.isEqual(amStartTime)){
  166. Long amBetween = ChronoUnit.MINUTES.between(judgeTime, amStartTime);
  167. if(judgeTime.isBefore(amStartTime) && amBetween >= ruleDetails.getAgoMinutes() - 1 && amBetween <= ruleDetails.getAgoMinutes() + 1){//相差分钟数小于0
  168. result.put(ruleDetails.getId(), 1);
  169. }else if(judgeTime.isAfter(amStartTime) && amBetween >= ruleDetails.getOverMinutes() - 1 && amBetween <= ruleDetails.getOverMinutes() + 1){
  170. result.put(ruleDetails.getId(), 2);
  171. }
  172. }
  173. }
  174. if(ruleDetails.getPmStartTime() != null){
  175. LocalDateTime pmStartTime = judgeTime.with(ruleDetails.getPmStartTime().toLocalTime());
  176. if(recentlyTime.isEqual(pmStartTime)){
  177. Long pmBetween = ChronoUnit.MINUTES.between(judgeTime, pmStartTime);
  178. if(judgeTime.isBefore(pmStartTime) && pmBetween >= ruleDetails.getAgoMinutes() - 1 && pmBetween <= ruleDetails.getAgoMinutes() + 1){
  179. result.put(ruleDetails.getId(), 1);
  180. }else if(judgeTime.isAfter(pmStartTime) && pmBetween >= ruleDetails.getOverMinutes() - 1 && pmBetween <= ruleDetails.getOverMinutes() + 1){
  181. result.put(ruleDetails.getId(), 2);
  182. }
  183. }
  184. }
  185. if(ruleDetails.getEveningStartTime() != null){
  186. LocalDateTime eveningStartTime = judgeTime.with(ruleDetails.getEveningStartTime().toLocalTime());
  187. if(recentlyTime.isEqual(eveningStartTime)){
  188. Long eveningBetween = ChronoUnit.MINUTES.between(judgeTime, eveningStartTime);
  189. if(judgeTime.isBefore(eveningStartTime) && eveningBetween >= ruleDetails.getAgoMinutes() - 1 && eveningBetween <= ruleDetails.getAgoMinutes() + 1){
  190. result.put(ruleDetails.getId(), 1);
  191. }else if(judgeTime.isAfter(eveningStartTime) && eveningBetween >= ruleDetails.getOverMinutes() - 1 && eveningBetween <= ruleDetails.getOverMinutes() + 1){
  192. result.put(ruleDetails.getId(), 2);
  193. }
  194. }
  195. }
  196. if(!result.containsKey(ruleDetails.getId())){
  197. result.put(ruleDetails.getId(), 0);
  198. }
  199. }else{
  200. result.put(ruleDetails.getId(), 0);
  201. }
  202. }
  203. return result;
  204. }
  205. /**
  206. * 查询出所有用户信息(openId不为空的)
  207. * @param userIds 需要插叙的userid
  208. * @return 用户信息
  209. */
  210. List<XjrUser> getUserList(Set<Long> userIds){
  211. return userService.list(
  212. new QueryWrapper<XjrUser>().lambda()
  213. .in(XjrUser::getId, userIds)
  214. .isNotNull(XjrUser::getOpenId)
  215. );
  216. }
  217. LocalDateTime getRecentlyTime(List<AttendanceRuleDetails> ruleDetails, LocalDateTime now){
  218. List<LocalDateTime> result = new ArrayList<>();
  219. for (AttendanceRuleDetails ruleDetail : ruleDetails) {
  220. if(ruleDetail.getIsAllowInOutSchool() != null && ruleDetail.getIsAllowInOutSchool() == 1
  221. && ruleDetail.getIsAttendance() != null && ruleDetail.getIsAttendance() == 1){
  222. if(ruleDetail.getAmStartTime() != null){
  223. LocalDateTime amStartTime = now.with(ruleDetail.getAmStartTime().toLocalTime());
  224. result.add(amStartTime.plusDays(- ruleDetail.getAgoMinutes()));
  225. result.add(amStartTime.plusDays(ruleDetail.getOverMinutes()));
  226. }
  227. if(ruleDetail.getPmStartTime() != null){
  228. LocalDateTime pmStartTime = now.with(ruleDetail.getPmStartTime().toLocalTime());
  229. result.add(pmStartTime.plusDays(- ruleDetail.getAgoMinutes()));
  230. result.add(pmStartTime.plusDays(ruleDetail.getOverMinutes()));
  231. }
  232. if(ruleDetail.getEveningStartTime() != null){
  233. LocalDateTime eveningStartTime = now.with(ruleDetail.getEveningStartTime().toLocalTime());
  234. result.add(eveningStartTime.plusDays(- ruleDetail.getAgoMinutes()));
  235. result.add(eveningStartTime.plusDays(ruleDetail.getOverMinutes()));
  236. }
  237. }
  238. }
  239. if(result.isEmpty()){
  240. return null;
  241. }
  242. Map<Long, LocalDateTime> timeMap = new HashMap<>();
  243. for (LocalDateTime localDateTime : result) {
  244. long between = ChronoUnit.SECONDS.between(now, localDateTime);
  245. timeMap.put(Math.abs(between), localDateTime);
  246. }
  247. List<Long> collect = timeMap.keySet().stream().collect(Collectors.toList());
  248. Collections.sort(collect, Long::compare);
  249. return timeMap.get(collect.get(0));
  250. }
  251. }