Pārlūkot izejas kodu

考勤状态判定

dzx 1 gadu atpakaļ
vecāks
revīzija
67421a0b28

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

@@ -111,6 +111,9 @@ public class StudentStatisticsController {
 
                 Integer lateCount = 0;
                 for (StudentOutInRecordVo outInRecord : notStayMap.get(record.getId())) {
+                    if(outInRecord.getStatus() == 0){
+                        continue;
+                    }
                     AttendanceRuleDetailsUserVo ruleDetails = notStayTodyRule.get(outInRecord.getUserId());
                     if(dto.getTimePeriod() == 1 && outInRecord.getRecordTime().toLocalTime().compareTo(ruleDetails.getAmStartTime()) > 0){
                         lateCount ++;
@@ -119,6 +122,9 @@ public class StudentStatisticsController {
                     }
                 }
                 for (StudentOutInRecordVo outInRecord : stayMap.get(record.getId())) {
+                    if(outInRecord.getStatus() == 0){
+                        continue;
+                    }
                     AttendanceRuleDetailsUserVo ruleDetails = staySundayRule.get(outInRecord.getUserId());
                     if(dto.getTimePeriod() == 1 && outInRecord.getRecordTime().toLocalTime().compareTo(ruleDetails.getAmStartTime()) > 0){
                         lateCount ++;
@@ -288,4 +294,86 @@ public class StudentStatisticsController {
         return RT.ok(pageOutput);
     }
 
+    @GetMapping(value = "/leaving-school")
+    @ApiOperation(value="离校统计")
+    @SaCheckPermission("statistics:detail")
+    public RT<PageOutput<ClassStatisticsVo>> leavingSchool(@Valid AttendanceStatisticDto dto){
+        Page<ClassStatisticsVo> attendancePage = classService.getAttendancePage(new Page<>(dto.getLimit(), dto.getSize()), dto);
+        List<Long> classIds = new ArrayList<>();
+        for (ClassStatisticsVo record : attendancePage.getRecords()) {
+            classIds.add(record.getId());
+        }
+        if(dto.getDate() != null && !"".equals(dto.getDate())){
+            DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
+            LocalDate queryDate = LocalDate.parse(dto.getDate(), formatter);
+            LocalDateTime startTime, endTime;
+
+
+            if(dto.getTimePeriod() == 1){
+                startTime = queryDate.atTime(9, 0, 0);
+                endTime = queryDate.atTime(12, 0, 0);
+            }else if(dto.getTimePeriod() == 2){
+                startTime = queryDate.atTime(12, 0, 0);
+                endTime = queryDate.atTime(18, 0, 0);
+            }else{
+                startTime = queryDate.atTime(0, 0, 0);
+                endTime = queryDate.atTime(23, 59, 59);
+            }
+            LocalDateTime lastSundayStart = startTime.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).plusDays(-1);
+            LocalDateTime lastSundayEnd = endTime.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).plusDays(-1);
+
+            //查询每个班的走读生实到人数
+            Map<Long, List<StudentOutInRecordVo>> notStayMap = studentOutInRecordService.getNotStayList(startTime, endTime, classIds);
+            //查询住校生的实到情况
+            Map<Long, List<StudentOutInRecordVo>> stayMap = studentOutInRecordService.getStayList(lastSundayStart, lastSundayEnd, classIds);
+
+            //查询各班的请假人数
+            Map<Long, Integer> classLeaveCount = studentLeaveService.getClassLeaveCount(startTime, endTime);
+
+            //查询走读生的考勤规则
+            Map<Long, AttendanceRuleDetailsUserVo> notStayTodyRule = ruleCategoryService.getAllStudentTodyRule(queryDate.getDayOfWeek().name());
+            //查询住校生生的考勤规则
+            Map<Long, AttendanceRuleDetailsUserVo> staySundayRule = ruleCategoryService.getAllStudentTodyRule(lastSundayStart.getDayOfWeek().name());
+
+            for (ClassStatisticsVo record: attendancePage.getRecords()) {
+                record.setLeaveCount(classLeaveCount.get(record.getId()));
+                record.setActualCount(notStayMap.get(record.getId()).size() + stayMap.get(record.getId()).size());
+
+                Integer lateCount = 0;
+                for (StudentOutInRecordVo outInRecord : notStayMap.get(record.getId())) {
+                    if(outInRecord.getStatus() == 1){
+                        continue;
+                    }
+                    AttendanceRuleDetailsUserVo ruleDetails = notStayTodyRule.get(outInRecord.getUserId());
+                    if(dto.getTimePeriod() == 1 && outInRecord.getRecordTime().toLocalTime().compareTo(ruleDetails.getAmStartTime()) > 0){
+                        lateCount ++;
+                    }else if(dto.getTimePeriod() == 2 && outInRecord.getRecordTime().toLocalTime().compareTo(ruleDetails.getPmStartTime()) > 0){
+                        lateCount ++;
+                    }
+                }
+                for (StudentOutInRecordVo outInRecord : stayMap.get(record.getId())) {
+                    if(outInRecord.getStatus() == 1){
+                        continue;
+                    }
+                    AttendanceRuleDetailsUserVo ruleDetails = staySundayRule.get(outInRecord.getUserId());
+                    if(dto.getTimePeriod() == 1 && outInRecord.getRecordTime().toLocalTime().compareTo(ruleDetails.getAmStartTime()) > 0){
+                        lateCount ++;
+                    }else if(dto.getTimePeriod() == 2 && outInRecord.getRecordTime().toLocalTime().compareTo(ruleDetails.getPmStartTime()) > 0){
+                        lateCount ++;
+                    }
+                }
+                record.setLateCount(lateCount);
+
+                //最后通过总人数-实到人数-请假人数计算出缺勤人数
+                record.setAbsenteeismCount(record.getStudentCount() - record.getLeaveCount() - record.getActualCount());
+
+                //计算出勤率
+                BigDecimal divide = BigDecimal.valueOf(record.getActualCount()).divide(BigDecimal.valueOf(record.getStudentCount()), 2, RoundingMode.HALF_UP);
+                record.setAttendanceRate(divide.doubleValue());
+            }
+        }
+        PageOutput<ClassStatisticsVo> pageOutput = ConventPage.getPageOutput(attendancePage, ClassStatisticsVo.class);
+        return RT.ok(pageOutput);
+    }
+
 }

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

@@ -57,7 +57,7 @@ public class TeacherStatisticsController {
     @GetMapping(value = "/teacher-details")
     @ApiOperation(value="教师考勤")
     @SaCheckPermission("statistics:detail")
-    public RT<PageOutput<TeacherStatisticsPageVo>> studentDetails(@Valid AttendanceStatisticDto dto){
+    public RT<PageOutput<TeacherStatisticsPageVo>> teacherDetails(@Valid AttendanceStatisticDto dto){
         MPJLambdaWrapper<User> queryUser = new MPJLambdaWrapper<>();
         queryUser.disableSubLogicDel().distinct()
                 .selectAs(User::getName, TeacherStatisticsPageVo::getTeacherName)
@@ -90,9 +90,13 @@ public class TeacherStatisticsController {
                     new QueryWrapper<TeacherOutInRecord>().lambda()
                             .between(TeacherOutInRecord::getRecordTime, startTime, endTime)
                             .eq(TeacherOutInRecord::getStatus, 0)
+                            .orderByAsc(TeacherOutInRecord::getRecordTime)
             );
             Map<Long, TeacherOutInRecord> outInMap = new HashMap<>();
             for (TeacherOutInRecord inRecord : outInRecords) {
+                if(outInMap.containsKey(inRecord.getUserId())){
+                    continue;
+                }
                 outInMap.put(inRecord.getUserId(), inRecord);
             }
             for (TeacherStatisticsPageVo record : voIPage.getRecords()) {

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

@@ -45,4 +45,13 @@ public class ClassStatisticsVo {
     @ApiModelProperty("出勤率")
     private Double attendanceRate;
 
+    @ApiModelProperty("应该离校人数")
+    private Integer ygLeaveSchoolCount;
+
+    @ApiModelProperty("已经离校人数")
+    private Integer yjLeaveSchoolCount;
+
+    @ApiModelProperty("未离校人数")
+    private Integer wLeaveSchoolCount;
+
 }

+ 158 - 14
src/main/java/com/xjrsoft/module/hikvision/util/Out_In_RecordUtil.java

@@ -1,33 +1,38 @@
 package com.xjrsoft.module.hikvision.util;
 
 import cn.hutool.db.Db;
-import com.alibaba.excel.Empty;
 import com.google.gson.Gson;
 import com.google.gson.JsonArray;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
+import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails;
 import com.xjrsoft.module.teacher.mapper.FaceImportMapper;
 
 import java.sql.SQLException;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
-import java.util.*;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.Date;
+import java.util.List;
+import java.util.Objects;
 import java.util.concurrent.atomic.AtomicInteger;
 
 
 public class Out_In_RecordUtil {
-    private void teacherInsertRecord(Db db, Long userId, String recordTime, String facePhoto,int status, String eventId) throws SQLException {
+    private void teacherInsertRecord(Db db, Long userId, String recordTime, String facePhoto,int status, String eventId, String attendanceStatus) throws SQLException {
 
-        String sql = "INSERT INTO teacher_out_in_record(create_date, user_id, record_time, face_photo, eventId, status,delete_mark,enabled_mark) " +
+        String sql = "INSERT INTO teacher_out_in_record(create_date, user_id, record_time, face_photo, eventId, status,delete_mark,enabled_mark, attendance_status) " +
                 "VALUES(now(), '"  + userId + "', '" + recordTime + "', '" +
-                facePhoto + "', '" + eventId + "', '" +status + "',0,1)";
+                facePhoto + "', '" + eventId + "', '" +status + "',0,1,'" + attendanceStatus + "')";
         db.execute(sql);
     }
 
-    private void studentInsertRecord(Db db, Long userId, Long teacherId, Long classId, String facePhoto, String recordTime, int status, String eventId) throws SQLException {
-        String sql = "INSERT INTO student_out_in_record(create_date, user_id, teacher_id, class_id, face_photo, record_time , eventId,status,delete_mark,enabled_mark) " +
+    private void studentInsertRecord(Db db, Long userId, Long teacherId, Long classId, String facePhoto, String recordTime, int status, String eventId, String attendanceStatus) throws SQLException {
+        String sql = "INSERT INTO student_out_in_record(create_date, user_id, teacher_id, class_id, face_photo, record_time , eventId,status,delete_mark,enabled_mark, attendance_status) " +
                 "VALUES(now(), '" + userId + "', '" + teacherId + "', '" +
-                classId + "', '" + facePhoto + "', '" + recordTime + "', '" + eventId + "', '" + status + "',0,1)";
+                classId + "', '" + facePhoto + "', '" + recordTime + "', '" + eventId + "', '" + status + "',0,1,'" + attendanceStatus + "')";
         db.execute(sql);
     }
 
@@ -74,7 +79,7 @@ public class Out_In_RecordUtil {
     private void InsertTeacherStudentRecords(Db use, JsonArray doorEventsResponse, FaceImportMapper faceImportMapper) throws SQLException, ParseException {
         List<String> teacherEventIdList = faceImportMapper.GetTeacherUrlList();
         List<String> studentEventIdList = faceImportMapper.GetStudentUrlList();
-
+        DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
         for (JsonElement element : doorEventsResponse) {
             JsonObject item = element.getAsJsonObject();
 
@@ -90,18 +95,157 @@ public class Out_In_RecordUtil {
             String uri = item.get("picUri").isJsonNull() ? null : item.get("picUri").getAsString();
             String recordTime = item.get("eventTime").isJsonNull() ? null : item.get("eventTime").getAsString();
             String eventId = item.get("eventId").isJsonNull() ? null : item.get("eventId").getAsString();
-
+            String recordTimeStr = ChangeTime(recordTime);
             if (!Objects.equals(faceImportMapper.IsStudentTypeByPersonId(personId), "学生")) {
                 // 老师记录
-                if (teacherEventIdList.contains(eventId)) continue;
-                teacherInsertRecord(use, personId, ChangeTime(recordTime), ApiUtil.GetRedirectURL(uri),status,eventId);
+                if (teacherEventIdList.contains(eventId)) {
+                    continue;
+                }
+                LocalDateTime recordTimeDate = LocalDateTime.parse(recordTimeStr, formatter);
+                String attendanceStatus = discernTeacherStatus(use, recordTimeDate, status, personId);
+                teacherInsertRecord(use, personId, recordTimeStr, ApiUtil.GetRedirectURL(uri),status,eventId, attendanceStatus);
             } else {
                 // 学生记录
-                if (studentEventIdList.contains(eventId)) continue;
+                if (studentEventIdList.contains(eventId)){
+                    continue;
+                }
+                LocalDateTime recordTimeDate = LocalDateTime.parse(recordTimeStr, formatter);
+                String attendanceStatus = discernStudentStatus(use, recordTimeDate, status, personId);
                 studentInsertRecord(use, personId, faceImportMapper.GetTeacherIdByPersonId(personId),
-                        faceImportMapper.GetClassIdByPersonId(personId), ApiUtil.GetRedirectURL(uri), ChangeTime(recordTime), status,eventId);
+                        faceImportMapper.GetClassIdByPersonId(personId), ApiUtil.GetRedirectURL(uri), recordTimeStr, status,eventId, attendanceStatus);
+            }
+        }
+    }
+
+    String discernTeacherStatus(Db use, LocalDateTime recordTime, int status, Long userId) throws SQLException {
+        String attendanceStatus = "";
+        String dayOfWeek = recordTime.getDayOfWeek().name();
+        String sql = "SELECT t2.* FROM attendance_rule_category t1" +
+                " INNER JOIN attendance_rule_details t2 ON t1.id = t2.attendance_rule_category_id" +
+                " INNER JOIN attendance_user_relation t3 ON t1.id = t3.attendance_rule_category_id" +
+                " WHERE t1.delete_mark = 0 AND t2.delete_mark = 0 AND NOW() BETWEEN start_date AND end_date" +
+                " AND t2.date_type = '" + dayOfWeek + "' and t3.user_id = " + userId;
+        List<AttendanceRuleDetails> ruleDetailsList = use.query(sql, AttendanceRuleDetails.class);
+        if(!ruleDetailsList.isEmpty()){
+            AttendanceRuleDetails ruleDetails = ruleDetailsList.get(0);
+            if(ruleDetails.getIsAttendance() != null && ruleDetails.getIsAttendance() == 0){
+                attendanceStatus = "不考勤";
+            }else{
+                LocalDateTime amStartTime = null, amEndTime = null, pmStartTime = null, pmEndTime = null, eveningStartTime = null, eveningEndTime = null;
+                if(ruleDetails.getAmStatus() != null && ruleDetails.getAmStatus() == 1){
+                    amStartTime = recordTime.withHour(ruleDetails.getAmStartTime().getHour())
+                            .withMinute(ruleDetails.getAmStartTime().getMinute())
+                            .withSecond(ruleDetails.getAmStartTime().getSecond());
+                    amEndTime = recordTime.withHour(ruleDetails.getAmEndTime().getHour())
+                            .withMinute(ruleDetails.getAmEndTime().getMinute())
+                            .withSecond(ruleDetails.getAmEndTime().getSecond());
+                }
+                if(ruleDetails.getPmStatus() != null && ruleDetails.getPmStatus() == 1){
+                    pmStartTime = recordTime.withHour(ruleDetails.getPmStartTime().getHour())
+                            .withMinute(ruleDetails.getPmStartTime().getMinute())
+                            .withSecond(ruleDetails.getPmStartTime().getSecond());
+                    pmEndTime = recordTime.withHour(ruleDetails.getPmEndTime().getHour())
+                            .withMinute(ruleDetails.getPmEndTime().getMinute())
+                            .withSecond(ruleDetails.getPmEndTime().getSecond());
+                }
+                if(ruleDetails.getEveningStatus() != null && ruleDetails.getEveningStatus() == 1){
+                    eveningStartTime = recordTime.withHour(ruleDetails.getEveningStartTime().getHour())
+                            .withMinute(ruleDetails.getEveningStartTime().getMinute())
+                            .withSecond(ruleDetails.getEveningStartTime().getSecond());
+                    eveningEndTime = recordTime.withHour(ruleDetails.getEveningEndTime().getHour())
+                            .withMinute(ruleDetails.getEveningEndTime().getMinute())
+                            .withSecond(ruleDetails.getEveningEndTime().getSecond());
+                }
+                if(status == 1){//出
+                    if(recordTime.isBefore(amEndTime) && recordTime.isAfter(amStartTime)){
+                        attendanceStatus = "早退";
+                    }else if(recordTime.isBefore(pmEndTime) && recordTime.isAfter(pmStartTime)){
+                        attendanceStatus = "早退";
+                    }else if(recordTime.isBefore(eveningEndTime) && recordTime.isAfter(eveningStartTime)){
+                        attendanceStatus = "早退";
+                    }else{
+                        attendanceStatus = "离校";
+                    }
+                }else{//进
+                    if(recordTime.isBefore(amEndTime) && recordTime.isAfter(amStartTime)){
+                        attendanceStatus = "迟到";
+                    }else if(recordTime.isBefore(pmEndTime) && recordTime.isAfter(pmStartTime)){
+                        attendanceStatus = "迟到";
+                    }else if(recordTime.isBefore(eveningEndTime) && recordTime.isAfter(eveningStartTime)){
+                        attendanceStatus = "迟到";
+                    }else{
+                        attendanceStatus = "到校";
+                    }
+                }
+            }
+        }
+        return attendanceStatus;
+    }
+
+
+    String discernStudentStatus(Db use, LocalDateTime recordTime, int status, Long studentUserId) throws SQLException {
+        String attendanceStatus = "";
+        String dayOfWeek = recordTime.getDayOfWeek().name();
+        String sql = "SELECT t2.* FROM attendance_rule_category t1" +
+                " INNER JOIN attendance_rule_details t2 ON t1.id = t2.attendance_rule_category_id" +
+                " INNER JOIN attendance_user_relation t3 ON t1.id = t3.attendance_rule_category_id" +
+                " WHERE t1.delete_mark = 0 AND t2.delete_mark = 0 AND NOW() BETWEEN start_date AND end_date" +
+                " AND t2.date_type = '" + dayOfWeek + "' and t3.user_id = " + studentUserId;
+        List<AttendanceRuleDetails> ruleDetailsList = use.query(sql, AttendanceRuleDetails.class);
+        if(!ruleDetailsList.isEmpty()){
+            AttendanceRuleDetails ruleDetails = ruleDetailsList.get(0);
+            if(ruleDetails.getIsAttendance() != null && ruleDetails.getIsAttendance() == 0){
+                attendanceStatus = "不考勤";
+            }else{
+                LocalDateTime amStartTime = null, amEndTime = null, pmStartTime = null, pmEndTime = null, eveningStartTime = null, eveningEndTime = null;
+                if(ruleDetails.getAmStatus() != null && ruleDetails.getAmStatus() == 1){
+                    amStartTime = recordTime.withHour(ruleDetails.getAmStartTime().getHour())
+                            .withMinute(ruleDetails.getAmStartTime().getMinute())
+                            .withSecond(ruleDetails.getAmStartTime().getSecond());
+                    amEndTime = recordTime.withHour(ruleDetails.getAmEndTime().getHour())
+                            .withMinute(ruleDetails.getAmEndTime().getMinute())
+                            .withSecond(ruleDetails.getAmEndTime().getSecond());
+                }
+                if(ruleDetails.getPmStatus() != null && ruleDetails.getPmStatus() == 1){
+                    pmStartTime = recordTime.withHour(ruleDetails.getPmStartTime().getHour())
+                            .withMinute(ruleDetails.getPmStartTime().getMinute())
+                            .withSecond(ruleDetails.getPmStartTime().getSecond());
+                    pmEndTime = recordTime.withHour(ruleDetails.getPmEndTime().getHour())
+                            .withMinute(ruleDetails.getPmEndTime().getMinute())
+                            .withSecond(ruleDetails.getPmEndTime().getSecond());
+                }
+                if(ruleDetails.getEveningStatus() != null && ruleDetails.getEveningStatus() == 1){
+                    eveningStartTime = recordTime.withHour(ruleDetails.getEveningStartTime().getHour())
+                            .withMinute(ruleDetails.getEveningStartTime().getMinute())
+                            .withSecond(ruleDetails.getEveningStartTime().getSecond());
+                    eveningEndTime = recordTime.withHour(ruleDetails.getEveningEndTime().getHour())
+                            .withMinute(ruleDetails.getEveningEndTime().getMinute())
+                            .withSecond(ruleDetails.getEveningEndTime().getSecond());
+                }
+                if(status == 1){//出
+                    if(recordTime.isBefore(amEndTime) && recordTime.isAfter(amStartTime)){
+                        attendanceStatus = "早退";
+                    }else if(recordTime.isBefore(pmEndTime) && recordTime.isAfter(pmStartTime)){
+                        attendanceStatus = "早退";
+                    }else if(recordTime.isBefore(eveningEndTime) && recordTime.isAfter(eveningStartTime)){
+                        attendanceStatus = "早退";
+                    }else{
+                        attendanceStatus = "离校";
+                    }
+                }else{//进
+                    if(recordTime.isBefore(amEndTime) && recordTime.isAfter(amStartTime)){
+                        attendanceStatus = "迟到";
+                    }else if(recordTime.isBefore(pmEndTime) && recordTime.isAfter(pmStartTime)){
+                        attendanceStatus = "迟到";
+                    }else if(recordTime.isBefore(eveningEndTime) && recordTime.isAfter(eveningStartTime)){
+                        attendanceStatus = "迟到";
+                    }else{
+                        attendanceStatus = "到校";
+                    }
+                }
             }
         }
+        return attendanceStatus;
     }
 
     public void GetVisitRecord(Db use, FaceImportMapper faceImportMapper) throws SQLException, ParseException {