AttendanceMessageTask.java 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  1. package com.xjrsoft.module.job;
  2. import cn.hutool.core.util.IdUtil;
  3. import cn.hutool.core.util.StrUtil;
  4. import cn.hutool.extra.spring.SpringUtil;
  5. import com.alibaba.fastjson.JSONObject;
  6. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  7. import com.github.yulichang.wrapper.MPJLambdaWrapper;
  8. import com.xjrsoft.common.utils.VoToColumnUtil;
  9. import com.xjrsoft.common.utils.WeChatUtil;
  10. import com.xjrsoft.config.CommonPropertiesConfig;
  11. import com.xjrsoft.module.attendance.entity.AttendanceMessageSet;
  12. import com.xjrsoft.module.attendance.entity.AttendanceMessageUserRelation;
  13. import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails;
  14. import com.xjrsoft.module.attendance.service.IAttendanceMessageSetService;
  15. import com.xjrsoft.module.attendance.service.IAttendanceRuleCategoryService;
  16. import com.xjrsoft.module.concat.service.IXjrUserService;
  17. import com.xjrsoft.module.holiday.entity.HolidayDate;
  18. import com.xjrsoft.module.holiday.service.IHolidayDateService;
  19. import com.xjrsoft.module.organization.dto.WeChatSendMessageDto;
  20. import com.xjrsoft.module.organization.entity.UserRoleRelation;
  21. import com.xjrsoft.module.organization.service.IWeChatService;
  22. import com.xjrsoft.module.outint.entity.StudentOutInRecord;
  23. import com.xjrsoft.module.outint.entity.TeacherOutInRecord;
  24. import com.xjrsoft.module.outint.service.IStudentOutInRecordService;
  25. import com.xjrsoft.module.outint.service.ITeacherOutInRecordService;
  26. import com.xjrsoft.module.student.entity.BaseStudent;
  27. import com.xjrsoft.module.system.entity.WechatMessageLog;
  28. import com.xjrsoft.module.system.service.IWechatMessageLogService;
  29. import com.xjrsoft.module.teacher.entity.BaseTeacher;
  30. import com.xjrsoft.module.teacher.entity.XjrUser;
  31. import lombok.extern.slf4j.Slf4j;
  32. import org.springframework.beans.factory.annotation.Autowired;
  33. import org.springframework.scheduling.annotation.Scheduled;
  34. import org.springframework.stereotype.Component;
  35. import java.time.LocalDateTime;
  36. import java.time.format.DateTimeFormatter;
  37. import java.time.temporal.ChronoUnit;
  38. import java.util.ArrayList;
  39. import java.util.Collections;
  40. import java.util.Date;
  41. import java.util.HashMap;
  42. import java.util.List;
  43. import java.util.Map;
  44. import java.util.Set;
  45. import java.util.stream.Collectors;
  46. /**
  47. * 考勤消息通知,给领导推送每个时段的考勤情况
  48. * @author dzx
  49. * @date 2024年6月7日
  50. */
  51. @Component
  52. @Slf4j
  53. public class AttendanceMessageTask {
  54. @Autowired
  55. private IAttendanceMessageSetService messageSetService;
  56. @Autowired
  57. private IAttendanceRuleCategoryService ruleCategoryService;
  58. @Autowired
  59. private IHolidayDateService holidayDateService;
  60. @Autowired
  61. private IXjrUserService userService;
  62. @Autowired
  63. private IStudentOutInRecordService studentOutInRecordService;
  64. @Autowired
  65. private ITeacherOutInRecordService teachertOutInRecordService;
  66. @Autowired
  67. private IWeChatService weChatService;
  68. @Autowired
  69. private CommonPropertiesConfig commonPropertiesConfig;
  70. @Autowired
  71. private WeChatUtil weChatUtil;
  72. @Autowired
  73. private IWechatMessageLogService wechatMessageLogService;
  74. @Scheduled(cron = "0 */1 * * * ?")
  75. public void RefreshConnectionPool() {
  76. String active = SpringUtil.getActiveProfile();
  77. if(!"prod".equals(active)){
  78. log.info("非正式环境,无法执行数据推送");
  79. return;
  80. }
  81. doExecute();
  82. }
  83. public void doExecute(){
  84. LocalDateTime now = LocalDateTime.now();
  85. HolidayDate holidayDate = holidayDateService.getOne(
  86. new QueryWrapper<HolidayDate>().lambda()
  87. .eq(HolidayDate::getDate, now.toLocalDate())
  88. );
  89. if(holidayDate != null && holidayDate.getWay() != null && holidayDate.getWay() != 0 && holidayDate.getWay() != 2){
  90. log.info("非工作日,不需要提醒");
  91. return;
  92. }
  93. //查询今天的考勤规则
  94. List<AttendanceRuleDetails> ruleDetails = ruleCategoryService.getTodayRules();
  95. List<AttendanceMessageSet> list = messageSetService.list();
  96. //判断是上午还是下午
  97. Integer timePeriod = null;
  98. String timePeriodStr = null;
  99. if(now.getHour() <= 12){
  100. timePeriod = 1;
  101. timePeriodStr = "上午考勤";
  102. }else if(now.getHour() <= 18){
  103. timePeriod = 2;
  104. timePeriodStr = "下午考勤";
  105. }else{
  106. timePeriod = 3;
  107. timePeriodStr = "晚上考勤";
  108. }
  109. DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  110. int userCount = 0;
  111. Set<Integer> roleTypes = list.stream().map(AttendanceMessageSet::getRoleType).collect(Collectors.toSet());
  112. //查询需要通知的人
  113. for (AttendanceMessageSet messageSet : list) {
  114. LocalDateTime recentlyTime = null;
  115. String characterKey = "character_string18";
  116. String wechatTemplate = weChatUtil.getAttendanceMsgLateTemplate();
  117. if(messageSet.getMessageCategory() != null && messageSet.getMessageCategory() == 1){
  118. wechatTemplate = weChatUtil.getAttendanceMsgLateTemplate();
  119. characterKey = "character_string18";
  120. //获取最近的时间
  121. recentlyTime = getRecentlyTime(ruleDetails, now);
  122. if(recentlyTime.getHour() != now.getHour() && Math.abs(recentlyTime.getMinute() - now.getMinute()) >= 2){
  123. log.info("未到时间,不进行推送");
  124. continue;
  125. }
  126. long count = wechatMessageLogService.count(
  127. new QueryWrapper<WechatMessageLog>().lambda()
  128. .eq(WechatMessageLog::getSendTime, recentlyTime)
  129. .eq(WechatMessageLog::getTemplateId, wechatTemplate)
  130. );
  131. if(count > 0){//已经推送过,不再进行推送
  132. log.info("已推送过,不进行推送");
  133. continue;
  134. }
  135. }else if(messageSet.getMessageCategory() != null && messageSet.getMessageCategory() == 3){
  136. wechatTemplate = weChatUtil.getAttendanceMsgAbsenceTemplate();
  137. recentlyTime = getRecentlyOverTime(ruleDetails, now);
  138. characterKey = "character_string36";
  139. if(recentlyTime.getHour() != now.getHour() && Math.abs(recentlyTime.getMinute() - now.getMinute()) >= 2){
  140. log.info("未到时间,不进行推送");
  141. continue;
  142. }
  143. long count = wechatMessageLogService.count(
  144. new QueryWrapper<WechatMessageLog>().lambda()
  145. .eq(WechatMessageLog::getSendTime, recentlyTime)
  146. .eq(WechatMessageLog::getTemplateId, wechatTemplate)
  147. );
  148. if(count > 0){//已经推送过,不再进行推送
  149. log.info("已推送过,不进行推送");
  150. continue;
  151. }
  152. }
  153. if(!messageSet.getTimePeriod().contains(timePeriod + "")){
  154. continue;
  155. }
  156. List<XjrUser> userList = userService.list(
  157. new MPJLambdaWrapper<XjrUser>().distinct()
  158. .select(XjrUser::getId)
  159. .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
  160. .leftJoin(UserRoleRelation.class, UserRoleRelation::getUserId, XjrUser::getId)
  161. .leftJoin(AttendanceMessageUserRelation.class, AttendanceMessageUserRelation::getUserId, XjrUser::getId)
  162. .in(UserRoleRelation::getRoleId, roleTypes)
  163. .eq(AttendanceMessageUserRelation::getAttendanceMessageSetId, messageSet.getId())
  164. );
  165. //没有需要通知的,直接跳过
  166. if(userList.isEmpty()){
  167. continue;
  168. }
  169. if(recentlyTime == null){
  170. continue;
  171. }
  172. String format = recentlyTime.format(formatter);
  173. userCount += userList.size();
  174. if(messageSet.getRoleType() != null && messageSet.getRoleType() == 1){
  175. //教师总人数
  176. long teacherCout = userService.count(
  177. new MPJLambdaWrapper<XjrUser>()
  178. .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId)
  179. );
  180. //查询进入记录,就是实际到校的人数
  181. List<TeacherOutInRecord> outInRecords = teachertOutInRecordService.list(
  182. new MPJLambdaWrapper<TeacherOutInRecord>()
  183. .le(TeacherOutInRecord::getRecordTime, recentlyTime)
  184. .eq(TeacherOutInRecord::getStatus, 1)
  185. .eq("DATE_FORMAT(record_time, '%Y-%m-%d')", recentlyTime.toLocalDate())
  186. );
  187. List<Long> collect = outInRecords.stream().map(TeacherOutInRecord::getUserId).collect(Collectors.toList());
  188. WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
  189. weChatSendMessageDto.setTemplateId(wechatTemplate);
  190. JSONObject paramJson = new JSONObject();
  191. JSONObject thing6 = new JSONObject();
  192. thing6.put("value", "教职工");
  193. paramJson.put("thing6", thing6);
  194. JSONObject time11 = new JSONObject();
  195. time11.put("value", format);
  196. paramJson.put("time11", time11);
  197. JSONObject const23 = new JSONObject();
  198. const23.put("value", timePeriodStr);
  199. paramJson.put("const23", const23);
  200. //迟到人数或者缺勤人数
  201. JSONObject character_string18 = new JSONObject();
  202. character_string18.put("value", teacherCout - collect.size());
  203. paramJson.put(characterKey, character_string18);
  204. JSONObject character_string16 = new JSONObject();
  205. character_string16.put("value", teacherCout);
  206. paramJson.put("character_string16", character_string16);
  207. weChatSendMessageDto.setContent(paramJson);
  208. weChatSendMessageDto.setUrl(StrUtil.format("{}pages/attendance/teacher/index", commonPropertiesConfig.getDomainApp()));
  209. for (XjrUser xjrUser : userList) {
  210. weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
  211. weChatSendMessageDto.setUserId(xjrUser.getOpenId());
  212. // weChatService.sendTemplateMessage(weChatSendMessageDto);
  213. }
  214. }else if(messageSet.getRoleType() != null && messageSet.getRoleType() == 2){
  215. //教师总人数
  216. long teacherCout = userService.count(
  217. new MPJLambdaWrapper<XjrUser>()
  218. .leftJoin(BaseStudent.class, BaseStudent::getUserId, XjrUser::getId)
  219. );
  220. //查询进入记录,就是实际到校的人数
  221. long outInRecords = studentOutInRecordService.count(
  222. new MPJLambdaWrapper<StudentOutInRecord>()
  223. .le(StudentOutInRecord::getRecordTime, recentlyTime)
  224. .eq(StudentOutInRecord::getStatus, 1)
  225. );
  226. WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
  227. weChatSendMessageDto.setTemplateId(wechatTemplate);
  228. JSONObject paramJson = new JSONObject();
  229. JSONObject thing6 = new JSONObject();
  230. thing6.put("value", "学生");
  231. paramJson.put("thing6", thing6);
  232. JSONObject time11 = new JSONObject();
  233. time11.put("value", format);
  234. paramJson.put("time11", time11);
  235. JSONObject const23 = new JSONObject();
  236. const23.put("value", timePeriodStr);
  237. paramJson.put("const23", const23);
  238. JSONObject character_string18 = new JSONObject();
  239. character_string18.put("value", teacherCout - outInRecords);
  240. paramJson.put(characterKey, character_string18);
  241. JSONObject character_string16 = new JSONObject();
  242. character_string16.put("value", teacherCout);
  243. paramJson.put("const3", character_string16);
  244. weChatSendMessageDto.setContent(paramJson);
  245. weChatSendMessageDto.setUrl(StrUtil.format("{}pages/attendance/class/index", commonPropertiesConfig.getDomainApp()));
  246. for (XjrUser xjrUser : userList) {
  247. weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
  248. weChatSendMessageDto.setUserId(xjrUser.getOpenId());
  249. // weChatService.sendTemplateMessage(weChatSendMessageDto);
  250. }
  251. }
  252. WechatMessageLog messageLog = new WechatMessageLog();
  253. messageLog.setTemplateId(wechatTemplate);
  254. messageLog.setSendTime(recentlyTime);
  255. messageLog.setCreateDate(new Date());
  256. messageLog.setContent("消息推送人数:" + userCount);
  257. wechatMessageLogService.save(messageLog);
  258. }
  259. }
  260. LocalDateTime getRecentlyTime(List<AttendanceRuleDetails> ruleDetails, LocalDateTime now){
  261. List<LocalDateTime> result = new ArrayList<>();
  262. for (AttendanceRuleDetails ruleDetail : ruleDetails) {
  263. if(ruleDetail.getIsAllowInOutSchool() != null && ruleDetail.getIsAllowInOutSchool() == 1
  264. && ruleDetail.getIsAttendance() != null && ruleDetail.getIsAttendance() == 1){
  265. if(ruleDetail.getAmStartTime() != null){
  266. LocalDateTime amStartTime = now.with(ruleDetail.getAmStartTime().toLocalTime());
  267. result.add(amStartTime);
  268. }
  269. if(ruleDetail.getPmStartTime() != null){
  270. LocalDateTime pmStartTime = now.with(ruleDetail.getPmStartTime().toLocalTime());
  271. result.add(pmStartTime);
  272. }
  273. if(ruleDetail.getEveningStartTime() != null){
  274. LocalDateTime eveningStartTime = now.with(ruleDetail.getEveningStartTime().toLocalTime());
  275. result.add(eveningStartTime);
  276. }
  277. }
  278. }
  279. if(result.isEmpty()){
  280. return null;
  281. }
  282. Map<Long, LocalDateTime> timeMap = new HashMap<>();
  283. for (LocalDateTime localDateTime : result) {
  284. long between = ChronoUnit.SECONDS.between(now, localDateTime);
  285. timeMap.put(Math.abs(between), localDateTime);
  286. }
  287. List<Long> collect = timeMap.keySet().stream().collect(Collectors.toList());
  288. Collections.sort(collect, Long::compare);
  289. return timeMap.get(collect.get(0));
  290. }
  291. LocalDateTime getRecentlyOverTime(List<AttendanceRuleDetails> ruleDetails, LocalDateTime now){
  292. List<LocalDateTime> result = new ArrayList<>();
  293. for (AttendanceRuleDetails ruleDetail : ruleDetails) {
  294. if(ruleDetail.getIsAllowInOutSchool() != null && ruleDetail.getIsAllowInOutSchool() == 1
  295. && ruleDetail.getIsAttendance() != null && ruleDetail.getIsAttendance() == 1){
  296. if(ruleDetail.getAmStartTime() != null){
  297. LocalDateTime amStartTime = now.with(ruleDetail.getAmStartTime().toLocalTime());
  298. if(ruleDetail.getOverMinutes() != null){
  299. amStartTime.plusMinutes(ruleDetail.getOverMinutes());
  300. }
  301. result.add(amStartTime);
  302. }
  303. if(ruleDetail.getPmStartTime() != null){
  304. LocalDateTime pmStartTime = now.with(ruleDetail.getPmStartTime().toLocalTime());
  305. if(ruleDetail.getOverMinutes() != null){
  306. pmStartTime.plusMinutes(ruleDetail.getOverMinutes());
  307. }
  308. result.add(pmStartTime);
  309. }
  310. if(ruleDetail.getEveningStartTime() != null){
  311. LocalDateTime eveningStartTime = now.with(ruleDetail.getEveningStartTime().toLocalTime());
  312. if(ruleDetail.getOverMinutes() != null){
  313. eveningStartTime.plusMinutes(ruleDetail.getOverMinutes());
  314. }
  315. result.add(eveningStartTime);
  316. }
  317. }
  318. }
  319. if(result.isEmpty()){
  320. return null;
  321. }
  322. Map<Long, LocalDateTime> timeMap = new HashMap<>();
  323. for (LocalDateTime localDateTime : result) {
  324. long between = ChronoUnit.SECONDS.between(now, localDateTime);
  325. timeMap.put(Math.abs(between), localDateTime);
  326. }
  327. List<Long> collect = timeMap.keySet().stream().collect(Collectors.toList());
  328. Collections.sort(collect, Long::compare);
  329. return timeMap.get(collect.get(0));
  330. }
  331. }