Explorar o código

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

大数据与最优化研究所 hai 8 meses
pai
achega
d8ce3d7afa
Modificáronse 18 ficheiros con 815 adicións e 262 borrados
  1. 34 0
      src/main/java/com/xjrsoft/common/enums/OutInStatusEnum.java
  2. 32 8
      src/main/java/com/xjrsoft/module/attendance/controller/StatisticsController.java
  3. 12 4
      src/main/java/com/xjrsoft/module/attendance/controller/StudentStatisticsController.java
  4. 43 5
      src/main/java/com/xjrsoft/module/attendance/controller/TeacherStatisticsController.java
  5. 5 0
      src/main/java/com/xjrsoft/module/attendance/entity/AttendanceUserRelation.java
  6. 41 35
      src/main/java/com/xjrsoft/module/attendance/service/impl/AttendanceRuleCategoryServiceImpl.java
  7. 6 0
      src/main/java/com/xjrsoft/module/attendance/vo/TeacherStatisticsPageVo.java
  8. 8 3
      src/main/java/com/xjrsoft/module/hikvision/controller/EventController.java
  9. 35 29
      src/main/java/com/xjrsoft/module/hikvision/util/DataUtil.java
  10. 178 54
      src/main/java/com/xjrsoft/module/hikvision/util/OutInRecordUtil.java
  11. 84 42
      src/main/java/com/xjrsoft/module/job/AttenDanceWarnNoticeTask.java
  12. 21 15
      src/main/java/com/xjrsoft/module/job/AttendanceMessageTask.java
  13. 5 5
      src/main/java/com/xjrsoft/module/job/HikvisionBaseDataTask.java
  14. 5 1
      src/main/java/com/xjrsoft/module/outint/entity/CarOutInRecord.java
  15. 1 0
      src/main/java/com/xjrsoft/module/personnel/controller/StundentFaceProcessController.java
  16. 1 0
      src/main/resources/mapper/outin/StudentOutInRecordMapper.xml
  17. 252 9
      src/test/java/com/xjrsoft/module/job/AttenDanceWarnNoticeTaskTest.java
  18. 52 52
      src/test/java/com/xjrsoft/module/job/HikvisionBaseDataTaskTest.java

+ 34 - 0
src/main/java/com/xjrsoft/common/enums/OutInStatusEnum.java

@@ -0,0 +1,34 @@
+package com.xjrsoft.common.enums;
+
+/**
+ * @description: 进出状态(0:进 1:出)
+ * @Author: dzx
+ * @Date: 2024年6月20日
+ */
+public enum OutInStatusEnum {
+
+    /**
+     * 春季招生
+     */
+    enter(0, "出场"),
+    /**
+     *  秋季招生
+     */
+    goOut(1, "进场");
+
+    final Integer code;
+    final String value;
+
+    public Integer getCode() {
+        return this.code;
+    }
+
+    public String getValue() {
+        return this.value;
+    }
+
+    OutInStatusEnum(final Integer code, final String message) {
+        this.code = code;
+        this.value = message;
+    }
+}

+ 32 - 8
src/main/java/com/xjrsoft/module/attendance/controller/StatisticsController.java

@@ -5,16 +5,21 @@ import cn.hutool.core.util.ObjectUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.github.yulichang.toolkit.MPJWrappers;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.xjrsoft.common.enums.StudyStatusEnum;
 import com.xjrsoft.common.model.result.RT;
+import com.xjrsoft.common.utils.VoToColumnUtil;
 import com.xjrsoft.module.attendance.dto.AttendanceStatisticDto;
 import com.xjrsoft.module.attendance.vo.TeacherStatisticsVo;
 import com.xjrsoft.module.attendance.vo.VisitorInfoVo;
 import com.xjrsoft.module.concat.service.IXjrUserService;
 import com.xjrsoft.module.organization.entity.UserDeptRelation;
+import com.xjrsoft.module.outint.entity.CarOutInRecord;
 import com.xjrsoft.module.outint.entity.StudentOutInRecord;
 import com.xjrsoft.module.outint.entity.TeacherOutInRecord;
+import com.xjrsoft.module.outint.service.ICarOutInRecordService;
 import com.xjrsoft.module.outint.service.IStudentOutInRecordService;
 import com.xjrsoft.module.outint.service.ITeacherOutInRecordService;
+import com.xjrsoft.module.personnel.entity.CarMessageApply;
 import com.xjrsoft.module.personnel.service.IReservationSchoolService;
 import com.xjrsoft.module.student.entity.BaseStudent;
 import com.xjrsoft.module.student.entity.BaseStudentSchoolRoll;
@@ -59,6 +64,7 @@ public class StatisticsController {
     private final IWfTeacherleaveService wfTeacherleaveService;
     private final IStudentLeaveService studentLeaveService;
     private final IReservationSchoolService reservationSchoolService;
+    private final ICarOutInRecordService carOutInRecordService;
 
     @GetMapping(value = "/teacher-statistics")
     @ApiOperation(value="教职工考勤统计")
@@ -76,32 +82,47 @@ public class StatisticsController {
         if(dto.getDate() != null && !"".equals(dto.getDate())){
             DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
             LocalDate queryDate = LocalDate.parse(dto.getDate(), formatter);
-            LocalDateTime startTime, endTime;
+            LocalDateTime startTime, endTime, amEndTime = null;
             if(dto.getTimePeriod() != null && dto.getTimePeriod() == 1){
                 startTime = queryDate.atTime(5, 0, 0);
                 endTime = queryDate.atTime(12, 0, 0);
             }else if(dto.getTimePeriod() != null && dto.getTimePeriod() == 2){
                 startTime = queryDate.atTime(12, 0, 0);
                 endTime = queryDate.atTime(18, 0, 0);
+                amEndTime = queryDate.atTime(12, 0, 0);
             }else if(dto.getTimePeriod() != null && dto.getTimePeriod() == 3){
                 startTime = queryDate.atTime(18, 0, 0);
                 endTime = queryDate.atTime(23, 59, 59);
+                amEndTime = queryDate.atTime(18, 0, 0);
             }else{
                 startTime = queryDate.atTime(0, 0, 0);
                 endTime = queryDate.atTime(23, 59, 59);
             }
 
             List<TeacherOutInRecord> outInRecords = teacherOutInRecordService.list(
-                    new QueryWrapper<TeacherOutInRecord>().lambda()
-                            .between(TeacherOutInRecord::getRecordTime, startTime, endTime)
+                    new MPJLambdaWrapper<TeacherOutInRecord>()
+                            .le(TeacherOutInRecord::getRecordTime, endTime)
                             .eq(TeacherOutInRecord::getStatus, 1)
+                            .eq("DATE_FORMAT(record_time, '%Y-%m-%d')", endTime.toLocalDate())
+                            .ge(dto.getTimePeriod() == 2 && amEndTime != null, CarOutInRecord::getRecordTime, amEndTime)
                             .orderByAsc(TeacherOutInRecord::getRecordTime)
             );
 
-            List<Long> collect = outInRecords.stream().map(TeacherOutInRecord::getUserId).collect(Collectors.toList());
+            List<CarOutInRecord> list = carOutInRecordService.list(
+                    new MPJLambdaWrapper<CarOutInRecord>()
+                            .select(CarOutInRecord.class, x -> VoToColumnUtil.fieldsToColumns(CarOutInRecord.class).contains(x.getProperty()))
+                            .leftJoin(CarMessageApply.class, CarMessageApply::getId, CarOutInRecord::getCarMessageApplyId)
+                            .le(CarOutInRecord::getRecordTime, endTime)
+                            .eq("DATE_FORMAT(record_time, '%Y-%m-%d')", endTime.toLocalDate())
+                            .ge(dto.getTimePeriod() == 2 && amEndTime != null, CarOutInRecord::getRecordTime, amEndTime)
+                            .eq(CarOutInRecord::getStatus, 0)
+                            .orderByAsc(CarOutInRecord::getRecordTime)
+            );
+
+            Set<Long> collect = outInRecords.stream().map(TeacherOutInRecord::getUserId).collect(Collectors.toSet());
             Set<Long> userIds = new HashSet<>(collect);
             //实到人数
-            statisticsVo.setActualCount(Long.valueOf(userIds.size()));
+            statisticsVo.setActualCount(Long.valueOf(collect.size()));
 
             //查询教师请假人数
             Long leaveCount = wfTeacherleaveService.getLeaveCount(startTime, endTime);
@@ -150,6 +171,9 @@ public class StatisticsController {
                 .innerJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, XjrUser::getId)
                 .innerJoin(BaseStudent.class, BaseStudent::getUserId, XjrUser::getId);
         long allCount = xjrUserService.count(queryWrapper);
+
+        queryWrapper.eq(BaseStudentSchoolRoll::getStduyStatus, StudyStatusEnum.AttendDaySchool.getCode());
+        long attendDaySchoolCount = xjrUserService.count(queryWrapper);
         statisticsVo.setAllCount(allCount);
         if(dto.getDate() != null && !"".equals(dto.getDate())){
             DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
@@ -172,7 +196,7 @@ public class StatisticsController {
                             .eq(StudentOutInRecord::getStatus, 1)
             );
             //实到人数
-            List<Long> collect = outInRecords.stream().map(StudentOutInRecord::getUserId).collect(Collectors.toList());
+            Set<Long> collect = outInRecords.stream().map(StudentOutInRecord::getUserId).collect(Collectors.toSet());
             statisticsVo.setActualCount(Long.valueOf(collect.size()));
 
             //查询教师请假人数
@@ -199,8 +223,8 @@ public class StatisticsController {
             //计算出勤率
             if(statisticsVo.getAllCount() != null && statisticsVo.getAllCount() != 0){
                 //最后通过总人数-实到人数-请假人数计算出缺勤人数
-                statisticsVo.setAbsenteeismCount(statisticsVo.getAllCount() - statisticsVo.getLeaveCount() - statisticsVo.getActualCount());
-                BigDecimal divide = BigDecimal.valueOf(statisticsVo.getActualCount()).divide(BigDecimal.valueOf(statisticsVo.getAllCount()), 4, RoundingMode.HALF_UP);
+                statisticsVo.setAbsenteeismCount(attendDaySchoolCount - statisticsVo.getLeaveCount() - statisticsVo.getActualCount());
+                BigDecimal divide = BigDecimal.valueOf(statisticsVo.getActualCount()).divide(BigDecimal.valueOf(attendDaySchoolCount), 4, RoundingMode.HALF_UP);
                 statisticsVo.setAttendanceRate(divide.doubleValue() + "");
             }else{
                 statisticsVo.setAttendanceRate("0");

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

@@ -8,6 +8,7 @@ import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import com.xjrsoft.common.enums.ArchivesStatusEnum;
+import com.xjrsoft.common.enums.StudyStatusEnum;
 import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.page.ConventPage;
 import com.xjrsoft.common.page.PageOutput;
@@ -50,6 +51,8 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
 * @title: 考勤消息设置
@@ -144,12 +147,12 @@ public class StudentStatisticsController {
                 record.setLateCount(lateCount);
 
                 //最后通过总人数-实到人数-请假人数计算出缺勤人数
-                record.setAbsenteeismCount(record.getStudentCount() - record.getLeaveCount() - record.getActualCount());
+                record.setAbsenteeismCount(record.getNotStayCount() - record.getLeaveCount() - record.getActualCount());
 
                 //计算出勤率
                 BigDecimal divide = BigDecimal.ZERO;
-                if(record.getStudentCount() != null && record.getStudentCount() != 0){
-                    divide = BigDecimal.valueOf(record.getActualCount()).divide(BigDecimal.valueOf(record.getStudentCount()), 4, RoundingMode.HALF_UP);
+                if(record.getNotStayCount() != null && record.getNotStayCount() != 0){
+                    divide = BigDecimal.valueOf(record.getActualCount()).divide(BigDecimal.valueOf(record.getNotStayCount()), 4, RoundingMode.HALF_UP);
                 }
                 record.setAttendanceRate(divide.doubleValue() + "");
             }
@@ -236,6 +239,9 @@ public class StudentStatisticsController {
                         record.setStatus("缺勤");
                     }
                 }
+                if(StudyStatusEnum.InResidence.getValue().equals(record.getStduyStatusCn())){
+                    record.setStatus("不考勤");
+                }
             }
         }
         PageOutput<StudentStatisticsPageVo> pageOutput = ConventPage.getPageOutput(voIPage, StudentStatisticsPageVo.class);
@@ -275,7 +281,9 @@ public class StudentStatisticsController {
 
             for (ClassStatisticsVo record: attendancePage.getRecords()) {
                 record.setLeaveCount(classLeaveCount.get(record.getId()) == null ? 0:classLeaveCount.get(record.getId()));
-                record.setActualCount(notStayMap.get(record.getId()).size() + stayMap.get(record.getId()).size());
+                Set<Long> collect = notStayMap.get(record.getId()).stream().map(StudentOutInRecordVo::getUserId).collect(Collectors.toSet());
+
+                record.setActualCount(collect.size());
                 record.setStudentCount(record.getStudentCount() * dayOfWeeks.size() * 3);
 
                 Integer lateCount = 0;

+ 43 - 5
src/main/java/com/xjrsoft/module/attendance/controller/TeacherStatisticsController.java

@@ -6,6 +6,7 @@ import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.xjrsoft.common.enums.OutInStatusEnum;
 import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.page.ConventPage;
 import com.xjrsoft.common.page.PageOutput;
@@ -20,8 +21,11 @@ import com.xjrsoft.module.organization.entity.Department;
 import com.xjrsoft.module.organization.entity.User;
 import com.xjrsoft.module.organization.entity.UserDeptRelation;
 import com.xjrsoft.module.organization.service.IUserService;
+import com.xjrsoft.module.outint.entity.CarOutInRecord;
 import com.xjrsoft.module.outint.entity.TeacherOutInRecord;
+import com.xjrsoft.module.outint.service.ICarOutInRecordService;
 import com.xjrsoft.module.outint.service.ITeacherOutInRecordService;
+import com.xjrsoft.module.personnel.entity.CarMessageApply;
 import com.xjrsoft.module.teacher.entity.BaseTeacher;
 import com.xjrsoft.module.teacher.entity.WfHeadTeacherLeave;
 import com.xjrsoft.module.teacher.entity.WfTeacherleave;
@@ -62,6 +66,7 @@ public class TeacherStatisticsController {
     private final IHolidayDateService holidayDateService;
     private final IWfHeadTeacherLeaveService headTeacherLeaveService;
     private final IAttendanceRuleCategoryService attendanceRuleCategoryService;
+    private final ICarOutInRecordService carOutInRecordService;
 
     @GetMapping(value = "/teacher-details")
     @ApiOperation(value="教师考勤")
@@ -114,7 +119,7 @@ public class TeacherStatisticsController {
 //                outInMap.put(inRecord.getUserId(), inRecord);
 //            }
             for (TeacherStatisticsPageVo record : voIPage.getRecords()) {
-                LocalDateTime startTime, endTime;
+                LocalDateTime startTime, endTime, amEndTime = null;
                 AttendanceRuleDetailsUserVo detailsUserVo = teacherTodyRuleByUserId.get(record.getUserId());
                 if(dto.getTimePeriod() == 1){
                     startTime = queryDate.atTime(5, 0, 0);
@@ -134,6 +139,10 @@ public class TeacherStatisticsController {
                     if(detailsUserVo != null && detailsUserVo.getPmEndTime() != null){
                         endTime = queryDate.atTime(detailsUserVo.getPmEndTime());
                     }
+                    amEndTime  = queryDate.atTime(12, 0, 0);
+                    if(detailsUserVo != null && detailsUserVo.getAmEndTime() != null){
+                        amEndTime = queryDate.atTime(detailsUserVo.getAmEndTime());
+                    }
                 }else{
                     startTime = queryDate.atTime(0, 0, 0);
                     if(detailsUserVo != null && detailsUserVo.getEveningStartTime() != null){
@@ -164,9 +173,10 @@ public class TeacherStatisticsController {
                     continue;
                 }
                 List<TeacherOutInRecord> outInRecords = teacherOutInRecordService.list(
-                    new QueryWrapper<TeacherOutInRecord>().lambda()
-                            .between(TeacherOutInRecord::getRecordTime, startTime, endTime)
-                            .eq(TeacherOutInRecord::getStatus, 1)
+                    new MPJLambdaWrapper<TeacherOutInRecord>()
+                            .le(TeacherOutInRecord::getRecordTime, startTime)
+                            .eq(TeacherOutInRecord::getStatus, OutInStatusEnum.enter.getCode())
+                            .eq("DATE_FORMAT(record_time, '%Y-%m-%d')", startTime.toLocalDate())
                             .eq(TeacherOutInRecord::getUserId, record.getUserId())
                             .orderByAsc(TeacherOutInRecord::getRecordTime)
                 );
@@ -175,12 +185,40 @@ public class TeacherStatisticsController {
                     if(outInRecord != null){
                         record.setRecordTime(outInRecord.getRecordTime());
                         record.setStatus(outInRecord.getAttendanceStatus());
+                        record.setAttendanceMode("人脸");
+                    }
+                }else{
+                    //查询该教师是否通过车辆进入
+                    List<CarOutInRecord> list = carOutInRecordService.list(
+                            new MPJLambdaWrapper<CarOutInRecord>()
+                                    .select(CarOutInRecord.class, x -> VoToColumnUtil.fieldsToColumns(CarOutInRecord.class).contains(x.getProperty()))
+                                    .leftJoin(CarMessageApply.class, CarMessageApply::getId, CarOutInRecord::getCarMessageApplyId)
+                                    .le(CarOutInRecord::getRecordTime, endTime)
+                                    .eq("DATE_FORMAT(record_time, '%Y-%m-%d')", endTime.toLocalDate())
+                                    .eq(CarMessageApply::getUserId, record.getUserId())
+                                    .ge(dto.getTimePeriod() == 2 && amEndTime != null, CarOutInRecord::getRecordTime, amEndTime)
+                                    .eq(CarOutInRecord::getStatus, OutInStatusEnum.enter.getCode())
+                                    .orderByAsc(CarOutInRecord::getRecordTime)
+                    );
+                    if(!list.isEmpty()){
+                        CarOutInRecord outInRecord = list.get(0);
+                        if(outInRecord != null && outInRecord.getRecordTime().isBefore(startTime)){
+                            record.setRecordTime(outInRecord.getRecordTime());
+                            record.setStatus("到校");
+                            record.setAttendanceMode("车辆");
+                            record.setCarNumber(outInRecord.getPlanNo());
+                        }else if(outInRecord != null && outInRecord.getRecordTime().isAfter(startTime)){
+                            record.setRecordTime(outInRecord.getRecordTime());
+                            record.setStatus("迟到");
+                            record.setAttendanceMode("车辆");
+                            record.setCarNumber(outInRecord.getPlanNo());
+                        }
                     }
                 }
+
                 if(record.getStatus() == null){
                     record.setStatus("缺勤");
                 }
-
             }
         }
         PageOutput<TeacherStatisticsPageVo> pageOutput = ConventPage.getPageOutput(voIPage, TeacherStatisticsPageVo.class);

+ 5 - 0
src/main/java/com/xjrsoft/module/attendance/entity/AttendanceUserRelation.java

@@ -99,5 +99,10 @@ public class AttendanceUserRelation implements Serializable {
     @ApiModelProperty("最新考勤时间")
     private LocalDateTime attendanceTime;
 
+    @ApiModelProperty("考勤方式")
+    private String attendanceMode;
+
+    @ApiModelProperty("车牌号")
+    private String carNumber;
 
 }

+ 41 - 35
src/main/java/com/xjrsoft/module/attendance/service/impl/AttendanceRuleCategoryServiceImpl.java

@@ -105,7 +105,7 @@ public class AttendanceRuleCategoryServiceImpl extends MPJBaseServiceImpl<Attend
                     .eq(BaseTeacher::getDeleteMark, DeleteMark.NODELETE.getCode())
                     .eq(XjrUser::getDeleteMark, DeleteMark.NODELETE.getCode())
                     .in(!deptIds.isEmpty(), UserDeptRelation::getDeptId, deptIds)
-                    .in(!userIds.isEmpty(), XjrUser::getId, userIds).or()
+                    .in(!userIds.isEmpty(), XjrUser::getId, userIds)
                 );
                 //查询这部分人中是否已经有人有规则了
                 List<Long> relationUserIds = userList.stream().map(XjrUser::getId).collect(Collectors.toList());
@@ -297,25 +297,28 @@ public class AttendanceRuleCategoryServiceImpl extends MPJBaseServiceImpl<Attend
                 );
                 //查询这部分人中是否已经有人有规则了
                 List<Long> relationUserIds = userList.stream().map(XjrUser::getId).collect(Collectors.toList());
-                List<XjrUser> relations = xjrUserService.list(
-                    new MPJLambdaWrapper<XjrUser>()
-                    .select(XjrUser::getId)
-                    .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
-                    .leftJoin(AttendanceUserRelation.class, AttendanceUserRelation::getUserId, XjrUser::getId)
-                    .eq(AttendanceUserRelation::getDeleteMark, DeleteMark.NODELETE.getCode())
-                    .in(AttendanceUserRelation::getUserId, relationUserIds)
-                    .ne(AttendanceUserRelation::getAttendanceRuleCategoryId, attendanceRuleCategory.getId())
-                );
-                String peopleName = "";
-                for (int i = 0; i < relations.size(); i ++){
-                    if(i > 0){
-                        peopleName += ",";
+                if(!relationUserIds.isEmpty()){
+                    List<XjrUser> relations = xjrUserService.list(
+                            new MPJLambdaWrapper<XjrUser>()
+                                    .select(XjrUser::getId)
+                                    .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
+                                    .leftJoin(AttendanceUserRelation.class, AttendanceUserRelation::getUserId, XjrUser::getId)
+                                    .eq(AttendanceUserRelation::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                    .in(AttendanceUserRelation::getUserId, relationUserIds)
+                                    .ne(AttendanceUserRelation::getAttendanceRuleCategoryId, attendanceRuleCategory.getId())
+                    );
+                    String peopleName = "";
+                    for (int i = 0; i < relations.size(); i ++){
+                        if(i > 0){
+                            peopleName += ",";
+                        }
+                        peopleName += relations.get(i).getName();
+                    }
+                    if(!relations.isEmpty()){
+                        throw new MyException("以下教职工:【" + peopleName + "】已绑定其他考勤规则,无法添加");
                     }
-                    peopleName += relations.get(i).getName();
-                }
-                if(!relations.isEmpty()){
-                    throw new MyException("以下教职工:【" + peopleName + "】已绑定其他考勤规则,无法添加");
                 }
+
                 insertList.addAll(userList);
             }
         }else if(attendanceRuleCategory.getRoleId() != null && attendanceRuleCategory.getRoleId() == 3){//学生
@@ -366,25 +369,28 @@ public class AttendanceRuleCategoryServiceImpl extends MPJBaseServiceImpl<Attend
                 );
                 //查询这部分人中是否已经有人有规则了
                 List<Long> relationUserIds = userList.stream().map(XjrUser::getId).collect(Collectors.toList());
-                List<XjrUser> relations = xjrUserService.list(
-                    new MPJLambdaWrapper<XjrUser>()
-                    .select(XjrUser::getId)
-                    .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
-                    .leftJoin(AttendanceUserRelation.class, AttendanceUserRelation::getUserId, XjrUser::getId)
-                    .eq(AttendanceUserRelation::getDeleteMark, DeleteMark.NODELETE.getCode())
-                    .in(AttendanceUserRelation::getUserId, relationUserIds)
-                    .ne(AttendanceUserRelation::getAttendanceRuleCategoryId, attendanceRuleCategory.getId())
-                );
-                String peopleName = "";
-                for (int i = 0; i < relations.size(); i ++){
-                    if(i > 0){
-                        peopleName += ",";
+                if(!relationUserIds.isEmpty()){
+                    List<XjrUser> relations = xjrUserService.list(
+                            new MPJLambdaWrapper<XjrUser>()
+                                    .select(XjrUser::getId)
+                                    .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
+                                    .leftJoin(AttendanceUserRelation.class, AttendanceUserRelation::getUserId, XjrUser::getId)
+                                    .eq(AttendanceUserRelation::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                    .in(AttendanceUserRelation::getUserId, relationUserIds)
+                                    .ne(AttendanceUserRelation::getAttendanceRuleCategoryId, attendanceRuleCategory.getId())
+                    );
+                    String peopleName = "";
+                    for (int i = 0; i < relations.size(); i ++){
+                        if(i > 0){
+                            peopleName += ",";
+                        }
+                        peopleName += relations.get(i).getName();
+                    }
+                    if(!relations.isEmpty()){
+                        throw new MyException("以下学生:【" + peopleName + "】已绑定其他考勤规则,无法修改");
                     }
-                    peopleName += relations.get(i).getName();
-                }
-                if(!relations.isEmpty()){
-                    throw new MyException("以下学生:【" + peopleName + "】已绑定其他考勤规则,无法修改");
                 }
+
                 insertList.addAll(userList);
             }
         }

+ 6 - 0
src/main/java/com/xjrsoft/module/attendance/vo/TeacherStatisticsPageVo.java

@@ -31,4 +31,10 @@ public class TeacherStatisticsPageVo {
 
     @ApiModelProperty("考勤时间")
     private LocalDateTime recordTime;
+
+    @ApiModelProperty("考勤方式")
+    private String attendanceMode;
+
+    @ApiModelProperty("车牌号")
+    private String carNumber;
 }

+ 8 - 3
src/main/java/com/xjrsoft/module/hikvision/controller/EventController.java

@@ -57,6 +57,8 @@ public class EventController {
         new Thread(() -> {
             try {
                 outInRecordUtil.GetVehicleRecordTest(faceImportMapper, eventData);
+                outInRecordUtil.UpdatePicVehicleRecordTest(eventData);
+                outInRecordUtil.UpdateReleaseVehicleRecordTest(eventData);
             } catch (ParseException e) {
                 throw new RuntimeException(e);
             }
@@ -208,9 +210,12 @@ public class EventController {
         ApiUtil apiUtil = new ApiUtil();
         JsonArray eventList = new JsonArray();
 //*******手动更改****************************************************
-//        eventList.add(196893);
-        eventList.add(771760130);
-        eventList.add(771760133);
+        eventList.add(196893);
+//        eventList.add(197151);
+        eventList.add(1392513025); //访客登记
+        eventList.add(1392513026); //访客签离
+//        eventList.add(771760130);
+//        eventList.add(771760133);
 //******************************************************************
         JsonObject paramJson = new JsonObject();
         paramJson.add("eventTypes", eventList);

+ 35 - 29
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")==null?"":objectMap.get("mobile").toString());
+            paramJson.addProperty("jobNo", objectMap.get("user_name").toString());
+            paramJson.addProperty("birthday", objectMap.get("birthday")==null?"":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());
             }
         }
 
@@ -315,7 +321,7 @@ public class DataUtil {
         return idMap;
     }
 
-    public Map<String, String> insertStudent(String tableName, Map<String, String> tableData) throws Exception {
+    public Map<String, String> insertStudent(String tableName, Map<String, String> tableData) {
         String sql = "SELECT t1.id,t1.name,CONCAT(t3.id,'-',t4.name,'-',t3.class_type,'-',t2.stduy_status)," +
                 " t1.user_name,t1.gender,t1.birth_date,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" +
@@ -401,22 +407,22 @@ public class DataUtil {
         JsonArray paramArray = new JsonArray();
         Map<Integer, String> clientMap = new HashMap<>();
         for(int i = 0; i < list.size(); i ++){
-            String[] el = SqlRunnerAdapterUtil.convertMapToStringArray(list.get(i));
-            if(tableData != null && tableData.containsKey(el[0])){
+            Map<String, Object> objectMap = list.get(i);
+            if(tableData != null && tableData.containsKey(objectMap.get("id").toString())){
                 continue;
             }
             JsonObject paramJson = new JsonObject();
             paramJson.addProperty("clientId", i);
-            paramJson.addProperty("personId", el[0]);
-            paramJson.addProperty("personName", el[1]);
-            paramJson.addProperty("orgIndexCode", deptMap.get(el[3]));
-            paramJson.addProperty("phoneNo", el[5]);
-            paramJson.addProperty("jobNo", el[9]);
-            paramJson.addProperty("birthday", el[4]);
+            paramJson.addProperty("personId", objectMap.get("id").toString());
+            paramJson.addProperty("personName", objectMap.get("name").toString());
+            paramJson.addProperty("orgIndexCode", objectMap.get("dept_id").toString());
+            paramJson.addProperty("phoneNo", objectMap.get("mobile")==null?"":objectMap.get("mobile").toString());
+            paramJson.addProperty("jobNo", objectMap.get("user_name").toString());
+            paramJson.addProperty("birthday", objectMap.get("birth_date")==null?"":objectMap.get("birth_date").toString());
             paramJson.addProperty("personType", 1);
 
             int gender;
-            switch (el[2]) {
+            switch (objectMap.get("gender").toString()) {
                 case "SB10001":
                     gender = 1;
                     break;
@@ -430,7 +436,7 @@ public class DataUtil {
             paramJson.addProperty("gender", gender);
             paramArray.add(paramJson);
 
-            clientMap.put(i, el[0]);
+            clientMap.put(i, objectMap.get("id").toString());
         }
 
         String apiPath = "/api/resource/v1/person/batch/add";

+ 178 - 54
src/main/java/com/xjrsoft/module/hikvision/util/OutInRecordUtil.java

@@ -5,6 +5,7 @@ import com.google.gson.Gson;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
+import com.xjrsoft.common.enums.OutInStatusEnum;
 import com.xjrsoft.common.mybatis.SqlRunnerAdapter;
 import com.xjrsoft.common.utils.SqlRunnerAdapterUtil;
 import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails;
@@ -37,7 +38,7 @@ public class OutInRecordUtil {
 
         String updSql = "UPDATE attendance_user_relation SET " +
                 "attendance_status = '" + attendanceStatus + "', attendance_time = '" + recordTime + "' " +
-                "WHERE user_id = '" + userId + "' AND delete_mark = 0";
+                "WHERE user_id = '" + userId + "', attendance_mode = '人脸' AND delete_mark = 0";
         SqlRunnerAdapter.db().update(updSql);
     }
 
@@ -51,7 +52,7 @@ public class OutInRecordUtil {
 
         String updSql = "UPDATE attendance_user_relation SET " +
                 "attendance_status = '" + attendanceStatus + "', attendance_time = '" + recordTime + "' " +
-                "WHERE user_id = '" + userId + "' AND delete_mark = 0";
+                "WHERE user_id = '" + userId + "', attendance_mode = '人脸' AND delete_mark = 0";
         SqlRunnerAdapter.db().update(updSql);
     }
 
@@ -90,10 +91,10 @@ public class OutInRecordUtil {
 
         SqlRunnerAdapter.db().dynamicInsert(tableName, where);
 
-        //车辆入库后,判定教师考状态
+        //车辆入库后,判定教师考状态
         if(carMessageApplyId != 0){
             String selectTable = "car_message_apply";
-            Entity selectWhere = Entity.create(tableName);
+            Entity selectWhere = Entity.create(selectTable);
             selectWhere.set("car_message_apply_id", carMessageApplyId);
             selectWhere.set("plan_no", planNo);
             Map<String, Object> objectMap = SqlRunnerAdapter.db().dynamicSelectOne(selectTable, selectWhere);
@@ -103,11 +104,43 @@ public class OutInRecordUtil {
 
             String updSql = "UPDATE attendance_user_relation SET " +
                     "attendance_status = '" + attendanceStatus + "', attendance_time = '" + recordTime + "' " +
-                    "WHERE user_id = '" + userId + "' AND delete_mark = 0";
+                    "WHERE user_id = '" + userId + "', attendance_mode = '车辆', car_number = '" + planNo + "' AND delete_mark = 0";
             SqlRunnerAdapter.db().update(updSql);
         }
     }
 
+    private void updatePicVehicleRecord(String eventId, String photo, int releaseWayInt, int releaseReasonInt, int releaseResultInt) {
+        String photoValue = (photo != null && !photo.equals("null")) ? photo : "";
+
+        String tableName = "car_out_in_record";
+
+        Entity params = Entity.create();
+        params.set("face_photo", photoValue);
+        params.set("release_way", releaseWayInt);
+        params.set("release_reason", releaseReasonInt);
+        params.set("release_result", releaseResultInt);
+
+        Entity where = Entity.create();
+        where.set("cross_record_syscode", eventId);
+
+        // 执行更新操作
+        SqlRunnerAdapter.db().dynamicUpdate(tableName, params, where);
+    }
+
+    private void updateReleaseVehicleRecord(String eventId, int releaseWayInt, int releaseReasonInt, int releaseResultInt) {
+        String tableName = "car_out_in_record";
+
+        Entity params = Entity.create();
+        params.set("release_way", releaseWayInt);
+        params.set("release_reason", releaseReasonInt);
+        params.set("release_result", releaseResultInt);
+
+        Entity where = Entity.create();
+        where.set("cross_record_syscode", eventId);
+
+        SqlRunnerAdapter.db().dynamicUpdate(tableName, params, where);
+    }
+
     public void GetTeacherAndStudentRecords(FaceImportMapper faceImportMapper) throws ParseException {
         JsonArray responseBuilder = new JsonArray();
 
@@ -149,7 +182,7 @@ public class OutInRecordUtil {
             if (personId == null) continue;
 
             int statusInt = item.get("inAndOutType").getAsInt();
-            int status = -1;
+            int status = 1;
             switch (statusInt){
                 case 0:
                     status = 1;
@@ -216,7 +249,7 @@ public class OutInRecordUtil {
                                 .withMinute(ruleDetails.getPmEndTime().toLocalTime().getMinute())
                                 .withSecond(ruleDetails.getPmEndTime().toLocalTime().getSecond());
                     }
-                    if (status == 0) {//出
+                    if (status == OutInStatusEnum.goOut.getCode()) {//出
                         if (recordTime.isBefore(amEndTime) && recordTime.isAfter(amStartTime)) {
                             attendanceStatus = "早退";
                         } else if (recordTime.isBefore(pmEndTime) && recordTime.isAfter(pmStartTime)) {
@@ -278,7 +311,7 @@ public class OutInRecordUtil {
                             .withMinute(ruleDetails.getEveningEndTime().toLocalTime().getMinute())
                             .withSecond(ruleDetails.getEveningEndTime().toLocalTime().getSecond());
                 }
-                if(status == 0){//出
+                if(status == OutInStatusEnum.goOut.getCode()){//出
                     if(recordTime.isBefore(amEndTime) && recordTime.isAfter(amStartTime)){
                         attendanceStatus = "早退";
                     }else if(recordTime.isBefore(pmEndTime) && recordTime.isAfter(pmStartTime)){
@@ -367,7 +400,7 @@ public class OutInRecordUtil {
             String eventId = item.get("eventId").isJsonNull() ? null : item.get("eventId").getAsString();
             String deviceDesc = item.get("deviceDesc").isJsonNull() ? null : item.get("deviceDesc").getAsString();
 
-            int status = -1;
+            int status = 1;
             for (JsonElement e : doorEventsResponse){
                 JsonObject ele = e.getAsJsonObject();
                 if (ele.get("eventId") == item.get("eventId")){
@@ -397,6 +430,8 @@ public class OutInRecordUtil {
             JsonObject paramJson = new JsonObject();
             paramJson.addProperty("pageNo", pageNo.getAndIncrement());
             paramJson.addProperty("pageSize", pageSize);
+//            paramJson.addProperty("startTime", "2024-06-18T00:00:00+08:00");
+//            paramJson.addProperty("endTime", "2024-06-19T16:00:00+08:00");
 
             String response = apiUtil.doPost(apiPath, String.valueOf(paramJson), null);
             JsonElement responseElement = new Gson().fromJson(response, JsonElement.class);
@@ -489,8 +524,11 @@ public class OutInRecordUtil {
         ApiUtil apiUtil = new ApiUtil();
         String apiPath = "/api/acs/v2/door/events";
         JsonObject paramJson = new JsonObject();
+        JsonArray eventList = new JsonArray();
+        eventList.add(196893); // 只获取人脸通过的
         paramJson.addProperty("pageNo", pageNo.get());
         paramJson.addProperty("pageSize", pageSize);
+        paramJson.add("eventTypes", eventList);
 
         return apiUtil.doPost(apiPath, String.valueOf(paramJson), null);
     }
@@ -525,7 +563,7 @@ public class OutInRecordUtil {
                 String happenTime = eventObject.get("happenTime").getAsString();
                 String extEventPictureURL = dataObject.get("ExtEventPictureURL").getAsString();
                 int statusInt = dataObject.get("ExtEventInOut").getAsInt();
-                int status = -1;
+                int status = 1;
                 switch (statusInt){
                     case 0:
                         status = 1;
@@ -575,60 +613,146 @@ public class OutInRecordUtil {
                 for (JsonElement eventElement : eventsArray) {
                     JsonObject eventObject = eventElement.getAsJsonObject();
                     JsonObject dataObject = eventObject.getAsJsonObject("data");
+                    if (dataObject.get("eventCmd").getAsInt() == 1){
+                        String carNum = dataObject.get("plateNo").getAsString().trim();
+                        String eventIndex = dataObject.get("eventIndex").getAsString().trim();
+                        String carMessageApplyIdStr = faceImportMapper.GetCarMessageApplyIdByCarNumber(carNum);
+                        Long carId = (carMessageApplyIdStr == null || carMessageApplyIdStr.isEmpty()) ? 0 : Long.parseLong(carMessageApplyIdStr);
+                        String eventTime = ChangeTime(dataObject.get("time").getAsString());
+
+                        int releaseWayInt = -1;
+                        int releaseReasonInt = -1;
+                        int releaseResultInt = -1;
+                        JsonObject inResultObject = dataObject.getAsJsonObject("inResult");
+                        JsonObject outResultObject = dataObject.getAsJsonObject("outResult");
+                        JsonObject inoutResult = (inResultObject != null && !inResultObject.isJsonNull()) ? inResultObject : outResultObject;
+                        if (inoutResult != null) {
+                            JsonObject rlsResultObject = inoutResult.getAsJsonObject("rlsResult");
+                            if (rlsResultObject.has("releaseWay") && rlsResultObject.has("releaseReason") && rlsResultObject.has("releaseResult")) {
+                                releaseWayInt = rlsResultObject.get("releaseWay").getAsInt();
+                                releaseReasonInt = rlsResultObject.get("releaseReason").getAsInt();
+                                releaseResultInt = rlsResultObject.get("releaseResult").getAsInt();
+                                if (releaseResultInt == 13) releaseResultInt = 1;
+                            }
+                        }
 
-                    String carNum = dataObject.get("plateNo").getAsString().trim();
-                    String eventIndex = dataObject.get("eventIndex").getAsString().trim();
-                    String carMessageApplyIdStr = faceImportMapper.GetCarMessageApplyIdByCarNumber(carNum);
-                    Long carId = (carMessageApplyIdStr == null || carMessageApplyIdStr.isEmpty()) ? 0 : Long.parseLong(carMessageApplyIdStr);
-                    String eventTime = ChangeTime(dataObject.get("time").getAsString());
-
-                    int releaseWayInt = -1;
-                    int releaseReasonInt = -1;
-                    int releaseResultInt = -1;
-                    JsonObject inResultObject = dataObject.getAsJsonObject("inResult");
-                    JsonObject outResultObject = dataObject.getAsJsonObject("outResult");
-                    JsonObject inoutResult = (inResultObject != null && !inResultObject.isJsonNull()) ? inResultObject : outResultObject;
-                    if (inoutResult != null) {
-                        JsonObject rlsResultObject = inoutResult.getAsJsonObject("rlsResult");
-                        if (rlsResultObject.has("releaseWay") && rlsResultObject.has("releaseReason") && rlsResultObject.has("releaseResult")) {
-                            releaseWayInt = rlsResultObject.get("releaseWay").getAsInt();
-                            releaseReasonInt = rlsResultObject.get("releaseReason").getAsInt();
-                            releaseResultInt = rlsResultObject.get("releaseResult").getAsInt();
+                        String carAttributeName = dataObject.get("carAttributeName").getAsString().trim();
+                        int vehicleType = dataObject.get("vehicleType").getAsInt();
+                        int category = -1;
+                        switch (carAttributeName){
+                            case "临时车":
+                                category = 1;
+                                break;
+                            case "固定车":
+                                category = 0;
+                                break;
                         }
-                    }
 
-                    String carAttributeName = dataObject.get("carAttributeName").getAsString().trim();
-                    int vehicleType = dataObject.get("vehicleType").getAsInt();
-                    int category = -1;
-                    switch (carAttributeName){
-                        case "临时车":
-                            category = 1;
-                            break;
-                        case "固定车":
-                            category = 0;
-                            break;
-                    }
+                        String facePicUri = "";
+                        JsonObject picUrlObject = dataObject.getAsJsonObject("picUrl");
+                        if (picUrlObject != null && picUrlObject.has("vehiclePicUrl")) {
+                            facePicUri = picUrlObject.get("vehiclePicUrl").getAsString();
+                        }
+
+                        String statusStr = dataObject.get("roadwayName").getAsString();
+                        int statusInt = -1;
+                        if (statusStr.contains("入")) {
+                            statusInt = 0;
+                        } else if (statusStr.contains("出")) {
+                            statusInt = 1;
+                        }
 
-                    String facePicUri = "";
-                    JsonObject picUrlObject = dataObject.getAsJsonObject("picUrl");
-                    if (picUrlObject != null && picUrlObject.has("vehiclePicUrl")) {
-                        facePicUri = picUrlObject.get("vehiclePicUrl").getAsString();
+                        String phone = faceImportMapper.GetPhoneNumberByPlanNum(carNum);
+                        String name = faceImportMapper.GetNameByPlanNum(carNum);
+
+                        if (vehicle_id_list.contains(eventIndex)) continue;
+
+                        vehicleInsertRecord(carId, eventTime, releaseReasonInt, category, ApiUtil.GetRedirectURL(facePicUri), statusInt, carNum, eventIndex, releaseResultInt, releaseWayInt,vehicleType,phone,name);
                     }
+                }
+            } catch (Exception e) {
+                log.info(String.valueOf(e));
+            }
+        }
+    }
+
+    public void UpdatePicVehicleRecordTest(String data) {
+        if (data != null) {
+            try {
+                JsonObject jsonObject = new Gson().fromJson(data, JsonObject.class);
+                JsonObject paramsObject = jsonObject.getAsJsonObject("params");
+                JsonArray eventsArray = paramsObject.getAsJsonArray("events");
+
+                for (JsonElement eventElement : eventsArray) {
+                    JsonObject eventObject = eventElement.getAsJsonObject();
+                    JsonObject dataObject = eventObject.getAsJsonObject("data");
 
-                    String statusStr = dataObject.get("roadwayName").getAsString();
-                    int statusInt = 0;
-                    if (statusStr.contains("入")) {
-                        statusInt = 0;
-                    } else if (statusStr.contains("出")) {
-                        statusInt = 1;
+                    if(dataObject.get("eventCmd").getAsInt() == 2){
+                        String eventIndex = dataObject.get("eventIndex").getAsString().trim();
+
+                        int releaseWayInt = -1;
+                        int releaseReasonInt = -1;
+                        int releaseResultInt = -1;
+                        JsonObject inResultObject = dataObject.getAsJsonObject("inResult");
+                        JsonObject outResultObject = dataObject.getAsJsonObject("outResult");
+                        JsonObject inoutResult = (inResultObject != null && !inResultObject.isJsonNull()) ? inResultObject : outResultObject;
+                        if (inoutResult != null) {
+                            JsonObject rlsResultObject = inoutResult.getAsJsonObject("rlsResult");
+                            if (rlsResultObject.has("releaseWay") && rlsResultObject.has("releaseReason") && rlsResultObject.has("releaseResult")) {
+                                releaseWayInt = rlsResultObject.get("releaseWay").getAsInt();
+                                releaseReasonInt = rlsResultObject.get("releaseReason").getAsInt();
+                                releaseResultInt = rlsResultObject.get("releaseResult").getAsInt();
+                                if (releaseResultInt == 13) releaseResultInt = 1;
+                            }
+                        }
+
+                        String facePicUri = "";
+                        JsonObject picUrlObject = dataObject.getAsJsonObject("picUrl");
+                        if (picUrlObject != null && picUrlObject.has("vehiclePicUrl")) {
+                            facePicUri = picUrlObject.get("vehiclePicUrl").getAsString();
+                        }
+
+                        updatePicVehicleRecord(eventIndex, ApiUtil.GetRedirectURL(facePicUri), releaseWayInt, releaseReasonInt, releaseResultInt);
                     }
+                }
+            } catch (Exception e) {
+                log.info(String.valueOf(e));
+            }
+        }
+    }
+
+    public void UpdateReleaseVehicleRecordTest(String data) {
+        if (data != null) {
+            try {
+                JsonObject jsonObject = new Gson().fromJson(data, JsonObject.class);
+                JsonObject paramsObject = jsonObject.getAsJsonObject("params");
+                JsonArray eventsArray = paramsObject.getAsJsonArray("events");
 
-                    String phone = faceImportMapper.GetPhoneNumberByPlanNum(carNum);
-                    String name = faceImportMapper.GetNameByPlanNum(carNum);
+                for (JsonElement eventElement : eventsArray) {
+                    JsonObject eventObject = eventElement.getAsJsonObject();
+                    JsonObject dataObject = eventObject.getAsJsonObject("data");
 
-                    if (vehicle_id_list.contains(eventIndex)) continue;
+                    if (dataObject.get("eventCmd").getAsInt() == 3 || dataObject.get("eventCmd").getAsInt() == 4) {
+                        String eventIndex = dataObject.get("eventIndex").getAsString().trim();
+
+                        int releaseWayInt = -1;
+                        int releaseReasonInt = -1;
+                        int releaseResultInt = -1;
+                        JsonObject inResultObject = dataObject.getAsJsonObject("inResult");
+                        JsonObject outResultObject = dataObject.getAsJsonObject("outResult");
+                        JsonObject inoutResult = (inResultObject != null && !inResultObject.isJsonNull()) ? inResultObject : outResultObject;
+                        if (inoutResult != null) {
+                            JsonObject rlsResultObject = inoutResult.getAsJsonObject("rlsResult");
+                            if (rlsResultObject.has("releaseWay") && rlsResultObject.has("releaseReason") && rlsResultObject.has("releaseResult")) {
+                                releaseWayInt = rlsResultObject.get("releaseWay").getAsInt();
+                                releaseReasonInt = rlsResultObject.get("releaseReason").getAsInt();
+                                releaseResultInt = rlsResultObject.get("releaseResult").getAsInt();
+                                if (releaseResultInt == 13) releaseResultInt = 1;
+                            }
+                        }
 
-                    vehicleInsertRecord(carId, eventTime, releaseReasonInt, category, ApiUtil.GetRedirectURL(facePicUri), statusInt, carNum, eventIndex, releaseResultInt, releaseWayInt,vehicleType,phone,name);
+                        updateReleaseVehicleRecord(eventIndex, releaseWayInt, releaseReasonInt, releaseResultInt);
+                    }
                 }
             } catch (Exception e) {
                 log.info(String.valueOf(e));

+ 84 - 42
src/main/java/com/xjrsoft/module/job/AttenDanceWarnNoticeTask.java

@@ -13,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;
@@ -61,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;
         }
         //获取当前时间
@@ -95,11 +93,6 @@ public class AttenDanceWarnNoticeTask {
             allUserStatus.put(userRelation.getUserId(), userRelation);
         }
 
-        //判断所有当前时间下,哪几条规则需要进行提醒
-        Map<Long, Integer> ruleDetailsJudgeMap = judgeExecuteNotice(now, ruleDetailsList);
-
-        //查询
-
         //根据规则中的用户id查询出所有绑定了微信的学生和教师
         if(allTodyRule.isEmpty()){
             log.info("未能查询出规则,不进行推送");
@@ -108,20 +101,25 @@ public class AttenDanceWarnNoticeTask {
 
         //获取最近的时间
         LocalDateTime recentlyTime = getRecentlyTime(ruleDetailsList, now);
-        if(!recentlyTime.isEqual(now)){
+        if(recentlyTime.getHour() != now.getHour() && Math.abs(recentlyTime.getMinute() - now.getMinute()) <= 2){
             log.info("未到时间,不进行推送");
             return;
         }
         String wechatTemplate = weChatUtil.getAttenDanceWarnTemplate();
-        WechatMessageLog log = wechatMessageLogService.getOne(
+        List<WechatMessageLog> list = wechatMessageLogService.list(
                 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;
-        }
+//        if(!list.isEmpty()){//已经推送过,不再进行推送
+//            return;
+//        }
+
+        LocalDateTime attendanceTime = getAttendanceTime(ruleDetailsList, now);
+
+        //判断所有当前时间下,哪几条规则需要进行提醒
+        Map<Long, Integer> ruleDetailsJudgeMap = judgeExecuteNotice(now, ruleDetailsList, recentlyTime);
 
         WechatMessageLog messageLog = new WechatMessageLog();
         messageLog.setTemplateId(wechatTemplate);
@@ -134,11 +132,6 @@ public class AttenDanceWarnNoticeTask {
             if(status == 0){
                 continue;
             }
-            //查询这个用户最新的考勤状态
-            AttendanceUserRelation userRelation = allUserStatus.get(xjrUser.getId());
-            if(userRelation.getAttendanceTime().toLocalDate().isEqual(now.toLocalDate()) && "到校".equals(userRelation.getAttendanceStatus())){
-                continue;
-            }
 
             WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
             weChatSendMessageDto.setUserId(xjrUser.getOpenId());
@@ -146,6 +139,11 @@ public class AttenDanceWarnNoticeTask {
             weChatSendMessageDto.setMsgId(IdUtil.getSnowflakeNextId() + "");
             JSONObject paramJson = new JSONObject();
 
+
+            JSONObject time5 = new JSONObject();
+            time5.put("value", attendanceTime.format(formatter));
+            paramJson.put("time5", time5);
+
             JSONObject thing8 = new JSONObject();
             thing8.put("value", xjrUser.getName());
             paramJson.put("thing8", thing8);
@@ -156,9 +154,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);
 
@@ -177,53 +183,52 @@ 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);
+                    Long amBetween = Math.abs(ChronoUnit.MINUTES.between(judgeTime, amStartTime));
+                    if(recentlyTime.isEqual(amStartTime.plusMinutes(- ruleDetails.getAgoMinutes())) && amBetween >= ruleDetails.getAgoMinutes() - 1 && amBetween <= ruleDetails.getAgoMinutes() + 1){//相差分钟数小于0
+                        result.put(ruleDetails.getId(), 1);
+                    }else if(recentlyTime.isEqual(amStartTime.plusMinutes(ruleDetails.getOverMinutes())) && 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);
+                    Long pmBetween = Math.abs(ChronoUnit.MINUTES.between(judgeTime, pmStartTime));
+                    if(recentlyTime.isEqual(pmStartTime.plusMinutes(- ruleDetails.getAgoMinutes())) && pmBetween >= ruleDetails.getAgoMinutes() - 1 && pmBetween <= ruleDetails.getAgoMinutes() + 1){//相差分钟数小于0
+                        result.put(ruleDetails.getId(), 1);
+                    }else if(recentlyTime.isEqual(pmStartTime.plusMinutes(ruleDetails.getOverMinutes())) && 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);
+                    Long eveningBetween = Math.abs(ChronoUnit.MINUTES.between(judgeTime, eveningStartTime));
+                    if(recentlyTime.isEqual(eveningStartTime.plusMinutes(- ruleDetails.getAgoMinutes())) && eveningBetween >= ruleDetails.getAgoMinutes() - 1 && eveningBetween <= ruleDetails.getAgoMinutes() + 1){//相差分钟数小于0
+                        result.put(ruleDetails.getId(), 1);
+                    }else if(recentlyTime.isEqual(eveningStartTime.plusMinutes(ruleDetails.getOverMinutes())) && 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
@@ -238,6 +243,43 @@ 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.plusMinutes(- ruleDetail.getAgoMinutes()));
+                    result.add(amStartTime.plusMinutes(ruleDetail.getOverMinutes()));
+                }
+                if(ruleDetail.getPmStartTime() != null){
+                    LocalDateTime pmStartTime = now.with(ruleDetail.getPmStartTime().toLocalTime());
+                    result.add(pmStartTime.plusMinutes(- ruleDetail.getAgoMinutes()));
+                    result.add(pmStartTime.plusMinutes(ruleDetail.getOverMinutes()));
+                }
+
+                if(ruleDetail.getEveningStartTime() != null){
+                    LocalDateTime eveningStartTime = now.with(ruleDetail.getEveningStartTime().toLocalTime());
+                    result.add(eveningStartTime.plusMinutes(- ruleDetail.getAgoMinutes()));
+                    result.add(eveningStartTime.plusMinutes(ruleDetail.getOverMinutes()));
+                }
+            }
+        }
+        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));
+    }
+
+    LocalDateTime getAttendanceTime(List<AttendanceRuleDetails> ruleDetails, LocalDateTime now){
         List<LocalDateTime> result = new ArrayList<>();
         for (AttendanceRuleDetails ruleDetail : ruleDetails) {
             if(ruleDetail.getIsAllowInOutSchool() != null && ruleDetail.getIsAllowInOutSchool() == 1

+ 21 - 15
src/main/java/com/xjrsoft/module/job/AttendanceMessageTask.java

@@ -43,6 +43,7 @@ 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;
 
 /**
@@ -83,7 +84,7 @@ public class AttendanceMessageTask {
     @Autowired
     private IWechatMessageLogService wechatMessageLogService;
 
-    @Scheduled(cron = "0 */15 * * * ?")
+    @Scheduled(cron = "0 */1 * * * ?")
     public void RefreshConnectionPool() {
         String active = SpringUtil.getActiveProfile();
         if(!"prod".equals(active)){
@@ -149,21 +150,26 @@ public class AttendanceMessageTask {
         String format = recentlyTime.format(formatter);
 
         int userCount = 0;
+        Set<Integer> roleTypes = list.stream().map(AttendanceMessageSet::getRoleType).collect(Collectors.toSet());
+        Set<Long> setIds = list.stream().map(AttendanceMessageSet::getId).collect(Collectors.toSet());
+
+        //查询需要通知的人
+        List<XjrUser> userList = userService.list(
+                new MPJLambdaWrapper<XjrUser>().distinct()
+                        .select(XjrUser::getId)
+                        .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
+                        .leftJoin(UserRoleRelation.class, UserRoleRelation::getUserId, XjrUser::getId)
+                        .leftJoin(AttendanceMessageUserRelation.class, AttendanceMessageUserRelation::getUserId, XjrUser::getId)
+                        .in(UserRoleRelation::getRoleId, roleTypes)
+                        .in(AttendanceMessageUserRelation::getAttendanceMessageSetId, setIds)
+        );
+
 
         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;
@@ -176,13 +182,13 @@ public class AttendanceMessageTask {
                                 .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId)
                 );
                 //查询进入记录,就是实际到校的人数
-                long outInRecords = teachertOutInRecordService.count(
+                List<TeacherOutInRecord> outInRecords = teachertOutInRecordService.list(
                         new MPJLambdaWrapper<TeacherOutInRecord>()
                                 .le(TeacherOutInRecord::getRecordTime, recentlyTime)
                                 .eq(TeacherOutInRecord::getStatus, 1)
-                                .eq("DATE_FORMAT(record_time, '%Y-%m-%d')" , recentlyTime.toLocalDate())
-                                .groupBy(TeacherOutInRecord::getUserId)
+                                .eq("DATE_FORMAT(record_time, '%Y-%m-%d')", recentlyTime.toLocalDate())
                 );
+                List<Long> collect = outInRecords.stream().map(TeacherOutInRecord::getUserId).collect(Collectors.toList());
 
                 WeChatSendMessageDto weChatSendMessageDto = new WeChatSendMessageDto();
                 weChatSendMessageDto.setTemplateId(wechatTemplate);
@@ -201,7 +207,7 @@ public class AttendanceMessageTask {
                 paramJson.put("const23", const23);
 
                 JSONObject character_string18 = new JSONObject();
-                character_string18.put("value", teacherCout - outInRecords);
+                character_string18.put("value", teacherCout - collect.size());
                 paramJson.put("character_string18", character_string18);
 
                 JSONObject character_string16 = new JSONObject();

+ 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);
             }

+ 5 - 1
src/main/java/com/xjrsoft/module/outint/entity/CarOutInRecord.java

@@ -10,6 +10,7 @@ import io.swagger.annotations.ApiModelProperty;
 import lombok.Data;
 
 import java.io.Serializable;
+import java.time.LocalDateTime;
 import java.util.Date;
 
 
@@ -78,7 +79,7 @@ public class CarOutInRecord implements Serializable {
     * 记录时间
     */
     @ApiModelProperty("记录时间")
-    private String recordTime;
+    private LocalDateTime recordTime;
     /**
     * 人脸照片
     */
@@ -130,4 +131,7 @@ public class CarOutInRecord implements Serializable {
      */
     @ApiModelProperty("姓名")
     private String name;
+
+    @ApiModelProperty("车辆id(car_message_apply),固定车辆使用")
+    private Long carMessageApplyId;
 }

+ 1 - 0
src/main/java/com/xjrsoft/module/personnel/controller/StundentFaceProcessController.java

@@ -376,6 +376,7 @@ public class StundentFaceProcessController {
                 FaceManagement faceManagement = faceManagementMap.get(studentUser.getId());
                 faceManagement.setVerifyStatus(2);
                 faceManagement.setRegisterBase64(base64String);
+                faceManagement.setFileId(folderId);
                 faceManagementService.update(faceManagement);
             }
         }

+ 1 - 0
src/main/resources/mapper/outin/StudentOutInRecordMapper.xml

@@ -39,5 +39,6 @@
         INNER JOIN base_student_school_roll t2 ON t1.user_id = t2.user_id
         WHERE t1.delete_mark = 0 AND t2.delete_mark = 0
         AND t1.record_time BETWEEN #{startTime} AND #{endTime}
+        order by t1.record_time
     </select>
 </mapper>

+ 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));
     }
 
 }

+ 52 - 52
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");
 
@@ -137,8 +137,8 @@ class HikvisionBaseDataTaskTest {
 //        String carTableName = "car_message_apply";
 //        selectCar(use, carTableName);
 
-//        outInRecordUtil.GetVehicleRecord(use,faceImportMapper);
-        outInRecordUtil.GetTeacherAndStudentRecords(faceImportMapper);
+        outInRecordUtil.GetVehicleRecord(faceImportMapper);
+//        outInRecordUtil.GetTeacherAndStudentRecords(faceImportMapper);
 ////        selecAllPersonById(use);
 //        selectResource(use);
     }
@@ -170,43 +170,40 @@ 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 t3.class_type IS NOT NULL";
+                //" 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();
         Map<String, String> header = new HashMap<>();
         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;
-            }
+        for(int i = 1; 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")==null?"":objectMap.get("mobile").toString());
+            paramJson.addProperty("jobNo", objectMap.get("user_name").toString());
+            paramJson.addProperty("birthday", objectMap.get("birthday")==null?"":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";
+                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;
     }