package com.xjrsoft.module.job; import cn.hutool.core.util.IdUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.db.Entity; import cn.hutool.extra.spring.SpringUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.github.yulichang.wrapper.MPJLambdaWrapper; import com.xjrsoft.common.mybatis.SqlRunnerAdapter; import com.xjrsoft.common.utils.VoToColumnUtil; import com.xjrsoft.common.utils.WeChatUtil; import com.xjrsoft.config.CommonPropertiesConfig; import com.xjrsoft.module.attendance.entity.AttendanceMessageSet; import com.xjrsoft.module.attendance.entity.AttendanceMessageUserRelation; import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails; import com.xjrsoft.module.attendance.service.IAttendanceMessageSetService; import com.xjrsoft.module.attendance.service.IAttendanceRuleCategoryService; import com.xjrsoft.module.concat.service.IXjrUserService; import com.xjrsoft.module.holiday.entity.HolidayDate; import com.xjrsoft.module.holiday.service.IHolidayDateService; import com.xjrsoft.module.organization.dto.WeChatSendMessageDto; import com.xjrsoft.module.organization.entity.UserRoleRelation; import com.xjrsoft.module.organization.service.IWeChatService; import com.xjrsoft.module.outint.entity.StudentOutInRecord; import com.xjrsoft.module.outint.entity.TeacherOutInRecord; import com.xjrsoft.module.outint.service.IStudentOutInRecordService; import com.xjrsoft.module.outint.service.ITeacherOutInRecordService; import com.xjrsoft.module.student.entity.BaseStudent; import com.xjrsoft.module.teacher.entity.BaseTeacher; import com.xjrsoft.module.teacher.entity.XjrUser; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.text.SimpleDateFormat; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.*; import java.util.stream.Collectors; /** * 考勤消息通知,给领导推送每个时段的考勤情况 * * @author dzx * @date 2024年6月7日 */ @Component @Slf4j public class AttendanceMessageTask { @Autowired private IAttendanceMessageSetService messageSetService; @Autowired private IAttendanceRuleCategoryService ruleCategoryService; @Autowired private IHolidayDateService holidayDateService; @Autowired private IXjrUserService userService; @Autowired private IStudentOutInRecordService studentOutInRecordService; @Autowired private ITeacherOutInRecordService teachertOutInRecordService; @Autowired private IWeChatService weChatService; @Autowired private CommonPropertiesConfig commonPropertiesConfig; @Autowired private WeChatUtil weChatUtil; @Async @Scheduled(cron = "0 */1 * * * ?") public void RefreshConnectionPool() { String active = SpringUtil.getActiveProfile(); if (!"prod".equals(active)) { log.info("非正式环境,无法执行数据推送"); return; } doExecute(); } public void doExecute() { LocalDateTime now = LocalDateTime.now(); HolidayDate holidayDate = holidayDateService.getOne( new QueryWrapper().lambda() .eq(HolidayDate::getDate, now.toLocalDate()) ); //查询到了数据,且当天不是“普通工作日”或“需要补班的工作日” if (holidayDate != null && holidayDate.getWay() != null && holidayDate.getWay() != 0 && holidayDate.getWay() != 2) { log.info("非工作日,不需要提醒"); return; } //未查询到数据 String dayOfWeek = now.getDayOfWeek().name(); if (holidayDate == null || "SUNDAY".equals(dayOfWeek) || "SATURDAY".equals(dayOfWeek)) { log.info("非工作日,不需要提醒"); // return; } //查询今天的考勤规则 List ruleDetails = ruleCategoryService.getTodayRules(); List list = messageSetService.list(); //判断是上午还是下午 Integer timePeriod = null; String timePeriodStr = null; if (now.getHour() <= 12) { timePeriod = 1; timePeriodStr = "上午考勤"; } else if (now.getHour() <= 18) { timePeriod = 2; timePeriodStr = "下午考勤"; } else { timePeriod = 3; timePeriodStr = "晚上考勤"; } DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); int userCount = 0; Set roleTypes = list.stream().map(AttendanceMessageSet::getRoleType).collect(Collectors.toSet()); //查询需要通知的人 String table = "attendance_message_log"; boolean isInsert = true; for (AttendanceMessageSet messageSet : list) { LocalDateTime recentlyTime = null; String characterKey = "character_string18"; String wechatTemplate = weChatUtil.getAttendanceMsgLateTemplate(); if (messageSet.getMessageCategory() != null && messageSet.getMessageCategory() == 1) { wechatTemplate = weChatUtil.getAttendanceMsgLateTemplate(); characterKey = "character_string18"; //获取最近的时间 recentlyTime = getRecentlyTime(ruleDetails, now); if (recentlyTime.getHour() != now.getHour() || (recentlyTime.getHour() == now.getHour() && recentlyTime.getMinute() != now.getMinute())) { log.info("未到时间,不进行推送"); isInsert = false; continue; } Entity entity = Entity.create(table); entity.set("send_time", recentlyTime); entity.set("template_id", wechatTemplate); String sql = "SELECT COUNT(*) FROM " + table + " WHERE delete_mark = 0 AND template_id = '" + wechatTemplate + "' AND send_time = '" + recentlyTime.format(formatter) + "'"; long count = SqlRunnerAdapter.db().selectCount(sql); if (count > 0) {//已经推送过,不再进行推送 log.info("已推送过,不进行推送"); isInsert = false; continue; } } else if (messageSet.getMessageCategory() != null && messageSet.getMessageCategory() == 3) { wechatTemplate = weChatUtil.getAttendanceMsgAbsenceTemplate(); recentlyTime = getRecentlyOverTime(ruleDetails, now); characterKey = "character_string36"; if (recentlyTime.getHour() != now.getHour() || (recentlyTime.getHour() == now.getHour() && recentlyTime.getMinute() != now.getMinute())) { log.info("未到时间,不进行推送"); isInsert = false; continue; } String sql = "SELECT COUNT(*) FROM " + table + " WHERE delete_mark = 0 AND template_id = '" + wechatTemplate + "' AND send_time = '" + recentlyTime.format(formatter) + "'"; long count = SqlRunnerAdapter.db().selectCount(sql); if (count > 0) {//已经推送过,不再进行推送 log.info("已推送过,不进行推送"); isInsert = false; continue; } } if (!messageSet.getTimePeriod().contains(timePeriod + "")) { isInsert = false; continue; } List userList = userService.list( new MPJLambdaWrapper().distinct() .select(XjrUser::getId) .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty())) .leftJoin(UserRoleRelation.class, UserRoleRelation::getUserId, XjrUser::getId) .leftJoin(AttendanceMessageUserRelation.class, AttendanceMessageUserRelation::getUserId, XjrUser::getId) .in(UserRoleRelation::getRoleId, roleTypes) .eq(AttendanceMessageUserRelation::getAttendanceMessageSetId, messageSet.getId()) ); //没有需要通知的,直接跳过 if (userList.isEmpty()) { isInsert = false; continue; } if (recentlyTime == null) { isInsert = false; continue; } String format = recentlyTime.format(formatter); userCount += userList.size(); if (messageSet.getRoleType() != null && messageSet.getRoleType() == 1) { //教师总人数 long teacherCout = userService.count( new MPJLambdaWrapper() .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId) ); //查询进入记录,就是实际到校的人数 List outInRecords = teachertOutInRecordService.list( new MPJLambdaWrapper() .le(TeacherOutInRecord::getRecordTime, recentlyTime) .eq(TeacherOutInRecord::getStatus, 1) .eq("DATE_FORMAT(record_time, '%Y-%m-%d')", recentlyTime.toLocalDate()) ); List collect = outInRecords.stream().map(TeacherOutInRecord::getUserId).collect(Collectors.toList()); WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto(); weChatSendMessageDto.setTemplateId(wechatTemplate); JSONObject paramJson = new JSONObject(); JSONObject thing6 = new JSONObject(); thing6.put("value", "教职工"); paramJson.put("thing6", thing6); JSONObject time11 = new JSONObject(); time11.put("value", format); paramJson.put("time11", time11); JSONObject const23 = new JSONObject(); const23.put("value", timePeriodStr); paramJson.put("const23", const23); //迟到人数或者缺勤人数 JSONObject character_string18 = new JSONObject(); character_string18.put("value", teacherCout - collect.size()); paramJson.put(characterKey, character_string18); JSONObject character_string16 = new JSONObject(); character_string16.put("value", teacherCout); paramJson.put("character_string16", character_string16); weChatSendMessageDto.setContent(paramJson); weChatSendMessageDto.setUrl(StrUtil.format("{}pages/attendance/teacher/index", commonPropertiesConfig.getDomainApp())); for (XjrUser xjrUser : userList) { weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + ""); weChatSendMessageDto.setUserId(xjrUser.getOpenId()); weChatService.sendTemplateMessage(weChatSendMessageDto); } } else if (messageSet.getRoleType() != null && messageSet.getRoleType() == 2) { //教师总人数 long teacherCout = userService.count( new MPJLambdaWrapper() .leftJoin(BaseStudent.class, BaseStudent::getUserId, XjrUser::getId) ); //查询进入记录,就是实际到校的人数 long outInRecords = studentOutInRecordService.count( new MPJLambdaWrapper() .le(StudentOutInRecord::getRecordTime, recentlyTime) .eq(StudentOutInRecord::getStatus, 1) ); WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto(); weChatSendMessageDto.setTemplateId(wechatTemplate); JSONObject paramJson = new JSONObject(); JSONObject thing6 = new JSONObject(); thing6.put("value", "学生"); paramJson.put("thing6", thing6); JSONObject time11 = new JSONObject(); time11.put("value", format); paramJson.put("time11", time11); JSONObject const23 = new JSONObject(); const23.put("value", timePeriodStr); paramJson.put("const23", const23); JSONObject character_string18 = new JSONObject(); character_string18.put("value", teacherCout - outInRecords); paramJson.put(characterKey, character_string18); JSONObject character_string16 = new JSONObject(); character_string16.put("value", teacherCout); paramJson.put("const3", character_string16); weChatSendMessageDto.setContent(paramJson); weChatSendMessageDto.setUrl(StrUtil.format("{}pages/attendance/class/index", commonPropertiesConfig.getDomainApp())); for (XjrUser xjrUser : userList) { weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + ""); weChatSendMessageDto.setUserId(xjrUser.getOpenId()); weChatService.sendTemplateMessage(weChatSendMessageDto); } isInsert = true; } if (isInsert) { SimpleDateFormat sdf = new SimpleDateFormat("yyy-MM-dd HH:mm:ss"); Entity entity = Entity.create(table); entity.set("id", IdUtil.getSnowflakeNextId()); entity.set("content", "消息推送人数:" + userCount); entity.set("create_date", sdf.format(new Date())); entity.set("content", "消息推送人数:" + userCount); entity.set("template_id", wechatTemplate); entity.set("send_time", recentlyTime); SqlRunnerAdapter.db().dynamicInsert(table, entity); } } } LocalDateTime getRecentlyTime(List ruleDetails, LocalDateTime now) { List result = new ArrayList<>(); for (AttendanceRuleDetails ruleDetail : ruleDetails) { if (ruleDetail.getIsAllowInOutSchool() != null && ruleDetail.getIsAllowInOutSchool() == 1 && ruleDetail.getIsAttendance() != null && ruleDetail.getIsAttendance() == 1) { if (ruleDetail.getAmStartTime() != null) { LocalDateTime amStartTime = now.with(ruleDetail.getAmStartTime().toLocalTime()); result.add(amStartTime); } if (ruleDetail.getPmStartTime() != null) { LocalDateTime pmStartTime = now.with(ruleDetail.getPmStartTime().toLocalTime()); result.add(pmStartTime); } if (ruleDetail.getEveningStartTime() != null) { LocalDateTime eveningStartTime = now.with(ruleDetail.getEveningStartTime().toLocalTime()); result.add(eveningStartTime); } } } if (result.isEmpty()) { return null; } Map timeMap = new HashMap<>(); for (LocalDateTime localDateTime : result) { long between = ChronoUnit.SECONDS.between(now, localDateTime); timeMap.put(Math.abs(between), localDateTime); } List collect = timeMap.keySet().stream().collect(Collectors.toList()); Collections.sort(collect, Long::compare); return timeMap.get(collect.get(0)); } LocalDateTime getRecentlyOverTime(List ruleDetails, LocalDateTime now) { List result = new ArrayList<>(); for (AttendanceRuleDetails ruleDetail : ruleDetails) { if (ruleDetail.getIsAllowInOutSchool() != null && ruleDetail.getIsAllowInOutSchool() == 1 && ruleDetail.getIsAttendance() != null && ruleDetail.getIsAttendance() == 1) { if (ruleDetail.getAmStartTime() != null) { LocalDateTime amStartTime = now.with(ruleDetail.getAmStartTime().toLocalTime()); if (ruleDetail.getOverMinutes() != null) { amStartTime.plusMinutes(ruleDetail.getOverMinutes()); } result.add(amStartTime); } if (ruleDetail.getPmStartTime() != null) { LocalDateTime pmStartTime = now.with(ruleDetail.getPmStartTime().toLocalTime()); if (ruleDetail.getOverMinutes() != null) { pmStartTime.plusMinutes(ruleDetail.getOverMinutes()); } result.add(pmStartTime); } if (ruleDetail.getEveningStartTime() != null) { LocalDateTime eveningStartTime = now.with(ruleDetail.getEveningStartTime().toLocalTime()); if (ruleDetail.getOverMinutes() != null) { eveningStartTime.plusMinutes(ruleDetail.getOverMinutes()); } result.add(eveningStartTime); } } } if (result.isEmpty()) { return null; } Map timeMap = new HashMap<>(); for (LocalDateTime localDateTime : result) { long between = ChronoUnit.SECONDS.between(now, localDateTime); timeMap.put(Math.abs(between), localDateTime); } List collect = timeMap.keySet().stream().collect(Collectors.toList()); Collections.sort(collect, Long::compare); return timeMap.get(collect.get(0)); } }