Преглед изворни кода

Merge remote-tracking branch 'origin/dev' into dev

大数据与最优化研究所 пре 5 месеци
родитељ
комит
dd09273b6a

+ 17 - 5
src/main/java/com/xjrsoft/module/hikvision/controller/EventController.java

@@ -120,15 +120,27 @@ public class EventController {
                         weChatSendMessageDto.setMsgId(member.getId().toString());
                         JSONObject paramJson = new JSONObject();
 
-                        paramJson.put("thing1", student.getName());
-                        paramJson.put("time3", recordTimeStr);
-                        paramJson.put("thing2", baseClass.getName());
+                        JSONObject thing1 = new JSONObject();
+                        thing1.put("value", student.getName());
+                        paramJson.put("thing1", thing1);
+
+                        JSONObject time3 = new JSONObject();
+                        time3.put("value", recordTimeStr);
+                        paramJson.put("time3", time3);
+
+                        JSONObject thing2 = new JSONObject();
+                        thing2.put("value", baseClass.getName());
+                        paramJson.put("thing2", thing2);
+
+                        JSONObject const4 = new JSONObject();
                         if(status == 1){
-                            paramJson.put("const4", "进校");
+                            const4.put("value", "进校");
                         }else{
-                            paramJson.put("const4", "出校");
+                            const4.put("value", "出校");
                         }
 
+                        paramJson.put("const4", const4);
+
                         weChatSendMessageDto.setContent(paramJson);
                         weChatService.sendTemplateMessage(weChatSendMessageDto);
                     }

+ 22 - 3
src/main/java/com/xjrsoft/module/job/AttenDanceWarnNoticeTask.java

@@ -1,5 +1,6 @@
 package com.xjrsoft.module.job;
 
+import cn.hutool.extra.spring.SpringUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.xjrsoft.common.utils.WeChatUtil;
@@ -10,7 +11,10 @@ import com.xjrsoft.module.attendance.service.IAttendanceRuleCategoryService;
 import com.xjrsoft.module.concat.service.IXjrUserService;
 import com.xjrsoft.module.organization.dto.WeChatSendMessageDto;
 import com.xjrsoft.module.organization.service.IWeChatService;
+import com.xjrsoft.module.system.entity.WechatMessageLog;
+import com.xjrsoft.module.system.service.IWechatMessageLogService;
 import com.xjrsoft.module.teacher.entity.XjrUser;
+import com.yomahub.liteflow.util.JsonUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -19,13 +23,14 @@ import org.springframework.stereotype.Component;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
 /**
- * 考勤预警通知
+ * 考勤预警通知,提醒教师和学生是否该上课等
  * @author dzx
  * @date 2024年5月21日
  */
@@ -47,8 +52,16 @@ public class AttenDanceWarnNoticeTask {
     @Autowired
     private WeChatUtil weChatUtil;
 
+    @Autowired
+    private IWechatMessageLogService wechatMessageLogService;
+
     @Scheduled(cron = "0 */10 * * * ?")
     public void RefreshConnectionPool() {
+        String active = SpringUtil.getActiveProfile();
+        if(!"prod".equals(active)){
+            log.info("非正式环境,无法执行数据推送");
+            return;
+        }
         //获取当前时间
         LocalDateTime now = LocalDateTime.now();
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
@@ -78,8 +91,11 @@ public class AttenDanceWarnNoticeTask {
 
         //根据规则中的用户id查询出所有绑定了微信的学生和教师
         if(allTodyRule.isEmpty()){
+            log.info("未能查询出规则,不进行推送");
             return;
         }
+        List<WechatMessageLog> logList = new ArrayList<>();
+
         List<XjrUser> userList = getUserList(allTodyRule.keySet());
         for (XjrUser xjrUser : userList) {
             AttendanceRuleDetails ruleDetails = allTodyRule.get(xjrUser.getId());
@@ -102,10 +118,13 @@ public class AttenDanceWarnNoticeTask {
                 paramJson.put("const12", "出校");
             }
 
-
-
             weChatSendMessageDto.setContent(paramJson);
             weChatService.sendTemplateMessage(weChatSendMessageDto);
+
+        }
+
+        if(!logList.isEmpty()){
+            wechatMessageLogService.saveBatch(logList);
         }
     }
 

+ 85 - 28
src/main/java/com/xjrsoft/module/job/AttendanceMessageTask.java

@@ -5,6 +5,7 @@ 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.utils.VoToColumnUtil;
 import com.xjrsoft.common.utils.WeChatUtil;
 import com.xjrsoft.config.CommonPropertiesConfig;
 import com.xjrsoft.module.attendance.entity.AttendanceMessageSet;
@@ -23,8 +24,11 @@ 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.system.entity.WechatMessageLog;
+import com.xjrsoft.module.system.service.IWechatMessageLogService;
 import com.xjrsoft.module.teacher.entity.BaseTeacher;
 import com.xjrsoft.module.teacher.entity.XjrUser;
+import com.yomahub.liteflow.util.JsonUtil;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.annotation.Scheduled;
@@ -43,7 +47,7 @@ import java.util.Map;
 import java.util.stream.Collectors;
 
 /**
- * 考勤消息通知
+ * 考勤消息通知,给领导推送每个时段的考勤情况
  * @author dzx
  * @date 2024年6月7日
  */
@@ -77,6 +81,9 @@ public class AttendanceMessageTask {
     @Autowired
     private WeChatUtil weChatUtil;
 
+    @Autowired
+    private IWechatMessageLogService wechatMessageLogService;
+
     @Scheduled(cron = "0 */15 * * * ?")
     public void RefreshConnectionPool() {
         String active = SpringUtil.getActiveProfile();
@@ -84,12 +91,16 @@ public class AttendanceMessageTask {
             log.info("非正式环境,无法执行数据推送");
             return;
         }
+        doExecute();
+    }
+
+    public void doExecute(){
         LocalDateTime now = LocalDateTime.now();
         HolidayDate holidayDate = holidayDateService.getOne(
-                new QueryWrapper<HolidayDate>().lambda()
-                        .eq(HolidayDate::getDate, now.toLocalDate())
+            new QueryWrapper<HolidayDate>().lambda()
+            .eq(HolidayDate::getDate, now.toLocalDate())
         );
-        if(holidayDate.getWay() != null && holidayDate.getWay() != 0){
+        if(holidayDate != null && holidayDate.getWay() != null && holidayDate.getWay() != 0){
             log.info("非工作日,不需要提醒");
             return;
         }
@@ -97,9 +108,23 @@ public class AttendanceMessageTask {
         List<AttendanceRuleDetails> ruleDetails = ruleCategoryService.getTodayRules();
         //获取最近的时间
         LocalDateTime recentlyTime = getRecentlyTime(ruleDetails, now);
+        String wechatTemplate = weChatUtil.getAttendanceMessageTemplate();
+        WechatMessageLog log = wechatMessageLogService.getOne(
+                new QueryWrapper<WechatMessageLog>().lambda()
+                        .select(WechatMessageLog.class, x -> VoToColumnUtil.fieldsToColumns(WechatMessageLog.class).contains(x.getProperty()))
+                        .eq(WechatMessageLog::getSendTime, recentlyTime)
+                        .eq(WechatMessageLog::getTemplateId, wechatTemplate)
+        );
+        if(log != null){//已经推送过,不再进行推送
+            return;
+        }
+
+        WechatMessageLog messageLog = new WechatMessageLog();
+        messageLog.setTemplateId(wechatTemplate);
+        messageLog.setSendTime(recentlyTime);
 
         List<AttendanceMessageSet> list = messageSetService.list(
-            new QueryWrapper<AttendanceMessageSet>().lambda()
+                new QueryWrapper<AttendanceMessageSet>().lambda()
         );
         //判断是上午还是下午
         Integer timePeriod = null;
@@ -118,6 +143,8 @@ public class AttendanceMessageTask {
         DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
         String format = recentlyTime.format(formatter);
 
+
+
         for (AttendanceMessageSet messageSet : list) {
             if(!messageSet.getTimePeriod().contains(timePeriod + "")){
                 continue;
@@ -125,6 +152,8 @@ public class AttendanceMessageTask {
             //查询需要通知的人
             List<XjrUser> userList = userService.list(
                 new MPJLambdaWrapper<XjrUser>()
+                .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)
                 .eq(UserRoleRelation::getRoleId, messageSet.getRoleType())
@@ -137,14 +166,14 @@ public class AttendanceMessageTask {
             if(messageSet.getRoleType() != null && messageSet.getRoleType() == 2){
                 //教师总人数
                 long teacherCout = userService.count(
-                    new MPJLambdaWrapper<XjrUser>()
-                    .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId)
+                        new MPJLambdaWrapper<XjrUser>()
+                                .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId)
                 );
                 //查询进入记录,就是实际到校的人数
                 long outInRecords = teachertOutInRecordService.count(
-                    new MPJLambdaWrapper<TeacherOutInRecord>()
-                    .le(TeacherOutInRecord::getRecordTime, recentlyTime)
-                    .eq(TeacherOutInRecord::getStatus, 1)
+                        new MPJLambdaWrapper<TeacherOutInRecord>()
+                                .le(TeacherOutInRecord::getRecordTime, recentlyTime)
+                                .eq(TeacherOutInRecord::getStatus, 1)
                 );
 
                 //计算出勤率
@@ -154,14 +183,28 @@ public class AttendanceMessageTask {
                 }
 
                 WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
-                weChatSendMessageDto.setTemplateId(weChatUtil.getAttendanceMessageTemplate());
+                weChatSendMessageDto.setTemplateId(wechatTemplate);
                 JSONObject paramJson = new JSONObject();
 
-                paramJson.put("thing6", "教职工");
-                paramJson.put("time11", format);
-                paramJson.put("const23", timePeriodStr);
-                paramJson.put("character_string18", teacherCout - outInRecords);
-                paramJson.put("const3", divide.doubleValue());
+                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("character_string18", character_string18);
+
+                JSONObject const3 = new JSONObject();
+                const3.put("value", "出勤率 " + (divide.doubleValue() * 100) + "%");
+                paramJson.put("const3", const3);
 
                 weChatSendMessageDto.setContent(paramJson);
                 weChatSendMessageDto.setUrl(StrUtil.format("{}pages/attendance/teacher/index", commonPropertiesConfig.getDomainApp()));
@@ -174,14 +217,14 @@ public class AttendanceMessageTask {
             }else if(messageSet.getRoleType() != null && messageSet.getRoleType() == 3){
                 //教师总人数
                 long teacherCout = userService.count(
-                    new MPJLambdaWrapper<XjrUser>()
-                    .leftJoin(BaseStudent.class, BaseStudent::getUserId, XjrUser::getId)
+                        new MPJLambdaWrapper<XjrUser>()
+                                .leftJoin(BaseStudent.class, BaseStudent::getUserId, XjrUser::getId)
                 );
                 //查询进入记录,就是实际到校的人数
                 long outInRecords = studentOutInRecordService.count(
-                    new MPJLambdaWrapper<StudentOutInRecord>()
-                    .le(StudentOutInRecord::getRecordTime, recentlyTime)
-                    .eq(StudentOutInRecord::getStatus, 1)
+                        new MPJLambdaWrapper<StudentOutInRecord>()
+                                .le(StudentOutInRecord::getRecordTime, recentlyTime)
+                                .eq(StudentOutInRecord::getStatus, 1)
                 );
 
                 //计算出勤率
@@ -195,11 +238,25 @@ public class AttendanceMessageTask {
                 weChatSendMessageDto.setTemplateId(weChatUtil.getAttendanceMessageTemplate());
                 JSONObject paramJson = new JSONObject();
 
-                paramJson.put("thing6", "学生");
-                paramJson.put("time11", format);
-                paramJson.put("const23", timePeriodStr);
-                paramJson.put("character_string18", teacherCout - outInRecords);
-                paramJson.put("const3", divide.doubleValue());
+                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("character_string18", character_string18);
+
+                JSONObject const3 = new JSONObject();
+                const3.put("value", "出勤率 " + (divide.doubleValue() * 100) + "%");
+                paramJson.put("const3", const3);
 
                 weChatSendMessageDto.setContent(paramJson);
                 weChatSendMessageDto.setUrl(StrUtil.format("{}pages/attendance/class/index", commonPropertiesConfig.getDomainApp()));
@@ -211,13 +268,13 @@ public class AttendanceMessageTask {
                 }
             }
         }
-
+        wechatMessageLogService.save(messageLog);
     }
 
     LocalDateTime getRecentlyTime(List<AttendanceRuleDetails> ruleDetails, LocalDateTime now){
         List<LocalDateTime> result = new ArrayList<>();
         for (AttendanceRuleDetails ruleDetail : ruleDetails) {
-            if(ruleDetail.getIsAllowInOutSchool() != null && ruleDetail.getIsAllowInOutSchool() != 1
+            if(ruleDetail.getIsAllowInOutSchool() != null && ruleDetail.getIsAllowInOutSchool() == 1
                     && ruleDetail.getIsAttendance() != null && ruleDetail.getIsAttendance() == 1){
                 if(ruleDetail.getAmStartTime() != null){
                     LocalDateTime amStartTime = now.with(ruleDetail.getAmStartTime());

+ 65 - 0
src/main/java/com/xjrsoft/module/system/entity/WechatMessageLog.java

@@ -0,0 +1,65 @@
+package com.xjrsoft.module.system.entity;
+
+import com.baomidou.mybatisplus.annotation.FieldFill;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.Date;
+
+
+/**
+* @title: 微信消息发送记录
+* @Author dzx
+* @Date: 2024年6月11日
+* @Version 1.0
+*/
+@Data
+@TableName("wechat_message_log")
+@ApiModel(value = "微信消息发送记录对象", description = "微信消息发送记录")
+public class WechatMessageLog implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+
+    @ApiModelProperty("主键编号")
+    @TableId
+    private Long id;
+
+    @ApiModelProperty("创建人")
+    @TableField(fill = FieldFill.INSERT)
+    private Long createUserId;
+
+    @ApiModelProperty("创建时间")
+    @TableField(fill = FieldFill.INSERT)
+    private Date createDate;
+
+    @ApiModelProperty("删除标记")
+    @TableField(fill = FieldFill.INSERT)
+    @TableLogic
+    private Integer deleteMark;
+
+    @ApiModelProperty("有效标志")
+    @TableField(fill = FieldFill.INSERT)
+    private Integer enabledMark;
+
+    @ApiModelProperty("序号")
+    private Integer sortCode;
+
+    @ApiModelProperty("发送模板id")
+    private String templateId;
+
+    @ApiModelProperty("发送时间")
+    private LocalDateTime sendTime;
+
+    @ApiModelProperty("发送内容")
+    private String content;
+
+
+}

+ 16 - 0
src/main/java/com/xjrsoft/module/system/mapper/WechatMessageLogMapper.java

@@ -0,0 +1,16 @@
+package com.xjrsoft.module.system.mapper;
+
+import com.github.yulichang.base.MPJBaseMapper;
+import com.xjrsoft.module.system.entity.WechatMessageLog;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * @title: 微信消息发送记录
+ * @Author dzx
+ * @Date: 2024年6月11日
+ * @Version 1.0
+*/
+@Mapper
+public interface WechatMessageLogMapper extends MPJBaseMapper<WechatMessageLog> {
+
+}

+ 34 - 0
src/main/java/com/xjrsoft/module/system/service/IWechatMessageLogService.java

@@ -0,0 +1,34 @@
+package com.xjrsoft.module.system.service;
+
+import com.github.yulichang.base.MPJBaseService;
+import com.xjrsoft.module.system.entity.WechatMessageLog;
+
+import java.util.List;
+
+/**
+ * @title: 微信消息发送记录
+ * @Author dzx
+ * @Date: 2024年6月11日
+ * @Version 1.0
+*/
+
+public interface IWechatMessageLogService extends MPJBaseService<WechatMessageLog> {
+    /**
+    * 新增
+    *
+    */
+    Boolean add(WechatMessageLog wechatMessageLog);
+
+    /**
+    * 更新
+    *
+    */
+    Boolean update(WechatMessageLog wechatMessageLog);
+
+
+    /**
+    * 删除
+    *
+    */
+    Boolean delete(List<Long> ids);
+}

+ 43 - 0
src/main/java/com/xjrsoft/module/system/service/impl/WechatMessageLogServiceImpl.java

@@ -0,0 +1,43 @@
+package com.xjrsoft.module.system.service.impl;
+
+import com.github.yulichang.base.MPJBaseServiceImpl;
+import com.xjrsoft.module.system.entity.WechatMessageLog;
+import com.xjrsoft.module.system.mapper.WechatMessageLogMapper;
+import com.xjrsoft.module.system.service.IWechatMessageLogService;
+import lombok.AllArgsConstructor;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.List;
+
+/**
+ * @title: 微信消息发送记录
+ * @Author dzx
+ * @Date: 2024年6月11日
+ * @Version 1.0
+*/
+@Service
+@AllArgsConstructor
+public class WechatMessageLogServiceImpl extends MPJBaseServiceImpl<WechatMessageLogMapper, WechatMessageLog> implements IWechatMessageLogService {
+
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean add(WechatMessageLog wechatMessageLog) {
+        this.baseMapper.insert(wechatMessageLog);
+        return true;
+    }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean update(WechatMessageLog wechatMessageLog) {
+        this.baseMapper.updateById(wechatMessageLog);
+        return true;
+    }
+
+    @Transactional(rollbackFor = Exception.class)
+    public Boolean delete(List<Long> ids) {
+        this.baseMapper.deleteBatchIds(ids);
+        return true;
+    }
+}

+ 2 - 2
src/main/resources/application-pre.yml

@@ -118,9 +118,9 @@ xjrsoft:
   weChatMessageTemplate:
     commonTemplate: qmpXORPM1Cocqn503Qa4OkNNQ0uxlj2-ed9m6uWO-v4
     assessmentTemplate: ehYfXni7exZUmt6dJX4Ukbm9ETarFfKLfXVYwNnjKMc
-    attendanceMessageTemplate: uPPJkWOSronnB_GJolcnatrQzGjJREIKL7JZzOieoew
+    attendanceMessageTemplate: o-KboOcqcJ3YpjPN2xwgM_NcjN-0yzwWlDDXYfTM0Q4
     outInTemplate: ERkMebHjsziZO6WBrlzsbENiEuRR4vrlhJw5LR4aDr8
-    attenDanceWarnTemplate: Fg4AWVQRGernl0PiJQ8gRgCUFHEGZuizlClQNuVhqu4
+    attenDanceWarnTemplate: vdFsy-QUk5L56OmGgBsRC_RB-45qRTkLzMPQotV2A4Y
   appletWeChat:
     appKey: wx72e974483a9174e4
     appSecret: 3bbe99f6964c9f4fc11a8aa1224ac4b3

+ 1 - 1
src/main/resources/application.yml

@@ -5,7 +5,7 @@ server:
 spring:
   # 环境 dev|pre|prod
   profiles:
-    active: dev
+    active: prod
   # jackson时间格式化
   jackson:
     time-zone: GMT+8

+ 0 - 0
src/main/resources/sqlScript/200240428_sql.sql → src/main/resources/sqlScript/20240428_sql.sql


+ 0 - 0
src/main/resources/sqlScript/200240508_sql.sql → src/main/resources/sqlScript/20240508_sql.sql


+ 297 - 8
src/test/java/com/xjrsoft/module/job/AttendanceMessageTaskTest.java

@@ -1,26 +1,315 @@
 package com.xjrsoft.module.job;
 
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.http.HttpUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.xjrsoft.XjrSoftApplication;
+import com.xjrsoft.common.enums.WeChatType;
+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.system.entity.WechatMessageLog;
+import com.xjrsoft.module.system.service.IWechatMessageLogService;
+import com.xjrsoft.module.teacher.entity.BaseTeacher;
+import com.xjrsoft.module.teacher.entity.XjrUser;
 import org.junit.jupiter.api.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
 
-import java.time.DayOfWeek;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDateTime;
-import java.time.format.TextStyle;
-import java.util.Locale;
-
-import static org.junit.jupiter.api.Assertions.*;
+import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
 
 /**
  * @author dzx
  * @date 2024/5/23
  */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = XjrSoftApplication.class)
 class AttendanceMessageTaskTest {
+    @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;
+
+    @Autowired
+    private IWechatMessageLogService wechatMessageLogService;
+
 
     @Test
     void test(){
+        doExecute();
+    }
+
+    public void doExecute(){
         LocalDateTime now = LocalDateTime.now();
-        DayOfWeek dayOfWeek = now.getDayOfWeek();
+        HolidayDate holidayDate = holidayDateService.getOne(
+                new QueryWrapper<HolidayDate>().lambda()
+                        .eq(HolidayDate::getDate, now.toLocalDate())
+        );
+        if(holidayDate != null && holidayDate.getWay() != null && holidayDate.getWay() != 0){
+            return;
+        }
+        //查询今天的考勤规则
+        List<AttendanceRuleDetails> ruleDetails = ruleCategoryService.getTodayRules();
+        //获取最近的时间
+        LocalDateTime recentlyTime = getRecentlyTime(ruleDetails, now);
+        String wechatTemplate = weChatUtil.getAttendanceMessageTemplate();
+        WechatMessageLog log = wechatMessageLogService.getOne(
+                new QueryWrapper<WechatMessageLog>().lambda()
+                        .select(WechatMessageLog.class, x -> VoToColumnUtil.fieldsToColumns(WechatMessageLog.class).contains(x.getProperty()))
+                        .eq(WechatMessageLog::getSendTime, recentlyTime)
+                        .eq(WechatMessageLog::getTemplateId, wechatTemplate)
+        );
+        if(log != null){//已经推送过,不再进行推送
+            return;
+        }
+
+        WechatMessageLog messageLog = new WechatMessageLog();
+        messageLog.setTemplateId(wechatTemplate);
+        messageLog.setSendTime(recentlyTime);
+
+        List<AttendanceMessageSet> list = messageSetService.list(
+                new QueryWrapper<AttendanceMessageSet>().lambda()
+        );
+        //判断是上午还是下午
+        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");
+        String format = recentlyTime.format(formatter);
+
+
+
+        for (AttendanceMessageSet messageSet : list) {
+            if(!messageSet.getTimePeriod().contains(timePeriod + "")){
+                continue;
+            }
+            //查询需要通知的人
+            List<XjrUser> userList = userService.list(
+                    new MPJLambdaWrapper<XjrUser>()
+                            .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)
+                            .eq(UserRoleRelation::getRoleId, messageSet.getRoleType())
+                            .eq(AttendanceMessageUserRelation::getAttendanceMessageSetId, messageSet.getId())
+            );
+            //没有需要通知的,直接跳过
+            if(userList.isEmpty()){
+                continue;
+            }
+            if(messageSet.getRoleType() != null && messageSet.getRoleType() == 2){
+                //教师总人数
+                long teacherCout = userService.count(
+                        new MPJLambdaWrapper<XjrUser>()
+                                .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId)
+                );
+                //查询进入记录,就是实际到校的人数
+                long outInRecords = teachertOutInRecordService.count(
+                        new MPJLambdaWrapper<TeacherOutInRecord>()
+                                .le(TeacherOutInRecord::getRecordTime, recentlyTime)
+                                .eq(TeacherOutInRecord::getStatus, 1)
+                );
+
+                //计算出勤率
+                BigDecimal divide = BigDecimal.ZERO;
+                if(teacherCout != 0){
+                    divide = BigDecimal.valueOf(outInRecords).divide(BigDecimal.valueOf(teacherCout), 4, RoundingMode.HALF_UP);
+                }
+
+                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);
 
-        String dayName = dayOfWeek.getDisplayName(TextStyle.FULL, Locale.getDefault());
-        System.out.println("今天是:" + dayOfWeek.name());
+                JSONObject character_string18 = new JSONObject();
+                character_string18.put("value", teacherCout - outInRecords);
+                paramJson.put("character_string18", character_string18);
+
+                JSONObject const3 = new JSONObject();
+                const3.put("value", "出勤率  99%");
+                paramJson.put("const3", const3);
+
+                weChatSendMessageDto.setContent(paramJson);
+                weChatSendMessageDto.setUrl(StrUtil.format("{}pages/attendance/teacher/index", commonPropertiesConfig.getDomainApp()));
+
+                for (XjrUser xjrUser : userList) {
+                    weChatSendMessageDto.setMsgId(xjrUser.getId().toString());
+                    weChatSendMessageDto.setUserId(xjrUser.getOpenId());
+                    weChatService.sendTemplateMessage(weChatSendMessageDto);
+                }
+            }else if(messageSet.getRoleType() != null && messageSet.getRoleType() == 3){
+                //教师总人数
+                long teacherCout = userService.count(
+                        new MPJLambdaWrapper<XjrUser>()
+                                .leftJoin(BaseStudent.class, BaseStudent::getUserId, XjrUser::getId)
+                );
+                //查询进入记录,就是实际到校的人数
+                long outInRecords = studentOutInRecordService.count(
+                        new MPJLambdaWrapper<StudentOutInRecord>()
+                                .le(StudentOutInRecord::getRecordTime, recentlyTime)
+                                .eq(StudentOutInRecord::getStatus, 1)
+                );
+
+                //计算出勤率
+                BigDecimal divide = BigDecimal.ZERO;
+                if(teacherCout != 0){
+                    divide = BigDecimal.valueOf(outInRecords).divide(BigDecimal.valueOf(teacherCout), 4, RoundingMode.HALF_UP);
+                }
+
+
+                WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
+                weChatSendMessageDto.setTemplateId(weChatUtil.getAttendanceMessageTemplate());
+                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("character_string18", character_string18);
+
+                JSONObject const3 = new JSONObject();
+                const3.put("value", "出勤率  99%");
+                paramJson.put("const3", const3);
+
+                weChatSendMessageDto.setContent(paramJson);
+                weChatSendMessageDto.setUrl(StrUtil.format("{}pages/attendance/class/index", commonPropertiesConfig.getDomainApp()));
+
+                for (XjrUser xjrUser : userList) {
+                    weChatSendMessageDto.setMsgId(xjrUser.getId().toString());
+                    weChatSendMessageDto.setUserId(xjrUser.getOpenId());
+                    weChatService.sendTemplateMessage(weChatSendMessageDto);
+                }
+            }
+        }
+        wechatMessageLogService.save(messageLog);
+    }
+
+
+
+    LocalDateTime getRecentlyTime(List<AttendanceRuleDetails> ruleDetails, LocalDateTime now){
+        List<LocalDateTime> 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());
+                    result.add(amStartTime);
+                }
+                if(ruleDetail.getPmStartTime() != null){
+                    LocalDateTime pmStartTime = now.with(ruleDetail.getPmStartTime());
+                    result.add(pmStartTime);
+                }
+
+                if(ruleDetail.getEveningStartTime() != null){
+                    LocalDateTime eveningStartTime = now.with(ruleDetail.getEveningStartTime());
+                    result.add(eveningStartTime);
+                }
+            }
+        }
+        if(result.isEmpty()){
+            return null;
+        }
+        Map<Long, LocalDateTime> timeMap = new HashMap<>();
+        for (LocalDateTime localDateTime : result) {
+            long between = ChronoUnit.SECONDS.between(now, localDateTime);
+            timeMap.put(Math.abs(between), localDateTime);
+        }
+        List<Long> collect = timeMap.keySet().stream().collect(Collectors.toList());
+        Collections.sort(collect, Long::compare);
+
+        return timeMap.get(collect.get(0));
+    }
+
+
+    @Test
+    void getRid(){
+        String url = "https://api.weixin.qq.com/cgi-bin/openapi/rid/get?access_token=" + weChatUtil.getToken(WeChatType.WEWEB);
+        JSONObject rid = new JSONObject();
+        rid.put("rid", "6667fb56-0c3a8942-466e7d5e");
+        String result = HttpUtil.post(url, JSONObject.toJSONString(rid));
+        System.out.print(result);
     }
 }

+ 49 - 0
src/test/java/com/xjrsoft/module/liteflow/node/ImportStudentFaceNodeTest.java

@@ -0,0 +1,49 @@
+package com.xjrsoft.module.liteflow.node;
+
+import cn.hutool.core.convert.Convert;
+import com.xjrsoft.XjrSoftApplication;
+import com.xjrsoft.module.hikvision.mapper.HikvisionDataMapper;
+import com.xjrsoft.module.hikvision.util.FaceImportUtil;
+import com.xjrsoft.module.personnel.entity.StundentFaceProcess;
+import com.xjrsoft.module.personnel.service.IStundentFaceProcessService;
+import com.xjrsoft.module.teacher.mapper.FaceImportMapper;
+import org.junit.jupiter.api.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.junit4.SpringRunner;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * @author dzx
+ * @date 2024/6/11
+ */
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = XjrSoftApplication.class)
+class ImportStudentFaceNodeTest {
+    @Autowired
+    private IStundentFaceProcessService stundentFaceProcessService;
+
+    @Autowired
+    private HikvisionDataMapper hikvisionDataMapper;
+
+    @Autowired
+    private FaceImportMapper faceImportMapper;
+    @Test
+    void test(){
+        Long formId = 1799211798557667328L;
+        if (formId != null) {
+            String fileUrl = faceImportMapper.GetStudentHikvisionImgById(formId);
+            // 数据处理
+            StundentFaceProcess dataObj = stundentFaceProcessService.getById(formId);
+            dataObj.setStatus(1);
+            dataObj.setExamStatus(1);
+            String result = FaceImportUtil.ImportStudentFace(hikvisionDataMapper.getStudentHikvisionId(dataObj.getUserId()), fileUrl);
+            dataObj.setHikvisionResult(result);
+            stundentFaceProcessService.updateById(dataObj);
+
+
+        }
+    }
+}