Kaynağa Gözat

Merge branch 'pre'

dzx 1 yıl önce
ebeveyn
işleme
2e300e059b

+ 5 - 4
src/main/java/com/xjrsoft/module/attendance/controller/StatisticsController.java

@@ -128,7 +128,7 @@ public class StatisticsController {
             if(statisticsVo.getAllCount() != null && statisticsVo.getAllCount() != 0){
                 divide = BigDecimal.valueOf(statisticsVo.getActualCount()).divide(BigDecimal.valueOf(statisticsVo.getAllCount()), 4, RoundingMode.HALF_UP);
             }
-            statisticsVo.setAttendanceRate(divide.doubleValue());
+            statisticsVo.setAttendanceRate(divide.doubleValue() + "");
         }
 
         return RT.ok(statisticsVo);
@@ -172,7 +172,8 @@ public class StatisticsController {
                             .eq(StudentOutInRecord::getStatus, 1)
             );
             //实到人数
-            statisticsVo.setActualCount(Long.valueOf(outInRecords.size()));
+            List<Long> collect = outInRecords.stream().map(StudentOutInRecord::getUserId).collect(Collectors.toList());
+            statisticsVo.setActualCount(Long.valueOf(collect.size()));
 
             //查询教师请假人数
             Long leaveCount = studentLeaveService.getLeaveCount(startTime, endTime, dto);
@@ -200,9 +201,9 @@ public class StatisticsController {
                 //最后通过总人数-实到人数-请假人数计算出缺勤人数
                 statisticsVo.setAbsenteeismCount(statisticsVo.getAllCount() - statisticsVo.getLeaveCount() - statisticsVo.getActualCount());
                 BigDecimal divide = BigDecimal.valueOf(statisticsVo.getActualCount()).divide(BigDecimal.valueOf(statisticsVo.getAllCount()), 4, RoundingMode.HALF_UP);
-                statisticsVo.setAttendanceRate(divide.doubleValue());
+                statisticsVo.setAttendanceRate(divide.doubleValue() + "");
             }else{
-                statisticsVo.setAttendanceRate(0D);
+                statisticsVo.setAttendanceRate("0");
                 statisticsVo.setAbsenteeismCount(0L);
             }
 

+ 3 - 3
src/main/java/com/xjrsoft/module/attendance/controller/StudentStatisticsController.java

@@ -151,7 +151,7 @@ public class StudentStatisticsController {
                 if(record.getStudentCount() != null && record.getStudentCount() != 0){
                     divide = BigDecimal.valueOf(record.getActualCount()).divide(BigDecimal.valueOf(record.getStudentCount()), 4, RoundingMode.HALF_UP);
                 }
-                record.setAttendanceRate(divide.doubleValue());
+                record.setAttendanceRate(divide.doubleValue() + "");
             }
         }
         PageOutput<ClassStatisticsVo> pageOutput = ConventPage.getPageOutput(attendancePage, ClassStatisticsVo.class);
@@ -302,7 +302,7 @@ public class StudentStatisticsController {
                 if(record.getStudentCount() != null && record.getStudentCount() != 0){
                     divide = BigDecimal.valueOf(record.getActualCount()).divide(BigDecimal.valueOf(record.getStudentCount()), 4, RoundingMode.HALF_UP);
                 }
-                record.setAttendanceRate(divide.doubleValue());
+                record.setAttendanceRate(divide.doubleValue() + "");
             }
         }
         PageOutput<ClassStatisticsVo> pageOutput = ConventPage.getPageOutput(attendancePage, ClassStatisticsVo.class);
@@ -376,7 +376,7 @@ public class StudentStatisticsController {
 
                 //计算出勤率
                 BigDecimal divide = BigDecimal.valueOf(record.getActualCount()).divide(BigDecimal.valueOf(record.getStudentCount()), 4, RoundingMode.HALF_UP);
-                record.setAttendanceRate(divide.doubleValue());
+                record.setAttendanceRate(divide.doubleValue() + "");
             }
         }
         PageOutput<ClassStatisticsVo> pageOutput = ConventPage.getPageOutput(attendancePage, ClassStatisticsVo.class);

+ 1 - 1
src/main/java/com/xjrsoft/module/attendance/entity/AttendanceRuleDetails.java

@@ -227,7 +227,7 @@ public class AttendanceRuleDetails implements Serializable {
     private Time returnEndTime;
 
     @ApiModelProperty("节假日迟到旷课时间")
-    private Time holidaysLateMinutes;
+    private Integer holidaysLateMinutes;
 
     @ApiModelProperty("为节假日前一天时放学时间")
     private Time holidaysEndTime;

+ 1 - 1
src/main/java/com/xjrsoft/module/attendance/vo/ClassStatisticsVo.java

@@ -46,7 +46,7 @@ public class ClassStatisticsVo {
     private Integer absenteeismCount;
 
     @ApiModelProperty("出勤率")
-    private Double attendanceRate;
+    private String attendanceRate;
 
     @ApiModelProperty("应该离校人数")
     private Integer ygLeaveSchoolCount;

+ 1 - 1
src/main/java/com/xjrsoft/module/attendance/vo/StudentStatisticsVo.java

@@ -36,6 +36,6 @@ public class StudentStatisticsVo {
     private Long absenteeismCount;
 
     @ApiModelProperty("出勤率")
-    private Double attendanceRate;
+    private String attendanceRate;
 
 }

+ 1 - 1
src/main/java/com/xjrsoft/module/attendance/vo/TeacherStatisticsVo.java

@@ -36,7 +36,7 @@ public class TeacherStatisticsVo {
     private Long absenteeismCount;
 
     @ApiModelProperty("出勤率")
-    private Double attendanceRate;
+    private String attendanceRate;
 
     @ApiModelProperty("旷课人数")
     private Integer playTruantCount;

+ 3 - 0
src/main/java/com/xjrsoft/module/base/entity/CourseBookInfo.java

@@ -11,5 +11,8 @@ public class CourseBookInfo {
     private String bookName;
 
     private String bookId;
+    private String issn;
+    private String editorInChief;
+    private String version;
 
 }

+ 2 - 0
src/main/java/com/xjrsoft/module/concat/controller/ConcatController.java

@@ -6,6 +6,7 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import com.xjrsoft.common.enums.DeleteMark;
 import com.xjrsoft.common.model.result.RT;
+import com.xjrsoft.common.utils.TreeUtil;
 import com.xjrsoft.module.concat.dto.ConcatTreeDto;
 import com.xjrsoft.module.concat.service.IXjrUserService;
 import com.xjrsoft.module.concat.vo.ConcatTreeVo;
@@ -21,6 +22,7 @@ import org.springframework.web.bind.annotation.RestController;
 
 import java.util.ArrayList;
 import java.util.List;
+import java.util.Objects;
 
 /**
 * @title: 通讯录

+ 24 - 18
src/main/java/com/xjrsoft/module/hikvision/util/DataUtil.java

@@ -255,39 +255,39 @@ public class DataUtil {
     }
 
     public Map<String, String> insertStudentOne(String tableName, Map<String, String> tableData){
-        String sql = "SELECT t1.id,t1.name,CONCAT(t3.id,'-',replace(t4.name,'级',''),'-',t3.class_type,'-',t2.stduy_status)," +
-                " t1.user_name,t1.gender,DATE_FORMAT(t1.birth_date, '%Y-%m-%d'),t1.mobile,t1.email,t1.credential_type,t1.credential_number FROM xjr_user t1" +
+        String sql = "SELECT t1.id,t1.name,CONCAT(t3.id,'-',replace(t4.name,'级',''),'-',t3.class_type,'-',t2.stduy_status) as orgIndexCode," +
+                " t1.user_name,t1.gender,DATE_FORMAT(t1.birth_date, '%Y-%m-%d') as birthday,t1.mobile,t1.email,t1.credential_type,t1.credential_number FROM xjr_user t1" +
                 " INNER JOIN base_student_school_roll t2 ON t1.id = t2.user_id" +
                 " INNER JOIN base_class t3 ON t2.class_id = t3.id" +
                 " INNER JOIN base_grade t4 ON t3.grade_id = t4.id" +
-                " WHERE t1.delete_mark = 0 AND t2.delete_mark = 0 AND t3.class_type IS NOT NULL";
+                " WHERE t1.delete_mark = 0 AND t2.delete_mark = 0" +
+                " AND t3.class_type IS NOT NULL";
         List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql, String[].class);
         Map<Integer, String> clientMap = new HashMap<>();
 
-        String apiPath = "/api/resource/v2/person/single/add";
+
         Map<String, String> idMap = new HashMap<>();
         JsonParser jsonParser = new JsonParser();
         ApiUtil apiUtil = new ApiUtil();
         Map<String, String> header = new HashMap<>();
         header.put("tagId", "insert_student");
 
-        for(int i = 1; i < list.size(); i ++){
-            String[] el = SqlRunnerAdapterUtil.convertMapToStringArray(list.get(i));
-            if(tableData != null && tableData.containsKey(el[0])){
-                continue;
-            }
+        for(int i = 0; i < list.size(); i ++){
+            Map<String, Object> objectMap = list.get(i);
+            String apiPath = "/api/resource/v2/person/single/add";
+
             JsonObject paramJson = new JsonObject();
             paramJson.addProperty("clientId", i);
-            paramJson.addProperty("personId", el[0]);
-            paramJson.addProperty("personName", el[1]);
-            paramJson.addProperty("orgIndexCode", el[2]);
-            paramJson.addProperty("phoneNo", el[6]);
-            paramJson.addProperty("jobNo", el[3]);
-            paramJson.addProperty("birthday", el[5]);
+            paramJson.addProperty("personId", objectMap.get("id").toString());
+            paramJson.addProperty("personName", objectMap.get("name").toString());
+            paramJson.addProperty("orgIndexCode", objectMap.get("orgIndexCode").toString());
+            paramJson.addProperty("phoneNo", objectMap.get("mobile").toString());
+            paramJson.addProperty("jobNo", objectMap.get("user_name").toString());
+            paramJson.addProperty("birthday", objectMap.get("birthday").toString());
             paramJson.addProperty("personType", 2);
 
             int gender;
-            switch (el[4]) {
+            switch (objectMap.get("gender").toString()) {
                 case "SB10001":
                     gender = 1;
                     break;
@@ -300,13 +300,19 @@ public class DataUtil {
             }
             paramJson.addProperty("gender", gender);
 
-            clientMap.put(i, el[0]);
+            if(tableData != null && tableData.containsKey(objectMap.get("id").toString())){
+                apiPath = "/api/resource/v1/person/single/update";
+                apiUtil.doPost(apiPath, paramJson.toString(), null, header);
+                continue;
+            }
+
+            clientMap.put(i, objectMap.get("id").toString());
             String result = apiUtil.doPost(apiPath, paramJson.toString(), null, header);
             JsonElement parse = jsonParser.parse(result);
             JsonObject resultJson = parse.getAsJsonObject();
             if("0".equals(resultJson.get("code").getAsString()) && "success".equals(resultJson.get("msg").getAsString())){
                 JsonObject array = resultJson.get("data").getAsJsonObject();
-                idMap.put(el[0], array.get("personId").getAsString());
+                idMap.put(objectMap.get("id").toString(), array.get("personId").getAsString());
             }
         }
 

+ 95 - 37
src/main/java/com/xjrsoft/module/job/AttenDanceWarnNoticeTask.java

@@ -4,6 +4,7 @@ import cn.hutool.core.util.IdUtil;
 import cn.hutool.extra.spring.SpringUtil;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.common.utils.WeChatUtil;
 import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails;
 import com.xjrsoft.module.attendance.entity.AttendanceUserRelation;
@@ -12,8 +13,6 @@ 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.outint.service.IStudentOutInRecordService;
-import com.xjrsoft.module.outint.service.ITeacherOutInRecordService;
 import com.xjrsoft.module.system.entity.WechatMessageLog;
 import com.xjrsoft.module.system.service.IWechatMessageLogService;
 import com.xjrsoft.module.teacher.entity.XjrUser;
@@ -25,11 +24,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.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * 考勤预警通知,提醒教师和学生是否该上课等
@@ -57,11 +59,11 @@ public class AttenDanceWarnNoticeTask {
     @Autowired
     private IWechatMessageLogService wechatMessageLogService;
 
-    @Scheduled(cron = "0 */10 * * * ?")
+    @Scheduled(cron = "0 */5 * * * ?")
     public void RefreshConnectionPool() {
         String active = SpringUtil.getActiveProfile();
-        if(!"prod".equals(active)){
-            log.info("非正式环境,无法执行数据推送");
+        if("dev".equals(active)){
+            log.info("测试环境,无法执行数据推送");
             return;
         }
         //获取当前时间
@@ -91,20 +93,35 @@ public class AttenDanceWarnNoticeTask {
             allUserStatus.put(userRelation.getUserId(), userRelation);
         }
 
-        //判断所有当前时间下,哪几条规则需要进行提醒
-        Map<Long, Integer> ruleDetailsJudgeMap = judgeExecuteNotice(now, ruleDetailsList);
-
-        //查询
-
         //根据规则中的用户id查询出所有绑定了微信的学生和教师
         if(allTodyRule.isEmpty()){
             log.info("未能查询出规则,不进行推送");
             return;
         }
+
+        //获取最近的时间
+        LocalDateTime recentlyTime = getRecentlyTime(ruleDetailsList, now);
+        if(recentlyTime.getHour() != now.getHour() && Math.abs(recentlyTime.getMinute() - now.getMinute()) <= 2){
+            log.info("未到时间,不进行推送");
+            return;
+        }
         String wechatTemplate = weChatUtil.getAttenDanceWarnTemplate();
+        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;
+        }
+
+        //判断所有当前时间下,哪几条规则需要进行提醒
+        Map<Long, Integer> ruleDetailsJudgeMap = judgeExecuteNotice(now, ruleDetailsList, recentlyTime);
+
         WechatMessageLog messageLog = new WechatMessageLog();
         messageLog.setTemplateId(wechatTemplate);
-//        messageLog.setSendTime(recentlyTime);
+        messageLog.setSendTime(recentlyTime);
 
         List<XjrUser> userList = getUserList(allTodyRule.keySet());
         for (XjrUser xjrUser : userList) {
@@ -113,10 +130,6 @@ public class AttenDanceWarnNoticeTask {
             if(status == 0){
                 continue;
             }
-            AttendanceUserRelation userRelation = allUserStatus.get(xjrUser.getId());
-            if(userRelation.getAttendanceTime().toLocalDate().isEqual(now.toLocalDate())){
-
-            }
 
             WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
             weChatSendMessageDto.setUserId(xjrUser.getOpenId());
@@ -134,9 +147,17 @@ public class AttenDanceWarnNoticeTask {
 
             JSONObject const12 = new JSONObject();
             if(status == 1){
-                const12.put("value", "进校");
+                const12.put("value", "未打卡");
             }else{
-                const12.put("value", "出校");
+                const12.put("value", "待打卡");
+            }
+            //查询这个用户最新的考勤状态
+            AttendanceUserRelation userRelation = allUserStatus.get(xjrUser.getId());
+            if(userRelation != null
+                    && userRelation.getAttendanceTime() !=null
+                    && userRelation.getAttendanceTime().toLocalDate().isEqual(now.toLocalDate())
+                    && "到校".equals(userRelation.getAttendanceStatus())){
+                const12.put("value", "已打卡");
             }
             paramJson.put("const12", const12);
 
@@ -155,53 +176,58 @@ public class AttenDanceWarnNoticeTask {
      * 判断所有规则,哪些需要发送
      * @param judgeTime
      * @param ruleDetailsList
-     * @return 0:不需要提醒,-1:待打卡,1:未打卡
+     * @return 0:不需要提醒,1:未打卡,2:待打卡
      */
-    Map<Long, Integer> judgeExecuteNotice(LocalDateTime judgeTime, List<AttendanceRuleDetails> ruleDetailsList){
+    Map<Long, Integer> judgeExecuteNotice(LocalDateTime judgeTime, List<AttendanceRuleDetails> ruleDetailsList, LocalDateTime recentlyTime){
         Map<Long, Integer> result = new HashMap<>();
         for (AttendanceRuleDetails ruleDetails : ruleDetailsList) {
-            if(ruleDetails.getIsAllowInOutSchool() != null && ruleDetails.getIsAllowInOutSchool() != 1
+            if(ruleDetails.getIsAllowInOutSchool() != null && ruleDetails.getIsAllowInOutSchool() == 1
                     && ruleDetails.getIsAttendance() != null && ruleDetails.getIsAttendance() == 1){
                 if(ruleDetails.getAmStartTime() != null){
                     LocalDateTime amStartTime = judgeTime.with(ruleDetails.getAmStartTime().toLocalTime());
-                    long amBetween = ChronoUnit.MINUTES.between(judgeTime, amStartTime);
-                    if(amBetween == ruleDetails.getAgoMinutes()){
-                        result.put(ruleDetails.getId(), - 1);
-                    }else if(amBetween == ruleDetails.getOverMinutes()){
-                        result.put(ruleDetails.getId(), - 1);
+                    if(recentlyTime.isEqual(amStartTime)){
+                        Long amBetween = ChronoUnit.MINUTES.between(judgeTime, amStartTime);
+                        if(judgeTime.isBefore(amStartTime) && amBetween >= ruleDetails.getAgoMinutes() - 1 && amBetween <= ruleDetails.getAgoMinutes() + 1){//相差分钟数小于0
+                            result.put(ruleDetails.getId(), 1);
+                        }else if(judgeTime.isAfter(amStartTime) && amBetween >= ruleDetails.getOverMinutes() - 1 && amBetween <= ruleDetails.getOverMinutes() + 1){
+                            result.put(ruleDetails.getId(), 2);
+                        }
                     }
                 }
                 if(ruleDetails.getPmStartTime() != null){
                     LocalDateTime pmStartTime = judgeTime.with(ruleDetails.getPmStartTime().toLocalTime());
-                    long pmBetween = ChronoUnit.MINUTES.between(judgeTime, pmStartTime);
-                    if(pmBetween == ruleDetails.getAgoMinutes()){
-                        result.put(ruleDetails.getId(), - 1);
-                    }else if(pmBetween == ruleDetails.getOverMinutes()){
-                        result.put(ruleDetails.getId(), - 1);
+                    if(recentlyTime.isEqual(pmStartTime)){
+                        Long pmBetween = ChronoUnit.MINUTES.between(judgeTime, pmStartTime);
+                        if(judgeTime.isBefore(pmStartTime) && pmBetween >= ruleDetails.getAgoMinutes() - 1 && pmBetween <= ruleDetails.getAgoMinutes() + 1){
+                            result.put(ruleDetails.getId(), 1);
+                        }else if(judgeTime.isAfter(pmStartTime) && pmBetween >= ruleDetails.getOverMinutes() - 1 && pmBetween <= ruleDetails.getOverMinutes() + 1){
+                            result.put(ruleDetails.getId(), 2);
+                        }
                     }
                 }
 
                 if(ruleDetails.getEveningStartTime() != null){
                     LocalDateTime eveningStartTime = judgeTime.with(ruleDetails.getEveningStartTime().toLocalTime());
-                    long eveningBetween = ChronoUnit.MINUTES.between(judgeTime, eveningStartTime);
-                    if(eveningBetween == ruleDetails.getAgoMinutes()){
-                        result.put(ruleDetails.getId(), - 1);
-                    }else if(eveningBetween == ruleDetails.getOverMinutes()){
-                        result.put(ruleDetails.getId(), - 1);
+                    if(recentlyTime.isEqual(eveningStartTime)){
+                        Long eveningBetween = ChronoUnit.MINUTES.between(judgeTime, eveningStartTime);
+                        if(judgeTime.isBefore(eveningStartTime) && eveningBetween >= ruleDetails.getAgoMinutes() - 1 && eveningBetween <= ruleDetails.getAgoMinutes() + 1){
+                            result.put(ruleDetails.getId(), 1);
+                        }else if(judgeTime.isAfter(eveningStartTime)  && eveningBetween >= ruleDetails.getOverMinutes() - 1 && eveningBetween <= ruleDetails.getOverMinutes() + 1){
+                            result.put(ruleDetails.getId(), 2);
+                        }
                     }
                 }
 
-
                 if(!result.containsKey(ruleDetails.getId())){
                     result.put(ruleDetails.getId(), 0);
                 }
             }else{
                 result.put(ruleDetails.getId(), 0);
             }
-
         }
         return result;
     }
+
     /**
      * 查询出所有用户信息(openId不为空的)
      * @param userIds 需要插叙的userid
@@ -215,6 +241,38 @@ public class AttenDanceWarnNoticeTask {
         );
     }
 
+    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().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<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));
+    }
 
 }

+ 5 - 5
src/main/java/com/xjrsoft/module/job/HikvisionBaseDataTask.java

@@ -43,8 +43,8 @@ public class HikvisionBaseDataTask {
             List<Map<String, Object>> maps = SqlRunnerAdapter.db().selectList(sql, HikvisionData.class);
             Set<String> tables = new HashSet<>();
             for (Map<String, Object> map : maps) {
-                HikvisionData jianyueData = SqlRunnerAdapterUtil.convertMapToEntity(map, HikvisionData.class);
-                tables.add(jianyueData.getTableName());
+                String[] strings = SqlRunnerAdapterUtil.convertMapToStringArray(map);
+                tables.add(strings[0]);
             }
             sql = "SELECT * FROM hikvision_data WHERE 0 = 0";
             List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql, HikvisionData.class);
@@ -52,11 +52,11 @@ public class HikvisionBaseDataTask {
             for (String table : tables) {
                 Map<String, String> tableData = new HashMap<>();
                 for (Map<String, Object> hikvision : list) {
-                    HikvisionData hikvisiondata = SqlRunnerAdapterUtil.convertMapToEntity(hikvision, HikvisionData.class);
-                    if(!table.equals(hikvisiondata.getTableName())){
+
+                    if(!table.equals(hikvision.get("table_name").toString())){
                         continue;
                     }
-                    tableData.put(hikvisiondata.getSourceId(), hikvisiondata.getHikvisionId());
+                    tableData.put(hikvision.get("source_id").toString(), hikvision.get("hikvision_id").toString());
                 }
                 dataMap.put(table, tableData);
             }

+ 0 - 4
src/main/java/com/xjrsoft/module/organization/controller/UserController.java

@@ -138,10 +138,6 @@ public class UserController {
 
     private final IUserPostRelationService userPostRelationService;
 
-    private final CommonPropertiesConfig propertiesConfig;
-
-    private final WorkflowExtraMapper workflowExtraMapper;
-
     private final RedisUtil redisUtil;
 
     private final IFileService fileService;

+ 242 - 9
src/main/java/com/xjrsoft/module/personnel/controller/TeacherFaceProcessController.java

@@ -1,40 +1,60 @@
 package com.xjrsoft.module.personnel.controller;
 
 import cn.dev33.satoken.annotation.SaCheckPermission;
+import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.core.toolkit.IdWorker;
+import com.baomidou.mybatisplus.core.toolkit.StringPool;
 import com.github.yulichang.toolkit.MPJWrappers;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import com.xjrsoft.common.enums.DeleteMark;
 import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.page.ConventPage;
 import com.xjrsoft.common.page.PageOutput;
+import com.xjrsoft.common.utils.FileZipUtil;
+import com.xjrsoft.common.utils.ImageUtil;
+import com.xjrsoft.common.utils.UploadUtil;
+import com.xjrsoft.common.utils.VoToColumnUtil;
+import com.xjrsoft.module.hikvision.util.ApiUtil;
+import com.xjrsoft.module.organization.entity.Department;
 import com.xjrsoft.module.organization.entity.UserDeptRelation;
 import com.xjrsoft.module.personnel.dto.AddTeacherFaceProcessDto;
 import com.xjrsoft.module.personnel.dto.TeacherFaceProcessPageDto;
 import com.xjrsoft.module.personnel.dto.UpdateTeacherFaceProcessDto;
+import com.xjrsoft.module.personnel.entity.FaceManagement;
 import com.xjrsoft.module.personnel.entity.TeacherFaceProcess;
+import com.xjrsoft.module.personnel.service.IFaceManagementService;
 import com.xjrsoft.module.personnel.service.ITeacherFaceProcessService;
 import com.xjrsoft.module.personnel.vo.TeacherFaceProcessPageVo;
 import com.xjrsoft.module.personnel.vo.TeacherFaceProcessVo;
 import com.xjrsoft.module.system.entity.DictionaryDetail;
 import com.xjrsoft.module.system.entity.File;
+import com.xjrsoft.module.system.service.IFileService;
 import com.xjrsoft.module.teacher.entity.XjrUser;
+import com.xjrsoft.module.teacher.service.ITeacherbaseManagerService;
+import com.xjrsoft.module.teacher.vo.XjrUserPageVo;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.AllArgsConstructor;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
 
 import javax.validation.Valid;
-import java.util.List;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.time.LocalDateTime;
+import java.util.*;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
 
 /**
 * @title: 人脸信息审核
@@ -51,6 +71,12 @@ public class TeacherFaceProcessController {
 
     private final ITeacherFaceProcessService teacherFaceProcessService;
 
+    private final ITeacherbaseManagerService teacherbaseManagerService;
+
+    private final IFaceManagementService faceManagementService;
+
+    private final IFileService fileService;
+
     @GetMapping(value = "/page")
     @ApiOperation(value="人脸信息审核列表(分页)")
     @SaCheckPermission("teacherfaceprocess:detail")
@@ -125,4 +151,211 @@ public class TeacherFaceProcessController {
 
     }
 
+    @PostMapping(value = "/batch-import")
+    @ApiOperation(value = "批量新增教师人脸")
+    @SaCheckPermission("stundentfaceprocess:batch-upload")
+    public RT<Boolean> batchUpload(@RequestParam("file") MultipartFile file) throws Exception {
+        List<XjrUserPageVo> list = teacherbaseManagerService.selectJoinList(XjrUserPageVo.class,
+                new MPJLambdaWrapper<XjrUser>()
+                        .distinct()
+                        .select(XjrUser::getId)
+                        .selectAs(Department::getId, XjrUserPageVo::getDeptId)
+                        .selectAs(Department::getName, XjrUserPageVo::getDeptIdCn)
+                        .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUserPageVo.class).contains(x.getProperty()))
+                        .leftJoin(UserDeptRelation.class, UserDeptRelation::getUserId, XjrUser::getId)
+                        .leftJoin(Department.class, Department::getId, UserDeptRelation::getDeptId)
+                        .eq(XjrUser::getDeleteMark, DeleteMark.NODELETE.getCode())
+                        .eq(Department::getDeleteMark, DeleteMark.NODELETE.getCode())
+        );
+        Map<String, XjrUserPageVo> teacherMap = new HashMap<>();
+        for (XjrUserPageVo teacher : list) {
+            teacherMap.put(teacher.getCredentialNumber(), teacher);
+        }
+
+        List<TeacherFaceProcess> faceList = teacherFaceProcessService.list(
+                new QueryWrapper<TeacherFaceProcess>().lambda()
+                        .eq(TeacherFaceProcess::getDeleteMark, DeleteMark.NODELETE.getCode())
+        );
+        Map<Long, TeacherFaceProcess> faceMap = new HashMap<>();
+        for (TeacherFaceProcess faceProcess : faceList) {
+            faceMap.put(faceProcess.getUserId(), faceProcess);
+        }
+
+        List<FaceManagement> faceManagementList = faceManagementService.list(
+                new QueryWrapper<FaceManagement>().lambda()
+                        .select(FaceManagement.class, face -> !face.getColumn().equals("registerBase64"))
+                        .select(FaceManagement.class, face -> !face.getColumn().equals("register_base64"))
+                        .eq(FaceManagement::getDeleteMark, DeleteMark.NODELETE.getCode())
+                        .eq(FaceManagement::getUserType, 1)
+        );
+        Map<Long, FaceManagement> faceManagementMap = new HashMap<>();
+        for (FaceManagement management : faceManagementList) {
+            faceManagementMap.put(management.getUserId(), management);
+        }
+        JsonParser parser = new JsonParser();
+
+        ApiUtil apiUtil = new ApiUtil();
+        ZipFile zipFile = FileZipUtil.convertToZipFile(file);
+        Enumeration<? extends ZipEntry> entries = zipFile.entries();
+        while (entries.hasMoreElements()){
+            ZipEntry entry = entries.nextElement();
+            String filename = entry.getName();
+            InputStream inputStream = zipFile.getInputStream(entry); //读取文件内容
+            String[] split = filename.split("\\.");
+            String idNumber = split[0].substring(split[0].length() - 18);
+            XjrUserPageVo teacherUser = teacherMap.get(idNumber);
+            if(teacherUser == null){
+                continue;
+            }
+            //将照片转换成base64
+            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+            byte[] buffer = new byte[4096];
+            int bytesRead;
+            while ((bytesRead = inputStream.read(buffer)) != -1) {
+                outputStream.write(buffer, 0, bytesRead);
+            }
+            byte[] imageBytes = outputStream.toByteArray();
+            //压缩到200k
+            imageBytes = ImageUtil.compressUnderSize(imageBytes, 204800);
+
+            String base64String = Base64.getEncoder().encodeToString(imageBytes);
+            inputStream.close();
+            outputStream.close();
+
+            //保存到云服务器
+            String filePath = UploadUtil.uploadFileByte(filename, imageBytes);
+
+            //存入数据库
+            long fileId = IdUtil.getSnowflakeNextId();
+            String suffix = StringUtils.substringAfterLast(filename, StringPool.DOT);
+            Long folderId = IdWorker.getId();
+            File fileEntity = new File();
+            fileEntity.setId(fileId);
+            fileEntity.setFolderId(folderId);
+            fileEntity.setFileName(filename);
+            fileEntity.setCreateDate(LocalDateTime.now());
+            fileEntity.setCreateUserId(StpUtil.getLoginIdAsLong());
+            fileEntity.setDeleteMark(0);
+            fileEntity.setFileUrl(filePath);
+            fileEntity.setFileSize(file.getSize());
+            fileEntity.setFileSuffiex(StringPool.DOT + suffix);
+            fileEntity.setFileType(suffix);
+            fileService.save(fileEntity);
+
+            TeacherFaceProcess process = faceMap.get(Long.parseLong(teacherUser.getId()));
+            if(process == null){
+                long baseFaceId = IdUtil.getSnowflakeNextId();
+                FaceManagement baseFace = new FaceManagement();
+                baseFace.setId(baseFaceId);
+                baseFace.setRegisterBase64(base64String);
+                baseFace.setUserId(Long.parseLong(teacherUser.getId()));
+                baseFace.setSex(teacherUser.getGender());
+                baseFace.setName(teacherUser.getName());
+                baseFace.setIdno(teacherUser.getCredentialNumber());
+                baseFace.setVerifyStatus(1);
+                baseFace.setCreateDate(LocalDateTime.now());
+                baseFace.setCreateUserId(StpUtil.getLoginIdAsLong());
+                baseFace.setDeleteMark(0);
+                baseFace.setStatus(1);
+                baseFace.setFileId(folderId);
+                baseFace.setUserType(2L);
+                faceManagementService.save(baseFace);
+
+                TeacherFaceProcess teacherFace = new TeacherFaceProcess();
+                teacherFace.setStatus(1);
+                teacherFace.setCreateDate(new Date());
+                teacherFace.setCreateUserId(StpUtil.getLoginIdAsLong());
+                teacherFace.setDeleteMark(0);
+                teacherFace.setGender(teacherUser.getGender());
+                teacherFace.setFacePhoto(folderId);
+                teacherFace.setName(teacherUser.getName());
+                teacherFace.setDepId(Long.parseLong(teacherUser.getDeptId()));
+                teacherFace.setDepCn(teacherUser.getDeptIdCn());
+                teacherFace.setIdentityCard(teacherUser.getCredentialNumber());
+                teacherFace.setStatus(1);
+                teacherFace.setUserId(Long.parseLong(teacherUser.getId()));
+                teacherFace.setExamStatus(1);
+
+                //将人脸上传海康
+                JsonObject paramJson = new JsonObject();
+                paramJson.addProperty("personId", teacherUser.getId());
+                paramJson.addProperty("faceData", base64String);
+
+                Map<String, String> querys = new HashMap<>();
+                querys.put("tagId", "frs");
+
+                String apiPath = "/api/resource/v1/face/single/add";
+                String response = apiUtil.doPost(apiPath, String.valueOf(paramJson), querys);
+                teacherFace.setHikvisionResult(response);
+                teacherFaceProcessService.save(teacherFace);
+            } else {
+                process.setStatus(1);
+                process.setExamStatus(1);
+                process.setModifyDate(new Date());
+                process.setModifyUserId(StpUtil.getLoginIdAsLong());
+                process.setDeleteMark(0);
+                process.setFacePhoto(folderId);
+
+                String faceId = null;
+                if(process.getHikvisionResult() != null && process.getHikvisionResult().startsWith("{") && process.getHikvisionResult().endsWith("}")){
+                    JsonObject object = parser.parse(process.getHikvisionResult()).getAsJsonObject();
+                    if("0".equals(object.get("code").getAsString()) && "success".equals(object.get("msg").getAsString())){
+                        faceId = object.get("data").getAsJsonObject().get("faceId").getAsString();
+                    }
+                }
+                if(faceId == null){
+                    String apiUrl = "/api/resource/v1/person/condition/personInfo";
+                    JsonObject paramsJson = new JsonObject();
+                    paramsJson.addProperty("paramName", "personId");
+                    JsonArray array = new JsonArray();
+                    array.add(teacherUser.getId());
+                    paramsJson.add("paramValue", array);
+                    String personInfoRes = apiUtil.doPost(apiUrl, paramsJson.toString(), null);
+
+                    JsonObject personInfoData = parser.parse(personInfoRes).getAsJsonObject();
+                    if("0".equals(personInfoData.get("code").getAsString()) && "success".equals(personInfoData.get("msg").getAsString())){
+                        JsonObject dataJson = personInfoData.get("data").getAsJsonObject();
+                        if(dataJson.get("total").getAsInt() > 0){
+                            JsonArray personPhoto = dataJson.get("list").getAsJsonArray().get(0)
+                                    .getAsJsonObject().get("personPhoto").getAsJsonArray();
+                            if(personPhoto.size() > 0){
+                                faceId = personPhoto.get(0).getAsJsonObject().get("personPhotoIndexCode").getAsString();
+                            }
+
+                        }
+                    }
+                }
+
+                //更新海康数据
+                JsonObject paramJson = new JsonObject();
+                String apiPath;
+                if(faceId != null){
+                    apiPath = "/api/resource/v1/face/single/update";
+                    paramJson.addProperty("faceId", faceId);
+                    paramJson.addProperty("faceData", base64String);
+
+                }else{
+                    apiPath = "/api/resource/v1/face/single/add";
+                    paramJson.addProperty("personId", teacherUser.getId());
+                    paramJson.addProperty("faceData", base64String);
+                }
+                String result = apiUtil.doPost(apiPath, paramJson.toString(), null);
+                if(result.startsWith("{") && result.endsWith("}")){
+                    JsonObject object = parser.parse(result).getAsJsonObject();
+                    if("0".equals(object.get("code").getAsString()) && "success".equals(object.get("msg").getAsString())){
+                        process.setHikvisionResult(result);
+                    }
+                }
+
+                teacherFaceProcessService.updateById(process);
+
+                FaceManagement faceManagement = faceManagementMap.get(Long.parseLong(teacherUser.getId()));
+                faceManagement.setVerifyStatus(2);
+                faceManagement.setRegisterBase64(base64String);
+                faceManagementService.update(faceManagement);
+            }
+        }
+        return RT.ok(true);
+    }
+
 }

+ 5 - 0
src/main/java/com/xjrsoft/module/teacher/vo/XjrUserPageVo.java

@@ -63,6 +63,11 @@ public class XjrUserPageVo {
      */
     @ApiModelProperty("主组织机构")
     private String deptId;
+    /**
+     * 主组织机构
+     */
+    @ApiModelProperty("主组织机构")
+    private String deptIdCn;
     /**
      * 内主岗位类别-岗位
      */

+ 13 - 2
src/main/resources/mapper/base/BaseClassCourse.xml

@@ -55,7 +55,10 @@
         t1.name                  AS courseName,
         t.book_name              AS bookName,
         t.id                     AS bookId,
-        concat(t.course_subject_id, '_', t.id) AS id
+        concat(t.course_subject_id, '_', t.id) AS id,
+        t.issn,
+        t.editor_in_chief,
+        t.version
         FROM textbook t
         LEFT JOIN base_course_subject t1 ON t.course_subject_id = t1.id
         WHERE t.delete_mark = 0
@@ -74,7 +77,15 @@
     </select>
 
     <select id="getSelectedCourseBook" resultType="com.xjrsoft.module.base.entity.CourseBookInfo">
-        select t.course_id as courseId, t2.name as courseName, t1.book_name as bookName, t.textbook_id as bookId, concat(t.course_id, '_', t.textbook_id) AS id
+        select
+            t.course_id as courseId,
+            t2.name as courseName,
+            t1.book_name as bookName,
+            t.textbook_id as bookId,
+            concat(t.course_id, '_', t.textbook_id) AS id,
+            t1.issn,
+            t1.editor_in_chief,
+            t1.version
         from base_class_course t
         left join textbook t1 on t1.id = t.textbook_id
         left join base_course_subject t2 on t.course_id = t2.id

+ 252 - 9
src/test/java/com/xjrsoft/module/job/AttenDanceWarnNoticeTaskTest.java

@@ -1,30 +1,273 @@
 package com.xjrsoft.module.job;
 
+import cn.hutool.core.util.IdUtil;
+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;
+import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails;
+import com.xjrsoft.module.attendance.entity.AttendanceUserRelation;
+import com.xjrsoft.module.attendance.mapper.AttendanceUserRelationMapper;
+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 org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
 
-import java.time.LocalDate;
 import java.time.LocalDateTime;
-import java.time.LocalTime;
-
-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.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * @author dzx
  * @date 2024/6/4
  */
+@SpringBootTest
 class AttenDanceWarnNoticeTaskTest {
 
 
+    @Autowired
+    private IAttendanceRuleCategoryService categoryService;
+
+    @Autowired
+    private IXjrUserService userService;
+
+    @Autowired
+    private AttendanceUserRelationMapper relationMapper;
+
+    @Autowired
+    private IWeChatService weChatService;
+
+    @Autowired
+    private WeChatUtil weChatUtil;
+
+    @Autowired
+    private IWechatMessageLogService wechatMessageLogService;
+
     @Test
-    void test(){
+    public void RefreshConnectionPool() {
+        String active = SpringUtil.getActiveProfile();
+        if(!"dev".equals(active)){
+            return;
+        }
+        //获取当前时间
         LocalDateTime now = LocalDateTime.now();
-        System.out.println(now.getDayOfWeek().name());
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+        String timeStr = now.format(formatter);
+
+        //查询今天所有的考勤规则
+        List<AttendanceRuleDetails> ruleDetailsList = categoryService.getTodayRules();
+        Map<Long, AttendanceRuleDetails> ruleDetailsMap = new HashMap<>();
+        for (AttendanceRuleDetails ruleDetail : ruleDetailsList) {
+            ruleDetailsMap.put(ruleDetail.getAttendanceRuleCategoryId(), ruleDetail);
+        }
+
+        //查询出所有人的考勤规则
+        List<AttendanceUserRelation> relationList = relationMapper.selectList(
+                new QueryWrapper<AttendanceUserRelation>().lambda()
+                        .eq(AttendanceUserRelation::getDeleteMark, 0)
+        );
+        Map<Long, AttendanceRuleDetails> allTodyRule = new HashMap<>();
+        for (AttendanceUserRelation userRelation : relationList) {
+            allTodyRule.put(userRelation.getUserId(), ruleDetailsMap.get(userRelation.getAttendanceRuleCategoryId()));
+        }
+
+        Map<Long, AttendanceUserRelation> allUserStatus = new HashMap<>();
+        for (AttendanceUserRelation userRelation : relationList) {
+            allUserStatus.put(userRelation.getUserId(), userRelation);
+        }
+
+        //根据规则中的用户id查询出所有绑定了微信的学生和教师
+        if(allTodyRule.isEmpty()){
+            System.out.println("未能查询出规则,不进行推送");
+            return;
+        }
+
+        //获取最近的时间
+        LocalDateTime recentlyTime = getRecentlyTime(ruleDetailsList, now);
+        if(!recentlyTime.isEqual(now)){
+            System.out.println("未到时间,不进行推送");
+//            return;
+        }
+        String wechatTemplate = weChatUtil.getAttenDanceWarnTemplate();
+//        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;
+//        }
+
+        //判断所有当前时间下,哪几条规则需要进行提醒
+        Map<Long, Integer> ruleDetailsJudgeMap = judgeExecuteNotice(now, ruleDetailsList, recentlyTime);
+
+        WechatMessageLog messageLog = new WechatMessageLog();
+        messageLog.setTemplateId(wechatTemplate);
+        messageLog.setSendTime(recentlyTime);
+
+        List<XjrUser> userList = getUserList(allTodyRule.keySet());
+        for (XjrUser xjrUser : userList) {
+            AttendanceRuleDetails ruleDetails = allTodyRule.get(xjrUser.getId());
+            Integer status = ruleDetailsJudgeMap.get(ruleDetails.getId());
+            if(status == 0){
+                continue;
+            }
+
+            WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
+            weChatSendMessageDto.setUserId(xjrUser.getOpenId());
+            weChatSendMessageDto.setTemplateId(wechatTemplate);
+            weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
+            JSONObject paramJson = new JSONObject();
+
+            JSONObject thing8 = new JSONObject();
+            thing8.put("value", xjrUser.getName());
+            paramJson.put("thing8", thing8);
+
+            JSONObject time9 = new JSONObject();
+            time9.put("value", timeStr);
+            paramJson.put("time9", time9);
+
+            JSONObject const12 = new JSONObject();
+            if(status == 1){
+                const12.put("value", "未打卡");
+            }else{
+                const12.put("value", "待打卡");
+            }
+            //查询这个用户最新的考勤状态
+            AttendanceUserRelation userRelation = allUserStatus.get(xjrUser.getId());
+            if(userRelation != null
+                    && userRelation.getAttendanceTime() !=null
+                    && userRelation.getAttendanceTime().toLocalDate().isEqual(now.toLocalDate())
+                    && "到校".equals(userRelation.getAttendanceStatus())){
+                const12.put("value", "已打卡");
+            }
+            paramJson.put("const12", const12);
+
+            weChatSendMessageDto.setContent(paramJson);
+            weChatService.sendTemplateMessage(weChatSendMessageDto);
+        }
+
+        messageLog.setCreateDate(new Date());
+        messageLog.setContent("消息推送人数:" + userList.size());
+        wechatMessageLogService.save(messageLog);
+
+    }
+
+    /**
+     * 判断所有规则,哪些需要发送
+     * @param judgeTime
+     * @param ruleDetailsList
+     * @return 0:不需要提醒,1:未打卡,2:待打卡
+     */
+    Map<Long, Integer> judgeExecuteNotice(LocalDateTime judgeTime, List<AttendanceRuleDetails> ruleDetailsList, LocalDateTime recentlyTime){
+        Map<Long, Integer> result = new HashMap<>();
+        for (AttendanceRuleDetails ruleDetails : ruleDetailsList) {
+            if(ruleDetails.getIsAllowInOutSchool() != null && ruleDetails.getIsAllowInOutSchool() == 1
+                    && ruleDetails.getIsAttendance() != null && ruleDetails.getIsAttendance() == 1){
+                if(ruleDetails.getAmStartTime() != null){
+                    LocalDateTime amStartTime = judgeTime.with(ruleDetails.getAmStartTime().toLocalTime());
+                    if(recentlyTime.isEqual(amStartTime)){
+                        Long amBetween = ChronoUnit.MINUTES.between(judgeTime, amStartTime);
+                        if(judgeTime.isBefore(amStartTime) && amBetween >= ruleDetails.getAgoMinutes() - 1 && amBetween <= ruleDetails.getAgoMinutes() + 1){//相差分钟数小于0
+                            result.put(ruleDetails.getId(), 1);
+                        }else if(judgeTime.isAfter(amStartTime) && amBetween >= ruleDetails.getOverMinutes() - 1 && amBetween <= ruleDetails.getOverMinutes() + 1){
+                            result.put(ruleDetails.getId(), 2);
+                        }
+                    }
+                }
+                if(ruleDetails.getPmStartTime() != null){
+                    LocalDateTime pmStartTime = judgeTime.with(ruleDetails.getPmStartTime().toLocalTime());
+                    if(recentlyTime.isEqual(pmStartTime)){
+                        Long pmBetween = ChronoUnit.MINUTES.between(judgeTime, pmStartTime);
+                        if(judgeTime.isBefore(pmStartTime) && pmBetween >= ruleDetails.getAgoMinutes() - 1 && pmBetween <= ruleDetails.getAgoMinutes() + 1){
+                            result.put(ruleDetails.getId(), 1);
+                        }else if(judgeTime.isAfter(pmStartTime) && pmBetween >= ruleDetails.getOverMinutes() - 1 && pmBetween <= ruleDetails.getOverMinutes() + 1){
+                            result.put(ruleDetails.getId(), 2);
+                        }
+                    }
+                }
+
+                if(ruleDetails.getEveningStartTime() != null){
+                    LocalDateTime eveningStartTime = judgeTime.with(ruleDetails.getEveningStartTime().toLocalTime());
+                    if(recentlyTime.isEqual(eveningStartTime)){
+                        Long eveningBetween = ChronoUnit.MINUTES.between(judgeTime, eveningStartTime);
+                        if(judgeTime.isBefore(eveningStartTime) && eveningBetween >= ruleDetails.getAgoMinutes() - 1 && eveningBetween <= ruleDetails.getAgoMinutes() + 1){
+                            result.put(ruleDetails.getId(), 1);
+                        }else if(judgeTime.isAfter(eveningStartTime)  && eveningBetween >= ruleDetails.getOverMinutes() - 1 && eveningBetween <= ruleDetails.getOverMinutes() + 1){
+                            result.put(ruleDetails.getId(), 2);
+                        }
+                    }
+                }
+
+                if(!result.containsKey(ruleDetails.getId())){
+                    result.put(ruleDetails.getId(), 0);
+                }
+            }else{
+                result.put(ruleDetails.getId(), 0);
+            }
+        }
+        return result;
+    }
+    /**
+     * 查询出所有用户信息(openId不为空的)
+     * @param userIds 需要插叙的userid
+     * @return 用户信息
+     */
+    List<XjrUser> getUserList(Set<Long> userIds){
+        return userService.list(
+                new QueryWrapper<XjrUser>().lambda()
+                        .in(XjrUser::getId, userIds)
+//                        .isNotNull(XjrUser::getOpenId)
+        );
+    }
 
-        LocalTime amStartTime = LocalTime.of(8,0,0);
-        System.out.println(now.with(amStartTime));
+    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().toLocalTime());
+                    result.add(amStartTime);
+                }
+                if(ruleDetail.getPmStartTime() != null){
+                    LocalDateTime pmStartTime = now.with(ruleDetail.getPmStartTime().toLocalTime());
+                    result.add(pmStartTime);
+                }
 
-        System.out.println(1L == 1);
+                if(ruleDetail.getEveningStartTime() != null){
+                    LocalDateTime eveningStartTime = now.with(ruleDetail.getEveningStartTime().toLocalTime());
+                    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));
     }
 
 }

+ 49 - 49
src/test/java/com/xjrsoft/module/job/HikvisionBaseDataTaskTest.java

@@ -83,29 +83,29 @@ class HikvisionBaseDataTaskTest {
 
     @Test
     void test() throws Exception {
-        DataSource datasource = DatasourceUtil.getDataSource(GlobalConstant.DEFAULT_DATASOURCE_KEY);
-        Db use = Db.use(datasource);
-//        String sql = "SELECT distinct table_name FROM hikvision_data WHERE 1 = 1";
-//        List<JianyueData> query = use.query(sql, JianyueData.class);
-//        Set<String> tables = new HashSet<>();
-//        for (JianyueData jianyueData : query) {
-//            tables.add(jianyueData.getTableName());
-//        }
-//        sql = "SELECT * FROM hikvision_data WHERE 0 = 0";
-//        List<HikvisionData> list = use.query(sql, HikvisionData.class);
-//        Map<String, Map<String, String>> dataMap = new HashMap<>();
-//        for (String table : tables) {
-//            Map<String, String> tableData = new HashMap<>();
-//            for (HikvisionData hikvisiondata : list) {
-//                if(!table.equals(hikvisiondata.getTableName())){
-//                    continue;
-//                }
-//                tableData.put(hikvisiondata.getSourceId(), hikvisiondata.getHikvisionId());
-//            }
-//            dataMap.put(table, tableData);
-//        }
+        String sql = "SELECT distinct table_name FROM hikvision_data WHERE 1 = 1";
+        List<Map<String, Object>> maps = SqlRunnerAdapter.db().selectList(sql, HikvisionData.class);
+        Set<String> tables = new HashSet<>();
+        for (Map<String, Object> map : maps) {
+            String[] strings = SqlRunnerAdapterUtil.convertMapToStringArray(map);
+            tables.add(strings[0]);
+        }
+        sql = "SELECT * FROM hikvision_data WHERE 0 = 0";
+        List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql, HikvisionData.class);
+        Map<String, Map<String, String>> dataMap = new HashMap<>();
+        for (String table : tables) {
+            Map<String, String> tableData = new HashMap<>();
+            for (Map<String, Object> hikvision : list) {
+
+                if(!table.equals(hikvision.get("table_name").toString())){
+                    continue;
+                }
+                tableData.put(hikvision.get("source_id").toString(), hikvision.get("hikvision_id").toString());
+            }
+            dataMap.put(table, tableData);
+        }
 //        DataUtil dataUtil = new DataUtil();
-//        String tableName = "xjr_department";
+        String tableName = "xjr_department";
 //        Map<String, String> department = dataUtil.insertDepartment(use, tableName, dataMap.get(tableName));
 //        if(department.isEmpty() && dataMap.get(tableName) != null){
 //            department = dataMap.get(tableName);
@@ -127,9 +127,9 @@ class HikvisionBaseDataTaskTest {
 //        Map<String, String> classes = dataUtil.insertClass(use, tableName, baseClass);
 
 
-//        tableName = "base_student";
-//        Map<String, String> baseStudent = dataMap.get(tableName);
-//        Map<String, String> student = dataUtil.insertStudentOne(use, tableName, baseStudent);
+        tableName = "base_student";
+        Map<String, String> baseStudent = dataMap.get(tableName);
+        Map<String, String> student = insertStudentOne(tableName, baseStudent);
 
 //        selectOrg(use, "base_class");
 
@@ -138,7 +138,7 @@ class HikvisionBaseDataTaskTest {
 //        selectCar(use, carTableName);
 
 //        outInRecordUtil.GetVehicleRecord(use,faceImportMapper);
-        outInRecordUtil.GetTeacherAndStudentRecords(faceImportMapper);
+//        outInRecordUtil.GetTeacherAndStudentRecords(faceImportMapper);
 ////        selecAllPersonById(use);
 //        selectResource(use);
     }
@@ -170,20 +170,18 @@ class HikvisionBaseDataTaskTest {
         db.executeBatch(sqls);
     }
 
-    public Map<String, String> insertStudentOne(Db db, String tableName, Map<String, String> tableData) throws Exception {
-        String sql = "SELECT t1.id,t1.name,CONCAT(t3.id,'-',t4.name,'-',t3.class_type,'-',t2.stduy_status)," +
-                " t1.user_name,t1.gender,DATE_FORMAT(t1.birth_date, '%Y-%m-%d'),t1.mobile,t1.email,t1.credential_type,t1.credential_number FROM xjr_user t1" +
+    public Map<String, String> insertStudentOne(String tableName, Map<String, String> tableData) throws Exception {
+        String sql = "SELECT t1.id,t1.name,CONCAT(t3.id,'-',replace(t4.name,'级',''),'-',t3.class_type,'-',t2.stduy_status) as orgIndexCode," +
+                " t1.user_name,t1.gender,DATE_FORMAT(t1.birth_date, '%Y-%m-%d') as birthday,t1.mobile,t1.email,t1.credential_type,t1.credential_number FROM xjr_user t1" +
                 " INNER JOIN base_student_school_roll t2 ON t1.id = t2.user_id" +
                 " INNER JOIN base_class t3 ON t2.class_id = t3.id" +
                 " INNER JOIN base_grade t4 ON t3.grade_id = t4.id" +
                 " WHERE t1.delete_mark = 0 AND t2.delete_mark = 0" +
                 " AND t3.class_type IS NOT NULL" +
-                " AND t1.id NOT IN (SELECT source_id FROM hikvision_data WHERE table_name = 'base_student'\n" +
-                ") AND t4.name NOT IN ('2021级','2020级')";
-        List<String[]> list = db.query(sql, String[].class);
+                " AND t1.name IN ('白江龙')";
+        List<Map<String, Object>> list = SqlRunnerAdapter.db().selectList(sql, String[].class);
         Map<Integer, String> clientMap = new HashMap<>();
 
-        String apiPath = "/api/resource/v2/person/single/add";
         Map<String, String> idMap = new HashMap<>();
         JsonParser jsonParser = new JsonParser();
         ApiUtil apiUtil = new ApiUtil();
@@ -191,22 +189,21 @@ class HikvisionBaseDataTaskTest {
         header.put("tagId", "insert_student");
 
         for(int i = 0; i < list.size(); i ++){
-            String[] el = list.get(i);
-            if(tableData != null && tableData.containsKey(el[0])){
-                continue;
-            }
+            Map<String, Object> objectMap = list.get(i);
+            String apiPath = "/api/resource/v2/person/single/add";
+
             JsonObject paramJson = new JsonObject();
             paramJson.addProperty("clientId", i);
-            paramJson.addProperty("personId", el[0]);
-            paramJson.addProperty("personName", el[1]);
-            paramJson.addProperty("orgIndexCode", el[2]);
-            paramJson.addProperty("phoneNo", el[6]);
-            paramJson.addProperty("jobNo", el[3]);
-            paramJson.addProperty("birthday", el[5]);
+            paramJson.addProperty("personId", objectMap.get("id").toString());
+            paramJson.addProperty("personName", objectMap.get("name").toString());
+            paramJson.addProperty("orgIndexCode", objectMap.get("orgIndexCode").toString());
+            paramJson.addProperty("phoneNo", objectMap.get("mobile").toString());
+            paramJson.addProperty("jobNo", objectMap.get("user_name").toString());
+            paramJson.addProperty("birthday", objectMap.get("birthday").toString());
             paramJson.addProperty("personType", 2);
 
             int gender;
-            switch (el[4]) {
+            switch (objectMap.get("gender").toString()) {
                 case "SB10001":
                     gender = 1;
                     break;
@@ -219,18 +216,21 @@ class HikvisionBaseDataTaskTest {
             }
             paramJson.addProperty("gender", gender);
 
-            clientMap.put(i, el[0]);
-            System.out.println("请求参数:" + paramJson.toString());
+            if(tableData != null && tableData.containsKey(objectMap.get("id").toString())){
+                apiPath = "/api/resource/v1/person/single/update";
+                String doPost = apiUtil.doPost(apiPath, paramJson.toString(), null, header);
+                continue;
+            }
+
+            clientMap.put(i, objectMap.get("id").toString());
             String result = apiUtil.doPost(apiPath, paramJson.toString(), null, header);
-            System.out.println("返回结果:" + result);
             JsonElement parse = jsonParser.parse(result);
             JsonObject resultJson = parse.getAsJsonObject();
             if("0".equals(resultJson.get("code").getAsString()) && "success".equals(resultJson.get("msg").getAsString())){
                 JsonObject array = resultJson.get("data").getAsJsonObject();
-                idMap.put(el[0], array.get("personId").getAsString());
+                idMap.put(objectMap.get("id").toString(), array.get("personId").getAsString());
             }
         }
-        insertRecord(db, tableName, idMap);
         //插入记录表
         return idMap;
     }