snihwxf 2 тижнів тому
батько
коміт
7fe1444b93

+ 10 - 4
src/main/java/com/xjrsoft/module/attendance/controller/AttendanceRuleCategoryController.java

@@ -13,10 +13,7 @@ import com.xjrsoft.common.model.result.RT;
 import com.xjrsoft.common.page.ConventPage;
 import com.xjrsoft.common.page.PageOutput;
 import com.xjrsoft.common.utils.VoToColumnUtil;
-import com.xjrsoft.module.attendance.dto.AddAttendanceRuleCategoryDto;
-import com.xjrsoft.module.attendance.dto.AddAttendanceUserRelationDto;
-import com.xjrsoft.module.attendance.dto.AttendanceRuleCategoryPageDto;
-import com.xjrsoft.module.attendance.dto.UpdateAttendanceRuleCategoryDto;
+import com.xjrsoft.module.attendance.dto.*;
 import com.xjrsoft.module.attendance.entity.AttendanceRuleCategory;
 import com.xjrsoft.module.attendance.service.IAttendanceRuleCategoryService;
 import com.xjrsoft.module.attendance.vo.AttendanceRuleCategoryPageVo;
@@ -143,6 +140,15 @@ public class AttendanceRuleCategoryController {
         return RT.ok(attendanceRuleCategoryService.update(dto));
     }
 
+    @PostMapping(value = "/copy")
+    @ApiOperation(value = "复制考勤规则")
+//    @SaCheckPermission("attendancerulecategory:copy")
+    @XjrLog(value = "复制考勤规则", saveResponseData = true)
+    public RT<Boolean> copy(@Valid @RequestBody CopyAttendanceRuleCategoryDto dto) {
+        boolean isSuccess = attendanceRuleCategoryService.copy(dto);
+        return RT.ok(isSuccess);
+    }
+
     @DeleteMapping
     @ApiOperation(value = "删除考勤规则")
     @SaCheckPermission("attendancerulecategory:delete")

+ 35 - 0
src/main/java/com/xjrsoft/module/attendance/dto/CopyAttendanceRuleCategoryDto.java

@@ -0,0 +1,35 @@
+package com.xjrsoft.module.attendance.dto;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDate;
+
+@Data
+public class CopyAttendanceRuleCategoryDto implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 复制的ID
+     */
+    @ApiModelProperty("复制的ID")
+    private Long id;
+    /**
+     * 考勤规则名称
+     */
+    @ApiModelProperty("考勤规则名称")
+    private String name;
+    /**
+     * 考勤开始时间
+     */
+    @ApiModelProperty("考勤开始时间")
+    private LocalDate startDate;
+    /**
+     * 考勤结束时间
+     */
+    @ApiModelProperty("考勤结束时间")
+    private LocalDate endDate;
+
+}

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

@@ -65,6 +65,11 @@ public class StudentAttendanceStatistics implements Serializable {
      */
     @ApiModelProperty("学生userId(xjr_user)")
     private Long userId;
+    /**
+     * 班级ID(base_class)
+     */
+    @ApiModelProperty("班级ID(base_class)")
+    private Long classId;
     /**
      * 考勤状态(xjr_dictionary_detail[attendance_status])
      */

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/service/IAttendanceRuleCategoryService.java

@@ -2,6 +2,7 @@ package com.xjrsoft.module.attendance.service;
 
 import com.github.yulichang.base.MPJBaseService;
 import com.xjrsoft.module.attendance.dto.AddAttendanceRuleCategoryDto;
+import com.xjrsoft.module.attendance.dto.CopyAttendanceRuleCategoryDto;
 import com.xjrsoft.module.attendance.dto.UpdateAttendanceRuleCategoryDto;
 import com.xjrsoft.module.attendance.entity.AttendanceRuleCategory;
 import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails;
@@ -36,6 +37,8 @@ public interface IAttendanceRuleCategoryService extends MPJBaseService<Attendanc
      */
     Boolean update(UpdateAttendanceRuleCategoryDto dto);
 
+    Boolean copy(CopyAttendanceRuleCategoryDto dto);
+
     /**
      * 删除
      *

+ 390 - 3
src/main/java/com/xjrsoft/module/attendance/service/impl/AttendanceRuleCategoryServiceImpl.java

@@ -2,16 +2,17 @@ package com.xjrsoft.module.attendance.service.impl;
 
 import cn.dev33.satoken.stp.StpUtil;
 import cn.hutool.core.bean.BeanUtil;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.github.yulichang.base.MPJBaseServiceImpl;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
+import com.google.gson.JsonParser;
 import com.xjrsoft.common.enums.DeleteMark;
+import com.xjrsoft.common.enums.EnabledMark;
 import com.xjrsoft.common.exception.MyException;
 import com.xjrsoft.common.utils.VoToColumnUtil;
-import com.xjrsoft.module.attendance.dto.AddAttendanceRuleCategoryDto;
-import com.xjrsoft.module.attendance.dto.AddAttendanceUserRelationDto;
-import com.xjrsoft.module.attendance.dto.UpdateAttendanceRuleCategoryDto;
+import com.xjrsoft.module.attendance.dto.*;
 import com.xjrsoft.module.attendance.entity.AttendanceRuleCategory;
 import com.xjrsoft.module.attendance.entity.AttendanceRuleDetails;
 import com.xjrsoft.module.attendance.entity.AttendanceUserRelation;
@@ -21,6 +22,8 @@ import com.xjrsoft.module.attendance.mapper.AttendanceUserRelationMapper;
 import com.xjrsoft.module.attendance.service.IAttendanceRuleCategoryService;
 import com.xjrsoft.module.attendance.vo.AttendanceRuleDetailsUserVo;
 import com.xjrsoft.module.attendance.vo.TimeRangeVo;
+import com.xjrsoft.module.base.entity.BaseClass;
+import com.xjrsoft.module.base.service.IBaseClassService;
 import com.xjrsoft.module.concat.service.IXjrUserService;
 import com.xjrsoft.module.organization.entity.UserDeptRelation;
 import com.xjrsoft.module.student.entity.BaseStudent;
@@ -52,6 +55,7 @@ public class AttendanceRuleCategoryServiceImpl extends MPJBaseServiceImpl<Attend
     private final AttendanceRuleDetailsMapper detailsMapper;
     private final AttendanceUserRelationMapper relationMapper;
     private final IXjrUserService xjrUserService;
+    private  final IBaseClassService baseClassService;
 
 
     @Override
@@ -67,6 +71,160 @@ public class AttendanceRuleCategoryServiceImpl extends MPJBaseServiceImpl<Attend
         AttendanceRuleCategory attendanceRuleCategory = BeanUtil.toBean(dto, AttendanceRuleCategory.class);
         attendanceRuleCategory.setUserRelation(JsonUtil.toJsonString(dto.getAttendanceUserRelationList()));
 
+        List<XjrUser> insertList = new ArrayList<>();
+        List<Long> classIds=new ArrayList<>();
+        if (attendanceRuleCategory.getRoleId() != null && attendanceRuleCategory.getRoleId() == 2) {
+            if (attendanceRuleCategory.getAttendanceRange() == 1) {
+                //首先判断是否已经存在一个全体教职工的考勤规则
+                Integer existCount = categoryMapper.getExistCount(dto);
+                if (existCount > 0) {
+                    throw new MyException("已存在一个全体教职工的考勤规则,无法添加");
+                }
+                List<XjrUser> userList = xjrUserService.list(
+                        new MPJLambdaWrapper<XjrUser>()
+                                .select(XjrUser::getId)
+                                .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
+                                .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId)
+                                .eq(BaseTeacher::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                .eq(XjrUser::getDeleteMark, DeleteMark.NODELETE.getCode())
+                );
+                insertList.addAll(userList);
+            } else if (attendanceRuleCategory.getAttendanceRange() == 2) {
+                List<Long> deptIds = new ArrayList<>();
+                for (AddAttendanceUserRelationDto relation : dto.getAttendanceUserRelationList()) {
+                    if (relation.getDeptId() != null) {
+                        deptIds.add(relation.getDeptId());
+                    }
+                }
+                List<Long> userIds = new ArrayList<>();
+                for (AddAttendanceUserRelationDto relation : dto.getAttendanceUserRelationList()) {
+                    if (relation.getUserId() != null) {
+                        userIds.add(relation.getUserId());
+                    }
+                }
+
+                List<XjrUser> userList = xjrUserService.list(
+                        new MPJLambdaWrapper<XjrUser>()
+                                .select(XjrUser::getId)
+                                .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
+                                .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId)
+                                .leftJoin(UserDeptRelation.class, UserDeptRelation::getUserId, XjrUser::getId)
+                                .eq(BaseTeacher::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                .eq(XjrUser::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                .in(!deptIds.isEmpty(), UserDeptRelation::getDeptId, deptIds)
+                                .in(!userIds.isEmpty(), XjrUser::getId, userIds)
+                );
+                //查询这部分人中是否已经有人有规则了
+                List<Long> relationUserIds = userList.stream().map(XjrUser::getId).collect(Collectors.toList());
+                List<XjrUser> relations = xjrUserService.list(
+                        new MPJLambdaWrapper<XjrUser>().distinct()
+                                .select(XjrUser::getId)
+                                .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
+                                .leftJoin(AttendanceUserRelation.class, AttendanceUserRelation::getUserId, XjrUser::getId)
+                                .leftJoin(AttendanceRuleCategory.class, AttendanceRuleCategory::getId, AttendanceUserRelation::getAttendanceRuleCategoryId)
+                                .eq(AttendanceUserRelation::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                .eq(AttendanceUserRelation::getEnabledMark, EnabledMark.ENABLED.getCode())
+                                .in(!relationUserIds.isEmpty(), AttendanceUserRelation::getUserId, relationUserIds)
+                                .apply("(( '"+dto.getStartDate()+"' BETWEEN t2.start_date AND t2.end_date) OR ( '"+dto.getEndDate()+"' BETWEEN t2.start_date AND t2.end_date))")
+                );
+                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 + "】已绑定其他考勤规则,无法添加");
+                }
+                insertList.addAll(userList);
+            }
+        } else if (attendanceRuleCategory.getRoleId() != null && attendanceRuleCategory.getRoleId() == 3) {//学生 学生存班级ID
+            if (attendanceRuleCategory.getAttendanceRange() == 1) {
+                //首先判断是否已经存在一个全体学生的考勤规则
+                Integer existCount = categoryMapper.getExistCount(dto);
+                if (existCount > 0) {
+                    throw new MyException("已存在一个全体学生的考勤规则,无法添加");
+                }
+
+                List<BaseClass> classList = baseClassService.list(
+                        new MPJLambdaWrapper<BaseClass>()
+                                .select(BaseClass::getId)
+                                .eq(BaseClass::getDeleteMark,DeleteMark.NODELETE.getCode())
+                                .eq(BaseClass::getIsGraduate,1)
+                );
+
+                classIds=classList.stream().map(BaseClass::getId).collect(Collectors.toList());
+
+            } else if (attendanceRuleCategory.getAttendanceRange() == 2) {
+                for (AddAttendanceUserRelationDto relation : dto.getAttendanceUserRelationList()) {
+                    if (relation.getClassId() != null) {
+                        classIds.add(relation.getClassId());
+                    }
+                }
+                List<BaseClass> relations = baseClassService.list(
+                        new MPJLambdaWrapper<BaseClass>().distinct()
+                                .select(BaseClass::getId)
+                                .select(BaseClass.class, x -> VoToColumnUtil.fieldsToColumns(BaseClass.class).contains(x.getProperty()))
+                                .leftJoin(AttendanceUserRelation.class, AttendanceUserRelation::getClassId, XjrUser::getId)
+                                .leftJoin(AttendanceRuleCategory.class, AttendanceRuleCategory::getId, AttendanceUserRelation::getAttendanceRuleCategoryId)
+                                .eq(AttendanceUserRelation::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                .eq(AttendanceUserRelation::getEnabledMark, EnabledMark.ENABLED.getCode())
+                                .eq(AttendanceRuleCategory::getStduyStatus, dto.getStduyStatus())
+                                .in(!classIds.isEmpty(), AttendanceUserRelation::getClassId, classIds)
+                                .apply("(( '"+dto.getStartDate()+"' BETWEEN t2.start_date AND t2.end_date) OR ( '"+dto.getEndDate()+"' BETWEEN t2.start_date AND t2.end_date))")
+                );
+                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 + "】已绑定其他考勤规则,无法修改");
+                }
+            }
+        }
+        attendanceRuleCategory.setCreateDate(new Date());
+        categoryMapper.insert(attendanceRuleCategory);
+        for (AttendanceRuleDetails attendanceRuleDetails : attendanceRuleCategory.getAttendanceRuleDetailsList()) {
+            attendanceRuleDetails.setAttendanceRuleCategoryId(attendanceRuleCategory.getId());
+            detailsMapper.insert(attendanceRuleDetails);
+        }
+        for (XjrUser user : insertList) {
+            AttendanceUserRelation relation = new AttendanceUserRelation();
+            relation.setCreateDate(new Date());
+            relation.setCreateUserId(StpUtil.getLoginIdAsLong());
+            relation.setUserId(user.getId());
+            relation.setAttendanceRuleCategoryId(attendanceRuleCategory.getId());
+            relationMapper.insert(relation);
+        }
+
+
+        for (Long classId : classIds) {
+            AttendanceUserRelation relation = new AttendanceUserRelation();
+            relation.setCreateDate(new Date());
+            relation.setCreateUserId(StpUtil.getLoginIdAsLong());
+            relation.setClassId(classId);
+            relation.setAttendanceRuleCategoryId(attendanceRuleCategory.getId());
+            relationMapper.insert(relation);
+        }
+
+        return true;
+    }
+
+    public Boolean addOld(AddAttendanceRuleCategoryDto dto) {
+        List<AttendanceRuleCategory> defaultShowRuleCategories = this.list(
+                new QueryWrapper<AttendanceRuleCategory>().lambda()
+                        .eq(AttendanceRuleCategory::getIsDefaultShow, 1)
+        );
+        if(!defaultShowRuleCategories.isEmpty() && dto.getIsDefaultShow() != null && dto.getIsDefaultShow() == 1){
+            throw new MyException("已存在一个默认显示的规则,无法再次添加");
+        }
+        AttendanceRuleCategory attendanceRuleCategory = BeanUtil.toBean(dto, AttendanceRuleCategory.class);
+        attendanceRuleCategory.setUserRelation(JsonUtil.toJsonString(dto.getAttendanceUserRelationList()));
+
         List<XjrUser> insertList = new ArrayList<>();
         if (attendanceRuleCategory.getRoleId() != null && attendanceRuleCategory.getRoleId() == 2) {
             if (attendanceRuleCategory.getAttendanceRange() == 1) {
@@ -237,6 +395,219 @@ public class AttendanceRuleCategoryServiceImpl extends MPJBaseServiceImpl<Attend
             }
         }
 
+        categoryMapper.updateById(attendanceRuleCategory);
+        //********************************* AttendanceRuleDetails  增删改  开始 *******************************************/
+        {
+            // 查出所有子级的id
+            List<AttendanceRuleDetails> attendanceRuleDetailsList = detailsMapper.selectList(Wrappers.lambdaQuery(AttendanceRuleDetails.class).eq(AttendanceRuleDetails::getAttendanceRuleCategoryId, attendanceRuleCategory.getId()).select(AttendanceRuleDetails::getId));
+            List<Long> attendanceRuleDetailsIds = attendanceRuleDetailsList.stream().map(AttendanceRuleDetails::getId).collect(Collectors.toList());
+            //原有子表单 没有被删除的主键
+            List<Long> attendanceRuleDetailsOldIds = attendanceRuleCategory.getAttendanceRuleDetailsList().stream().map(AttendanceRuleDetails::getId).filter(Objects::nonNull).collect(Collectors.toList());
+            //找到需要删除的id
+            List<Long> attendanceRuleDetailsRemoveIds = attendanceRuleDetailsIds.stream().filter(item -> !attendanceRuleDetailsOldIds.contains(item)).collect(Collectors.toList());
+
+            for (AttendanceRuleDetails attendanceRuleDetails : attendanceRuleCategory.getAttendanceRuleDetailsList()) {
+                //如果不等于空则修改
+                if (attendanceRuleDetails.getId() != null) {
+                    detailsMapper.updateById(attendanceRuleDetails);
+                }
+                //如果等于空 则新增
+                else {
+                    //已经不存在的id 删除
+                    attendanceRuleDetails.setAttendanceRuleCategoryId(attendanceRuleCategory.getId());
+                    detailsMapper.insert(attendanceRuleDetails);
+                }
+            }
+            //已经不存在的id 删除
+            if (!attendanceRuleDetailsRemoveIds.isEmpty()) {
+                detailsMapper.deleteBatchIds(attendanceRuleDetailsRemoveIds);
+            }
+        }
+        //********************************* AttendanceRuleDetails  增删改  结束 *******************************************/
+
+        //********************************* AttendanceUserRelation  增删改  开始 *******************************************/
+        List<XjrUser> insertList = new ArrayList<>();
+        List<Long> classIds=new ArrayList<>();
+        if (attendanceRuleCategory.getRoleId() != null && attendanceRuleCategory.getRoleId() == 2) {
+            if (attendanceRuleCategory.getAttendanceRange() == 1) {
+                List<XjrUser> userList = xjrUserService.list(
+                        new MPJLambdaWrapper<XjrUser>()
+                                .select(XjrUser::getId)
+                                .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
+                                .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId)
+                                .eq(BaseTeacher::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                .eq(XjrUser::getDeleteMark, DeleteMark.NODELETE.getCode())
+                );
+                insertList.addAll(userList);
+            } else if (attendanceRuleCategory.getAttendanceRange() == 2) {
+                List<Long> deptIds = new ArrayList<>();
+                for (AddAttendanceUserRelationDto relation : dto.getAttendanceUserRelationList()) {
+                    if (relation.getDeptId() != null) {
+                        deptIds.add(relation.getDeptId());
+                    }
+                }
+                List<Long> userIds = new ArrayList<>();
+                for (AddAttendanceUserRelationDto relation : dto.getAttendanceUserRelationList()) {
+                    if (relation.getUserId() != null) {
+                        userIds.add(relation.getUserId());
+                    }
+                }
+                List<XjrUser> userList = new ArrayList<>();
+                if (!deptIds.isEmpty()) {
+                    List<XjrUser> deptUserList = xjrUserService.list(
+                            new MPJLambdaWrapper<XjrUser>()
+                                    .select(XjrUser::getId)
+                                    .select(XjrUser.class, x -> VoToColumnUtil.fieldsToColumns(XjrUser.class).contains(x.getProperty()))
+                                    .leftJoin(BaseTeacher.class, BaseTeacher::getUserId, XjrUser::getId)
+                                    .leftJoin(UserDeptRelation.class, UserDeptRelation::getUserId, XjrUser::getId)
+                                    .eq(BaseTeacher::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                    .eq(XjrUser::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                    .in(UserDeptRelation::getDeptId, deptIds)
+                    );
+                    userList.addAll(deptUserList);
+                }
+                if (!userIds.isEmpty()) {
+                    userList.addAll(xjrUserService.listByIds(userIds));
+                }
+
+
+                //查询这部分人中是否已经有人有规则了
+                List<Long> relationUserIds = userList.stream().map(XjrUser::getId).collect(Collectors.toList());
+                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)
+                                    .leftJoin(AttendanceRuleCategory.class, AttendanceRuleCategory::getId, AttendanceUserRelation::getAttendanceRuleCategoryId)
+                                    .eq(AttendanceUserRelation::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                    .eq(AttendanceUserRelation::getEnabledMark, EnabledMark.ENABLED.getCode())
+                                    .eq(AttendanceRuleCategory::getStduyStatus, dto.getStduyStatus())
+                                    .in(AttendanceUserRelation::getUserId, relationUserIds)
+                                    .ne(AttendanceUserRelation::getAttendanceRuleCategoryId, attendanceRuleCategory.getId())
+                                    .apply("(( '"+dto.getStartDate()+"' BETWEEN t2.start_date AND t2.end_date) OR ( '"+dto.getEndDate()+"' BETWEEN t2.start_date AND t2.end_date))")
+                    );
+                    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 + "】已绑定其他考勤规则,无法添加");
+                    }
+                }
+
+                insertList.addAll(userList);
+            }
+        } else if (attendanceRuleCategory.getRoleId() != null && attendanceRuleCategory.getRoleId() == 3) {//学生
+            if (attendanceRuleCategory.getAttendanceRange() == 1) {
+                //首先判断是否已经存在一个全体学生的考勤规则
+                Long count = categoryMapper.selectCount(
+                        new QueryWrapper<AttendanceRuleCategory>()
+                                .lambda()
+                                .eq(AttendanceRuleCategory::getRoleId, attendanceRuleCategory.getRoleId())
+                                .eq(AttendanceRuleCategory::getAttendanceRange, attendanceRuleCategory.getAttendanceRange())
+                                .eq(AttendanceRuleCategory::getDeleteMark, DeleteMark.NODELETE.getCode())
+                );
+                if (count > 0) {
+                    throw new MyException("已存在一个全体学生的考勤规则,无法修改");
+                }
+                List<BaseClass> classList = baseClassService.list(
+                        new MPJLambdaWrapper<BaseClass>()
+                                .select(BaseClass::getId)
+                                .eq(BaseClass::getDeleteMark,DeleteMark.NODELETE.getCode())
+                                .eq(BaseClass::getIsGraduate,1)
+                );
+
+                classIds=classList.stream().map(BaseClass::getId).collect(Collectors.toList());
+
+            } else if (attendanceRuleCategory.getAttendanceRange() == 2) {
+                for (AddAttendanceUserRelationDto relation : dto.getAttendanceUserRelationList()) {
+                    if (relation.getClassId() != null) {
+                        classIds.add(relation.getClassId());
+                    }
+                }
+
+                if (!classIds.isEmpty()) {
+
+                    List<BaseClass> relations = baseClassService.list(
+                            new MPJLambdaWrapper<BaseClass>().distinct()
+                                    .select(BaseClass::getId)
+                                    .select(BaseClass.class, x -> VoToColumnUtil.fieldsToColumns(BaseClass.class).contains(x.getProperty()))
+                                    .leftJoin(AttendanceUserRelation.class, AttendanceUserRelation::getClassId, XjrUser::getId)
+                                    .leftJoin(AttendanceRuleCategory.class, AttendanceRuleCategory::getId, AttendanceUserRelation::getAttendanceRuleCategoryId)
+                                    .eq(AttendanceUserRelation::getDeleteMark, DeleteMark.NODELETE.getCode())
+                                    .eq(AttendanceUserRelation::getEnabledMark, EnabledMark.ENABLED.getCode())
+                                    .eq(AttendanceRuleCategory::getStduyStatus, dto.getStduyStatus())
+                                    .in( AttendanceUserRelation::getClassId, classIds)
+                                    .ne(AttendanceUserRelation::getAttendanceRuleCategoryId, attendanceRuleCategory.getId())
+                                    .apply("(( '"+dto.getStartDate()+"' BETWEEN t2.start_date AND t2.end_date) OR ( '"+dto.getEndDate()+"' BETWEEN t2.start_date AND t2.end_date))")
+                    );
+
+                    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 + "】已绑定其他考勤规则,无法修改");
+                    }
+                }
+            }
+        }
+        //先清空原来的全体教职工数据,再重新添加
+        relationMapper.delete(
+                Wrappers.lambdaQuery(AttendanceUserRelation.class)
+                        .eq(AttendanceUserRelation::getAttendanceRuleCategoryId, attendanceRuleCategory.getId())
+        );
+        for (XjrUser user : insertList) {
+            AttendanceUserRelation relation = new AttendanceUserRelation();
+            relation.setCreateDate(new Date());
+            relation.setCreateUserId(StpUtil.getLoginIdAsLong());
+            relation.setUserId(user.getId());
+            relation.setAttendanceRuleCategoryId(attendanceRuleCategory.getId());
+            relationMapper.insert(relation);
+        }
+
+        for (Long classId : classIds) {
+            AttendanceUserRelation relation = new AttendanceUserRelation();
+            relation.setCreateDate(new Date());
+            relation.setCreateUserId(StpUtil.getLoginIdAsLong());
+            relation.setClassId(classId);
+            relation.setAttendanceRuleCategoryId(attendanceRuleCategory.getId());
+            relationMapper.insert(relation);
+        }
+        //********************************* AttendanceUserRelation  增删改  结束 *******************************************/
+
+        return true;
+    }
+
+    public Boolean updateOld(UpdateAttendanceRuleCategoryDto dto) {
+        List<AttendanceRuleCategory> defaultShowRuleCategories = this.list(
+                new QueryWrapper<AttendanceRuleCategory>().lambda()
+                        .eq(AttendanceRuleCategory::getIsDefaultShow, 1)
+                        .ne(AttendanceRuleCategory::getId, dto.getId())
+        );
+        if(!defaultShowRuleCategories.isEmpty() && dto.getIsDefaultShow() != null && dto.getIsDefaultShow() == 1){
+            throw new MyException("已存在一个默认显示的规则,无法再次添加");
+        }
+        AttendanceRuleCategory attendanceRuleCategory = BeanUtil.toBean(dto, AttendanceRuleCategory.class);
+        attendanceRuleCategory.setUserRelation(JsonUtil.toJsonString(dto.getAttendanceUserRelationList()));
+        if (attendanceRuleCategory.getAttendanceRange() == 1) {
+            Integer count = categoryMapper.getExistCountNEId(dto);
+            if (count > 0) {
+                if (attendanceRuleCategory.getRoleId() == 2) {
+                    throw new MyException("已存在一个全体教职工的考勤规则,无法修改");
+                } else if (attendanceRuleCategory.getRoleId() == 3) {
+                    throw new MyException("已存在一个全体学生的考勤规则,无法修改");
+                }
+            }
+        }
+
         categoryMapper.updateById(attendanceRuleCategory);
         //********************************* AttendanceRuleDetails  增删改  开始 *******************************************/
         {
@@ -429,6 +800,22 @@ public class AttendanceRuleCategoryServiceImpl extends MPJBaseServiceImpl<Attend
         return true;
     }
 
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public  Boolean copy(CopyAttendanceRuleCategoryDto dto) {
+        AttendanceRuleCategory attendanceRuleCategory = this.getByIdDeep(dto.getId());
+
+        AddAttendanceRuleCategoryDto addAttendanceRuleCategoryDto = BeanUtil.toBean(attendanceRuleCategory, AddAttendanceRuleCategoryDto.class);
+        addAttendanceRuleCategoryDto.setName(dto.getName());
+        addAttendanceRuleCategoryDto.setStartDate(dto.getStartDate());
+        addAttendanceRuleCategoryDto.setEndDate(dto.getEndDate());
+
+        addAttendanceRuleCategoryDto.setAttendanceRuleDetailsList(BeanUtil.copyToList(attendanceRuleCategory.getAttendanceRuleDetailsList(), AddAttendanceRuleDetailsDto.class));
+        addAttendanceRuleCategoryDto.setAttendanceUserRelationList(JSONObject.parseArray(attendanceRuleCategory.getUserRelation(), AddAttendanceUserRelationDto.class));
+
+        return add(addAttendanceRuleCategoryDto);
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public Boolean delete(List<Long> ids) {

+ 105 - 3
src/main/java/com/xjrsoft/module/attendance/service/impl/StudentStatisticsServiceImpl.java

@@ -1,5 +1,6 @@
 package com.xjrsoft.module.attendance.service.impl;
 
+import camundajar.impl.scala.Int;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.github.yulichang.base.MPJBaseServiceImpl;
@@ -43,6 +44,7 @@ import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.stream.Collectors;
 
 @Service
 @AllArgsConstructor
@@ -69,6 +71,7 @@ public class StudentStatisticsServiceImpl  extends MPJBaseServiceImpl<StudentAtt
 
                     .selectAs(User::getId, StudentStatisticsPageVo::getUserId)
                     .selectAs(DictionaryDetail::getName, StudentStatisticsPageVo::getStduyStatusCn)
+                    .selectAs(BaseClass::getId, StudentStatisticsPageVo::getClassId)
 
                     .innerJoin(BaseStudentSchoolRoll.class, BaseStudentSchoolRoll::getUserId, User::getId)
                     .innerJoin(BaseClass.class, BaseClass::getId, BaseStudentSchoolRoll::getClassId)
@@ -126,6 +129,7 @@ public class StudentStatisticsServiceImpl  extends MPJBaseServiceImpl<StudentAtt
                 studentAttendanceStatistics.setUserId(record.getUserId());
                 studentAttendanceStatistics.setAttendanceDate(queryDate);
                 studentAttendanceStatistics.setTimeInterval(timePeriod);
+                studentAttendanceStatistics.setClassId(record.getClassId());
 
                 if (studentLeave != null) {
                     studentAttendanceStatistics.setAttendanceStatus(studentLeave.getLeaveType());
@@ -137,9 +141,9 @@ public class StudentStatisticsServiceImpl  extends MPJBaseServiceImpl<StudentAtt
                     } else {
                         studentAttendanceStatistics.setAttendanceStatus("缺勤");
                     }
-                }
-                if (StudyStatusEnum.InResidence.getValue().equals(record.getStduyStatusCn())) {
-                    studentAttendanceStatistics.setAttendanceStatus("不考勤");
+                    if (StudyStatusEnum.InResidence.getValue().equals(record.getStduyStatusCn())) {
+                        studentAttendanceStatistics.setAttendanceStatus("不考勤");
+                    }
                 }
 
                 studentAttendanceStatisticsList.add(studentAttendanceStatistics);
@@ -164,6 +168,104 @@ public class StudentStatisticsServiceImpl  extends MPJBaseServiceImpl<StudentAtt
         AttendanceStatisticDto dto = new AttendanceStatisticDto();
         dto.setDate(date);
         dto.setTimePeriod(timePeriod);
+//        dto.setClassId(567891198765111L);
+
+        List<ClassStatisticsVo> attendanceList = classService.getAttendanceList(dto);
+
+
+        if (dto.getDate() != null && !dto.getDate().isEmpty()) {
+            DateTimeFormatter formatter = DateTimeFormatter.ISO_DATE;
+            LocalDate queryDate = LocalDate.parse(dto.getDate(), formatter);
+
+            HolidayDate holidayDate = holidayDateService.getOne(
+                    new QueryWrapper<HolidayDate>().lambda()
+                            .eq(HolidayDate::getDate, queryDate)
+            );
+            if (holidayDate != null && holidayDate.getWay() != null && holidayDate.getWay() != 0) {
+                return;
+            }
+
+            List<StudentAttendanceStatistics> studentAttendanceStatisticsList = this.list(new QueryWrapper<StudentAttendanceStatistics>().lambda()
+
+//                    .eq(StudentAttendanceStatistics::getClassId, 567891198765111L)
+                    .eq(StudentAttendanceStatistics::getAttendanceDate, date)
+                    .eq(StudentAttendanceStatistics::getTimeInterval, timePeriod));
+
+            List<ClassAttendanceStatistics> classAttendanceStatisticsList = new ArrayList<>();
+
+            for (ClassStatisticsVo record : attendanceList) {
+
+                ClassAttendanceStatistics classAttendanceStatistics = new ClassAttendanceStatistics();
+
+                classAttendanceStatistics.setClassId(record.getId());
+                classAttendanceStatistics.setStudentCount(record.getStudentCount());
+                classAttendanceStatistics.setStayCount(record.getStayCount());
+                classAttendanceStatistics.setNotStayCount(record.getNotStayCount());
+                classAttendanceStatistics.setTimeInterval(timePeriod);
+                classAttendanceStatistics.setAttendanceDate(queryDate);
+
+                List<StudentAttendanceStatistics> studentAttendanceStatisticsFilter = studentAttendanceStatisticsList.stream().filter(row -> Objects.equals(row.getClassId(), record.getId())).collect(Collectors.toList());
+
+                Map<String, Integer> countByStatus = studentAttendanceStatisticsFilter.stream()
+                        .collect(Collectors.groupingBy(
+                                StudentAttendanceStatistics::getAttendanceStatus,
+                                Collectors.summingInt(e -> 1)
+                        ));
+                int leaveCount = 0,// 请假人数
+                        lateCount = 0,//迟到人数
+                        playTruantCount = 0,//旷课人数
+                        actualCount = 0,//   实到人数
+                        absenteeismCount = 0 //缺勤人数
+                                ;
+                for (Map.Entry<String, Integer> entry : countByStatus.entrySet()) {
+                    String status = entry.getKey();
+                    switch (status) {
+                        case "事假":
+                        case "病假":
+                            leaveCount += entry.getValue();
+                            break;
+                        case "迟到":
+                            lateCount += entry.getValue();
+                            break;
+                        case "旷课":
+                            playTruantCount += entry.getValue();
+                            break;
+                        case "缺勤":
+                            absenteeismCount += entry.getValue();
+                            break;
+                        default:
+                            actualCount += entry.getValue();
+                            break;
+                    }
+                }
+                classAttendanceStatistics.setLeaveCount(leaveCount);
+                classAttendanceStatistics.setLateCount(lateCount);
+                classAttendanceStatistics.setPlayTruantCount(playTruantCount);
+                classAttendanceStatistics.setActualCount(actualCount);
+                classAttendanceStatistics.setAbsenteeismCount(absenteeismCount);
+
+                //计算出勤率
+                BigDecimal divide = BigDecimal.ZERO;
+                if (classAttendanceStatistics.getStudentCount() != null && classAttendanceStatistics.getStudentCount() != 0) {
+                    divide = BigDecimal.valueOf(classAttendanceStatistics.getActualCount()).divide(BigDecimal.valueOf(classAttendanceStatistics.getStudentCount()), 4, RoundingMode.HALF_UP);
+                }
+                classAttendanceStatistics.setAttendanceRate(divide.doubleValue() + "");
+
+                classAttendanceStatisticsList.add(classAttendanceStatistics);
+            }
+
+            classStatisticsService.delete(date, timePeriod);
+            if (!classAttendanceStatisticsList.isEmpty()) {
+                classStatisticsService.add(classAttendanceStatisticsList);
+            }
+        }
+    }
+
+    public void  classStatisticsOld(String date,Integer timePeriod) {
+
+        AttendanceStatisticDto dto = new AttendanceStatisticDto();
+        dto.setDate(date);
+        dto.setTimePeriod(timePeriod);
 
         List<ClassStatisticsVo> attendanceList = classService.getAttendanceList(dto);
         List<Long> classIds = new ArrayList<>();

+ 3 - 0
src/main/java/com/xjrsoft/module/attendance/vo/StudentStatisticsPageVo.java

@@ -17,6 +17,9 @@ public class StudentStatisticsPageVo {
     @ApiModelProperty("班级名称")
     private String className;
 
+    @ApiModelProperty("班级ID")
+    private Long classId;
+
     @ApiModelProperty("班主任名称")
     private String teacherName;
 

+ 5 - 1
src/main/java/com/xjrsoft/module/hikvision/util/OutInRecordUtil.java

@@ -299,8 +299,10 @@ public class OutInRecordUtil {
         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" +
+                " INNER JOIN base_student_school_roll t4 ON t3.class_id = t4.class_id AND t1.stduy_status=t4.stduy_status" +
                 " 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;
+                " AND t4.delete_mark = 0 " +
+                " AND t2.date_type = '" + dayOfWeek + "' and t4.user_id = " + studentUserId;
         List<Map<String, Object>> ruleDetailsList = SqlRunnerAdapter.db().selectList(sql, AttendanceRuleDetails.class);
         if (!ruleDetailsList.isEmpty()) {
             AttendanceRuleDetails ruleDetails = SqlRunnerAdapterUtil.convertMapToEntity(ruleDetailsList.get(0), AttendanceRuleDetails.class);
@@ -379,6 +381,8 @@ public class OutInRecordUtil {
                     }
                 }
             }
+        }else{
+            attendanceStatus = "无规则";
         }
         return attendanceStatus;
     }

+ 1 - 0
src/main/resources/sqlScript/20251111_sql.sql

@@ -9,6 +9,7 @@ CREATE TABLE `student_attendance_statistics` (
   `modify_user_id` BIGINT DEFAULT NULL COMMENT '修改人id',
   `modify_date` DATETIME(3) DEFAULT NULL COMMENT '修改日期',
   `user_id` BIGINT DEFAULT NULL COMMENT '学生userId(xjr_user)',
+  `class_id` BIGINT DEFAULT NULL COMMENT '班级ID(base_class)',
   `attendance_status` VARCHAR(50) DEFAULT NULL COMMENT '考勤状态(xjr_dictionary_detail[attendance_status])',
   `time_interval` INT DEFAULT NULL COMMENT '时段(1:上午,2:下午,3:晚上)',
   `record_time` DATETIME NULL COMMENT '考勤时间',