LIVE_YE 1 hafta önce
ebeveyn
işleme
a8de66650d
20 değiştirilmiş dosya ile 876 ekleme ve 152 silme
  1. 7 2
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/index/IndexController.java
  2. 109 22
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/kaoqin/KaoQinController.java
  3. 7 4
      ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java
  4. 1 1
      ruoyi-admin/src/main/resources/application-prod.yml
  5. 1 0
      ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java
  6. 155 5
      ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java
  7. 9 2
      ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java
  8. 8 1
      ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java
  9. 1 1
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/CardReplacementRecordMapper.java
  10. 1 1
      ruoyi-system/src/main/java/com/ruoyi/system/mapper/RecordLeaveMapper.java
  11. 18 0
      ruoyi-system/src/main/java/com/ruoyi/system/service/Task.java
  12. 189 8
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BusinessTripServiceImpl.java
  13. 36 12
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CardReplacementRecordServiceImpl.java
  14. 109 58
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/KaoqinRecordServiceImpl.java
  15. 211 32
      ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RecordLeaveServiceImpl.java
  16. 6 0
      ruoyi-system/src/main/resources/mapper/system/BusinessTripMapper.xml
  17. 3 1
      ruoyi-system/src/main/resources/mapper/system/CardReplacementRecordMapper.xml
  18. 1 1
      ruoyi-system/src/main/resources/mapper/system/KaoqinRecordMapper.xml
  19. 2 1
      ruoyi-system/src/main/resources/mapper/system/ProcessConfigurationMapper.xml
  20. 2 0
      ruoyi-system/src/main/resources/mapper/system/RecordLeaveMapper.xml

+ 7 - 2
ruoyi-admin/src/main/java/com/ruoyi/web/controller/index/IndexController.java

@@ -21,6 +21,7 @@ import com.ruoyi.framework.web.service.SysLoginService;
 import com.ruoyi.system.domain.KaoqinConfig;
 import com.ruoyi.system.domain.KaoqinRecord;
 import com.ruoyi.system.domain.SendSms;
+import com.ruoyi.system.mapper.KaoqinRecordMapper;
 import com.ruoyi.system.service.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
@@ -69,6 +70,10 @@ public class IndexController extends BaseController {
     @Autowired
     private ISysDictDataService dictDataService;
 
+
+    @Autowired
+    private KaoqinRecordMapper kaoqinRecordMapper;
+
     /**
      * app新增用户
      */
@@ -176,7 +181,7 @@ public class IndexController extends BaseController {
         //查询该部门及以下所有人员
         Integer total = userService.selectUserCount(kaoQinRecord);
         //查询打卡人员
-        List<KaoqinRecord> kaoqinRecords = kaoqinRecordService.selectKaoqinRecordList(kaoQinRecord);
+        List<KaoqinRecord> kaoqinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoQinRecord);
         int daKaNum = 0;
         if (kaoqinRecords != null) {
             daKaNum = kaoqinRecords.size();
@@ -223,7 +228,7 @@ public class IndexController extends BaseController {
 
         for (String date : dates) {
             kaoQinRecord.setKaTime(date);
-            List<KaoqinRecord> kaoqinRecords = kaoqinRecordService.selectKaoqinRecordList(kaoQinRecord);
+            List<KaoqinRecord> kaoqinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoQinRecord);
             Map<String, List<KaoqinRecord>> collect = kaoqinRecords.stream().collect(Collectors.groupingBy(KaoqinRecord::getKaStatus));
             if (collect != null) {
                 //正常

+ 109 - 22
ruoyi-admin/src/main/java/com/ruoyi/web/controller/kaoqin/KaoQinController.java

@@ -3,15 +3,20 @@ package com.ruoyi.web.controller.kaoqin;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.config.RuoYiConfig;
+import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.controller.BaseController;
 import com.ruoyi.common.core.domain.AjaxResult;
 import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysDictData;
+import com.ruoyi.common.core.domain.entity.SysRole;
+import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.page.TableDataInfo;
 import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.enums.BusinessType;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.MapToObjectUtils;
+import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.poi.ExcelUtil;
 import com.ruoyi.system.domain.*;
@@ -32,8 +37,7 @@ import java.util.*;
 import java.util.stream.Collectors;
 
 import static com.ruoyi.common.constant.CacheConstants.WEEK;
-import static com.ruoyi.common.constant.Constants.ONE;
-import static com.ruoyi.common.constant.Constants.SIX;
+import static com.ruoyi.common.constant.Constants.*;
 
 /**
  * 实现考勤打卡
@@ -74,6 +78,9 @@ public class KaoQinController extends BaseController {
     @Autowired
     private SysDeptMapper deptMapper;
 
+    @Autowired
+    private KaoqinRecordMapper kaoqinRecordMapper;
+
     /**
      * 定位打卡提供计算参数
      *
@@ -125,9 +132,10 @@ public class KaoQinController extends BaseController {
     @PreAuthorize("@ss.hasPermi('kaoqin:statistics:abnormal')")
     @GetMapping("/abnormal")
     public AjaxResult abnormal(KaoqinRecord kaoqinRecord) {
+
         //传入userId/年 和 月份 设置查询异常的考勤
         //kaoqinRecord.setKaStatus("2");
-        List<KaoqinRecord> kaoQinRecords = kaoqinRecordService.selectKaoqinRecordList(kaoqinRecord);
+        List<KaoqinRecord> kaoQinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
         //记录该月有多少次异常总数
         Long count = 0L;
         SysDictData dictData = new SysDictData();
@@ -153,7 +161,7 @@ public class KaoQinController extends BaseController {
                 //获取异常名称
                 String dictLabel = dictToString(kaTypeAmIn);
                 map.compute(dictLabel, (k, aLong) -> aLong + 1);
-                if (!SIX.equals(kaTypeAmIn)) {
+                if (!SIX.equals(kaTypeAmIn) && !SEVEN.equals(kaTypeAmIn) && !EIGHT.equals(kaTypeAmIn)) {
                     count = count + 1;
                 }
 
@@ -162,7 +170,7 @@ public class KaoQinController extends BaseController {
                 //获取异常名称
                 String dictLabel = dictToString(kaTypeAmOut);
                 map.compute(dictLabel, (k, aLong) -> aLong + 1);
-                if (!SIX.equals(kaTypeAmIn)) {
+                if (!SIX.equals(kaTypeAmOut) && !SEVEN.equals(kaTypeAmOut) && !EIGHT.equals(kaTypeAmOut)) {
                     count = count + 1;
                 }
             }
@@ -170,7 +178,7 @@ public class KaoQinController extends BaseController {
                 //获取异常名称
                 String dictLabel = dictToString(kaTypePmIn);
                 map.compute(dictLabel, (k, aLong) -> aLong + 1);
-                if (!SIX.equals(kaTypeAmIn)) {
+                if (!SIX.equals(kaTypePmIn) && !SEVEN.equals(kaTypePmIn) && !EIGHT.equals(kaTypePmIn)) {
                     count = count + 1;
                 }
             }
@@ -178,7 +186,7 @@ public class KaoQinController extends BaseController {
                 //获取异常名称
                 String dictLabel = dictToString(kaTypePmOut);
                 map.compute(dictLabel, (k, aLong) -> aLong + 1);
-                if (!SIX.equals(kaTypeAmIn)) {
+                if (!SIX.equals(kaTypePmOut) && !SEVEN.equals(kaTypePmOut) && !EIGHT.equals(kaTypePmOut)) {
                     count = count + 1;
                 }
             }
@@ -195,7 +203,7 @@ public class KaoQinController extends BaseController {
     @GetMapping("/calendar")
     public AjaxResult calendar(KaoqinRecord kaoqinRecord) {
         //根据打卡人id和月份去找对应的打卡记录
-        List<KaoqinRecord> kaoqinRecords = kaoqinRecordService.selectKaoqinRecordList(kaoqinRecord);
+        List<KaoqinRecord> kaoqinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
         //查询传入月补卡信息
         CardReplacementRecord cardReplacementRecord = new CardReplacementRecord();
         cardReplacementRecord.setUserId(kaoqinRecord.getUserId());
@@ -321,6 +329,12 @@ public class KaoQinController extends BaseController {
 
             //标签显示状态
             map.put("info", abnormal);
+            //标签显示状态补卡,出差,请假
+            Boolean fo = false;
+            if(cardReplacementCollect.get(date)!=null || !recordList.isEmpty() || !businessList.isEmpty()){
+                fo = true;
+            }
+            map.put("fo", fo);
             //打卡记录列表
             map.put("list", kaoqinRecords1);
             //补卡信息
@@ -341,6 +355,7 @@ public class KaoQinController extends BaseController {
      * @param
      * @return
      */
+    @PreAuthorize("@ss.hasPermi('kaoqin:statistics:clockRecord')")
     @PostMapping("/clockRecord")
     public AjaxResult clockRecord(KaoqinRecord kaoqinRecord) {
 
@@ -356,7 +371,7 @@ public class KaoQinController extends BaseController {
         //定义返回值
         List<Map<String, Object>> list = new ArrayList();
         //根据部门id查询考勤数据
-        List<KaoqinRecord> kaoqinRecords = kaoqinRecordService.selectKaoqinRecordList(kaoqinRecord);
+        List<KaoqinRecord> kaoqinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
         if (kaoqinRecords != null) {
             //根据userId进行分组
             Map<Long, List<KaoqinRecord>> kaoQinRecords = kaoqinRecords.stream().collect(Collectors.groupingBy(KaoqinRecord::getUserId));
@@ -456,7 +471,7 @@ public class KaoQinController extends BaseController {
             BigDecimal yesterdayBd = new BigDecimal(yesterdayMap.get(s));
             BigDecimal fz = todayBd.subtract(yesterdayBd);
             //比较是否等于0,返回true则不等于0,返回false,则等于0
-            if (fz.compareTo(BigDecimal.ZERO) != 0) {
+            if (fz.compareTo(BigDecimal.ZERO) != 0 && yesterdayBd.compareTo(BigDecimal.ZERO) != 0) {
                 BigDecimal percentage = BigDecimal.ZERO;
                 //昨天数据>0
                 if (yesterdayBd.compareTo(BigDecimal.ZERO) > 0) {
@@ -472,7 +487,7 @@ public class KaoQinController extends BaseController {
                     ;
                 }
             } else {
-                if (yesterdayBd.compareTo(BigDecimal.ZERO) == 0) {
+                if (yesterdayBd.compareTo(BigDecimal.ZERO) == 0  && todayBd.compareTo(BigDecimal.ZERO) != 0) {
                     zz = "100%";
                 }
             }
@@ -498,6 +513,24 @@ public class KaoQinController extends BaseController {
             kaoqinRecord.setKaYear(DateUtils.getYear());
             kaoqinRecord.setKaMonth(DateUtils.justMonth());
         }
+        // 判断角色
+        SysUser user = SecurityUtils.getLoginUser().getUser();
+        if (!"admin".equals(user.getUserName())){
+            List<SysRole> roles = user.getRoles();
+            Boolean bl = false;
+            for (SysRole role : roles) {
+                if("conservator".equals(role.getRoleKey())) {
+                    bl = true;
+                    break;
+                }
+            }
+            if (bl) {
+                kaoqinRecord.setDeptId(user.getDeptId());
+            }else{
+                kaoqinRecord.setUserId(user.getUserId());
+            }
+        }
+
         Map<String, Object> map = new HashMap();
         //查询当天考勤数据
         Map<String, Long> todayMap = day(kaoqinRecord);
@@ -519,7 +552,7 @@ public class KaoQinController extends BaseController {
             BigDecimal todayBd = new BigDecimal(todayMap.get(s));
             BigDecimal yesterdayBd = new BigDecimal(yesterdayMap.get(s));
             BigDecimal fz = todayBd.subtract(yesterdayBd);
-            if (fz.compareTo(BigDecimal.ZERO) != 0) {
+            if (fz.compareTo(BigDecimal.ZERO) != 0 && yesterdayBd.compareTo(BigDecimal.ZERO) != 0) {
                 BigDecimal percentage = BigDecimal.ZERO;
                 //昨天数据>0
                 if (yesterdayBd.compareTo(BigDecimal.ZERO) > 0) {
@@ -535,7 +568,7 @@ public class KaoQinController extends BaseController {
                     ;
                 }
             } else {
-                if (yesterdayBd.compareTo(BigDecimal.ZERO) == 0) {
+                if (yesterdayBd.compareTo(BigDecimal.ZERO) == 0 && todayBd.compareTo(BigDecimal.ZERO) != 0) {
                     zz = "100%";
                 }
             }
@@ -557,9 +590,13 @@ public class KaoQinController extends BaseController {
     @PreAuthorize("@ss.hasPermi('kaoqin:statistics:monthyAbnormal')")
     @GetMapping("/month/abnormal")
     public AjaxResult monthAbnormal(KaoqinRecord kaoqinRecord) {
+        if (StringUtils.isEmpty(kaoqinRecord.getKaMonth())) {
+            kaoqinRecord.setKaYear(DateUtils.getYear());
+            kaoqinRecord.setKaMonth(DateUtils.justMonth());
+        }
         Map<String, Object> mapTj = new HashMap();
         Map<String, Long> mapCount = new HashMap();
-        List<KaoqinRecord> kaoQinRecords = kaoqinRecordService.selectKaoqinRecordList(kaoqinRecord);
+        List<KaoqinRecord> kaoQinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
         //外勤打卡次数
         Long wq = 0L;
         //迟到打卡次数
@@ -641,7 +678,9 @@ public class KaoQinController extends BaseController {
         //kaoqinRecord.setKaStatus("2");
         //查找最新的考勤规则
         KaoqinConfig kaoqinConfigDept = kaoqinConfigService.selectKaoqinConfigBynew();
-        List<KaoqinRecord> kaoQinRecords = kaoqinRecordService.selectKaoqinRecordList(kaoqinRecord);
+        List<KaoqinRecord> kaoQinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
+        //打卡总数
+        Long zcs = 0L;
         //正常打卡次数
         Long zc = 0L;
         //外勤打卡次数
@@ -672,22 +711,26 @@ public class KaoQinController extends BaseController {
             String kaTypeAmOut = kaoQinRecord.getKaTypeAmOut();
             String kaTypePmIn = kaoQinRecord.getKaTypePmIn();
             String kaTypePmOut = kaoQinRecord.getKaTypePmOut();
-            if (StringUtils.isNotBlank(kaTypeAmIn)) {
+            if (StringUtils.isNotBlank(kaTypeAmIn) && !SIX.equals(kaTypeAmIn) && !SEVEN.equals(kaTypeAmIn) && !EIGHT.equals(kaTypeAmOut)) {
+                zcs = zcs + 1;
                 Long aLong = todayMap.get(kaTypeAmIn);
                 todayMap.put(kaTypeAmIn, aLong + 1);
             }
             //如果只配置了两次打卡,中间两次打卡不计入统计
             if ("4".equals(kaoqinConfigDept.getKaNum())) {
-                if (StringUtils.isNotBlank(kaTypeAmOut)) {
+                if (StringUtils.isNotBlank(kaTypeAmOut) && !SIX.equals(kaTypeAmOut) && !SEVEN.equals(kaTypeAmOut) && !EIGHT.equals(kaTypeAmOut)) {
+                    zcs = zcs + 1;
                     Long aLong = todayMap.get(kaTypeAmOut);
                     todayMap.put(kaTypeAmOut, aLong + 1);
                 }
-                if (StringUtils.isNotBlank(kaTypePmIn)) {
+                if (StringUtils.isNotBlank(kaTypePmIn) && !SIX.equals(kaTypePmIn) && !SEVEN.equals(kaTypePmIn) && !EIGHT.equals(kaTypePmIn)) {
+                    zcs = zcs + 1;
                     Long aLong = todayMap.get(kaTypePmIn);
                     todayMap.put(kaTypePmIn, aLong + 1);
                 }
             }
-            if (StringUtils.isNotBlank(kaTypePmOut)) {
+            if (StringUtils.isNotBlank(kaTypePmOut) && !SIX.equals(kaTypePmOut) && !SEVEN.equals(kaTypePmOut) && !EIGHT.equals(kaTypePmOut)) {
+                zcs = zcs + 1;
                 Long aLong = todayMap.get(kaTypePmOut);
                 todayMap.put(kaTypePmOut, aLong + 1);
             }
@@ -700,6 +743,7 @@ public class KaoQinController extends BaseController {
         bk = todayMap.get("6");
 
         map.put("zs", count);
+        map.put("zcs", zcs);
         map.put("zc", zc);
         map.put("wq", wq);
         map.put("cd", cd);
@@ -723,6 +767,10 @@ public class KaoQinController extends BaseController {
             str = "qk";
         } else if ("6".equals(value)) {
             str = "bk";
+        } else if ("7".equals(value)) {
+            str = "qj";
+        } else if ("8".equals(value)) {
+            str = "cc";
         }
         return str;
     }
@@ -733,12 +781,20 @@ public class KaoQinController extends BaseController {
     @PreAuthorize("@ss.hasPermi('kaoqin:statistics:weekBk')")
     @GetMapping("/week/bk")
     public AjaxResult weekBk() {
+
+
         Map<String, Object> map = new HashMap();
         //周一到周六的日期
         List<String> weekDates = DateUtils.getWeekDatesFromMondayToSaturday();
         List<String> weekName = Arrays.asList(WEEK);
         //查询本周的补卡信息
-        List<CardReplacementRecord> cardReplacementRecordList = cardReplacementRecordMapper.selectCardReplacementRecordListWeek();
+        // 判断角色
+        CardReplacementRecord cardReplacementRecord = new CardReplacementRecord();
+        SysUser user = SecurityUtils.getLoginUser().getUser();
+        if (!"admin".equals(user.getUserName())){
+            cardReplacementRecord.setDeptId(user.getDeptId());
+        }
+        List<CardReplacementRecord> cardReplacementRecordList = cardReplacementRecordMapper.selectCardReplacementRecordListWeek(cardReplacementRecord);
         Map<String, List<CardReplacementRecord>> cardMap = cardReplacementRecordList.stream().collect(Collectors.groupingBy(CardReplacementRecord::getApplicationDate));
         List<Integer> nums = new ArrayList<>();
         for (int i = 0; i < weekDates.size(); i++) {
@@ -764,7 +820,13 @@ public class KaoQinController extends BaseController {
         List<String> weekDates = DateUtils.getWeekDatesFromMondayToSaturday();
         List<String> weekName = Arrays.asList(WEEK);
         //查询本周的请假信息
-        List<RecordLeave> recordLeaves = recordLeaveMapper.selectRecordLeaveListWeek();
+        // 判断角色
+        RecordLeave recordLeave = new RecordLeave();
+        SysUser user = SecurityUtils.getLoginUser().getUser();
+        if (!"admin".equals(user.getUserName())){
+            recordLeave.setDeptId(user.getDeptId());
+        }
+        List<RecordLeave> recordLeaves = recordLeaveMapper.selectRecordLeaveListWeek(recordLeave);
 
         List<Integer> nums = new ArrayList<>();
         for (int i = 0; i < weekDates.size(); i++) {
@@ -804,6 +866,31 @@ public class KaoQinController extends BaseController {
             throw new RuntimeException(e);
         }
         ExcelUtil<BaobiaoVo> util = new ExcelUtil<BaobiaoVo>(BaobiaoVo.class);
-        util.exportExcel(response, baobiaoVoList, "考勤统计数据");
+        util.exportExcel(response,baobiaoVoList, "考勤统计数据");
+
+    }
+
+    /**
+     * 导出人员打卡情况报表 返回文件地址
+     */
+    @PreAuthorize("@ss.hasPermi('kaoqin:statistics:urlExport')")
+    @Log(title = "导出人员打卡情况报表", businessType = BusinessType.EXPORT)
+    @PostMapping("/url/export")
+    public AjaxResult urlExport(HttpServletResponse response, KaoqinRecord kaoqinRecord) {
+        List<Map<String, Object>> maps = kqRecord(kaoqinRecord);
+        List<BaobiaoVo> baobiaoVoList = new ArrayList<>();
+        try {
+            for (Map<String, Object> map : maps) {
+
+                BaobiaoVo baobiaoVo = MapToObjectUtils.populate(map, BaobiaoVo.class);
+                baobiaoVoList.add(baobiaoVo);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+        ExcelUtil<BaobiaoVo> util = new ExcelUtil<BaobiaoVo>(BaobiaoVo.class);
+
+        return util.exportExcel(baobiaoVoList, "考勤统计数据");
+
     }
 }

+ 7 - 4
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysProfileController.java

@@ -24,6 +24,7 @@ import com.ruoyi.common.utils.file.MimeTypeUtils;
 import com.ruoyi.framework.web.service.TokenService;
 import com.ruoyi.system.service.ISysUserService;
 
+import static com.ruoyi.common.constant.Constants.ONE;
 import static com.ruoyi.common.constant.Constants.TWO;
 import static com.ruoyi.common.utils.SecurityUtils.checkStrongPwd;
 
@@ -144,15 +145,17 @@ public class SysProfileController extends BaseController {
     public AjaxResult face(@RequestParam("file") MultipartFile file, @RequestParam("userId") Long userId,@RequestParam("nickName") String nickName) throws Exception {
         if (!file.isEmpty()) {
             String newFileName = userId+"_"+nickName;
-            String face = FileUploadUtils.uploadFileName(RuoYiConfig.getFacePath(), file, MimeTypeUtils.IMAGE_EXTENSION,newFileName);
+            String face = FileUploadUtils.uploadFileName(RuoYiConfig.getFacePath(), file, MimeTypeUtils.IMAGE_EXTENSION,newFileName,ONE);
+
+            String faceBd = FileUploadUtils.uploadFileName(RuoYiConfig.getUploadPath(), file, MimeTypeUtils.IMAGE_EXTENSION,newFileName,TWO);
             //保存进数据库
             SysUser user = new SysUser();
             user.setUserId(userId);
-            user.setFacePhoto(face);
-            user.setFaceType(TWO);
+            user.setFacePhoto(faceBd);
+            user.setFaceType(ONE);
             userService.updateUserProfile(user);
             AjaxResult ajax = AjaxResult.success();
-            ajax.put("imgUrl", face);
+            ajax.put("imgUrl", faceBd);
             return ajax;
 
         }

+ 1 - 1
ruoyi-admin/src/main/resources/application-prod.yml

@@ -65,7 +65,7 @@ spring:
             master:
                 url: jdbc:mysql://127.0.0.1:3306/OA_kaoqin?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
                 username: root
-                password: zhaoshang@2018
+                password: 1q2w!Q@W
             # 从库数据源
             slave:
                 # 从数据源开关/默认关闭

+ 1 - 0
ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/SysUser.java

@@ -104,6 +104,7 @@ public class SysUser extends BaseEntity
 
     private String parameter;
 
+
     public String getCode() {
         return code;
     }

+ 155 - 5
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java

@@ -6,10 +6,12 @@ import java.text.SimpleDateFormat;
 import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoUnit;
 import java.time.temporal.TemporalAdjusters;
 import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.IntStream;
+import java.util.stream.Stream;
 
 import org.apache.commons.lang3.time.DateFormatUtils;
 
@@ -32,7 +34,7 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
     public static String YYYYMMDD = "yyyyMMdd";
 
     private static String[] parsePatterns = {
-            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
+            "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM","HH:mm:ss",
             "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
             "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};
 
@@ -432,11 +434,159 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
         return LocalTime.parse(timeStr, TIME_FORMATTER);
     }
 
-    public static void main(String[] args) {
 
-        String full1 = "09:30:00";
-        String full2 = "09:30:00";
-        System.out.println(compareTimes(full1, full2, "HH:mm:ss")); // 0
+    /**
+     * 获取两个日期之间的所有日期(包含开始和结束日期),返回字符串列表
+     *
+     * @param startDate 开始日期
+     * @param endDate   结束日期
+     * @return 日期字符串列表(格式:yyyy-MM-dd)
+     */
+    public static List<String> getDateStringsBetween(Date startDate, Date endDate) {
+        List<String> dateStrings = new ArrayList<>();
+
+        if (startDate == null || endDate == null) {
+            return dateStrings;
+        }
+
+        // 转换为Java 8的LocalDate
+        LocalDate start = startDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+        LocalDate end = endDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
+
+        if (start.isAfter(end)) {
+            return dateStrings;
+        }
+
+        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+
+        while (!start.isAfter(end)) {
+            dateStrings.add(formatter.format(start));
+            start = start.plusDays(1);
+        }
+
+        return dateStrings;
     }
 
+    public static void main(String[] args) throws ParseException {
+
+        try {
+            // 1. 准备日期部分
+            LocalDate datePart = LocalDate.of(2023, 12, 25);
+
+            // 2. 准备时间部分(只关心时间)
+            // 创建时间对象(日期部分无关紧要)
+            Date timePart = parseDate("17:44:52"); // 当前时间
+            System.out.println("原始时间Date: " + timePart);
+
+            // 3. 组合日期和时间
+            LocalDateTime result = combineDateTime(datePart, timePart);
+
+            // 4. 输出结果
+            System.out.println("组合后的LocalDateTime: " + result);
+            System.out.println("格式化输出: " +
+                    result.format(java.time.format.DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
+
+            // 5. 测试边界情况
+            // 午夜时间
+            Date midnight = java.util.Date.from(
+                    java.time.LocalTime.MIDNIGHT.atDate(LocalDate.now())
+                            .atZone(ZoneId.systemDefault())
+                            .toInstant()
+            );
+            LocalDateTime midnightResult = combineDateTime(datePart, midnight);
+            System.out.println("午夜时间组合: " + midnightResult);
+
+            // 最大时间
+            Date maxTime = java.util.Date.from(
+                    java.time.LocalTime.MAX.atDate(LocalDate.now())
+                            .atZone(ZoneId.systemDefault())
+                            .toInstant()
+            );
+            LocalDateTime maxResult = combineDateTime(datePart, maxTime);
+            System.out.println("最大时间组合: " + maxResult);
+
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    // 转换日期类型
+    public static LocalDateTime convertToLocalDateTime(Date date) {
+        return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
+    }
+
+    /**
+     * 获取两个日期之间的所有日期(包含开始和结束日期)
+     *
+     * @param startDate 开始日期
+     * @param endDate   结束日期
+     * @return 日期列表
+     */
+    public static List<LocalDate> getDateRange(LocalDate startDate, LocalDate endDate) {
+        List<LocalDate> dates = new ArrayList<>();
+
+        // 计算总天数(包含结束日)
+        long numOfDays = ChronoUnit.DAYS.between(startDate, endDate) + 1;
+
+        // 通过循环添加每一天
+        for (long i = 0; i < numOfDays; i++) {
+            dates.add(startDate.plusDays(i));
+        }
+
+        return dates;
+    }
+
+    /**
+     * 将 LocalDate 转换为字符串
+     * @param date 要转换的日期
+     * @param pattern 日期格式模式(可选),如果为null则使用默认格式
+     * @return 格式化后的日期字符串
+     */
+    public static String convertToString(LocalDate date, String pattern) {
+        if (date == null) {
+            return null;
+        }
+
+        if (pattern != null && !pattern.isEmpty()) {
+            // 使用自定义格式
+            return DateTimeFormatter.ofPattern(pattern).format(date);
+        } else {
+            // 使用默认格式 (ISO_LOCAL_DATE)
+            return date.toString();
+        }
+    }
+
+    // 获取星期数
+    public static String getWeekday(LocalDate date) {
+        int weekValue = date.getDayOfWeek().getValue();
+        return weekValue == 7 ? "0" : String.valueOf(weekValue); // 周日特殊处理
+    }
+
+    /**
+     * 将时间Date对象与LocalDate组合成LocalDateTime
+     *
+     * @param dateOnly 日期部分(LocalDate)
+     * @param timeOnly 时间部分(Date对象,只取时间部分)
+     * @return 组合后的LocalDateTime对象
+     * @throws IllegalArgumentException 如果任一参数为null
+     */
+    public static LocalDateTime combineDateTime(LocalDate dateOnly, Date timeOnly) {
+        // 验证输入
+        if (dateOnly == null) {
+            throw new IllegalArgumentException("日期部分不能为null");
+        }
+        if (timeOnly == null) {
+            throw new IllegalArgumentException("时间部分不能为null");
+        }
+
+        // 提取时间部分(忽略日期部分)
+        LocalTime localTime = timeOnly.toInstant()
+                .atZone(ZoneId.systemDefault())
+                .toLocalTime();
+
+        // 组合日期和时间
+        return LocalDateTime.of(dateOnly, localTime);
+    }
+
+
 }

+ 9 - 2
ruoyi-common/src/main/java/com/ruoyi/common/utils/file/FileUploadUtils.java

@@ -15,6 +15,8 @@ import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.common.utils.uuid.Seq;
 
+import static com.ruoyi.common.constant.Constants.ONE;
+
 /**
  * 文件上传工具类
  *
@@ -130,7 +132,7 @@ public class FileUploadUtils
      * @throws IOException 比如读写文件出错时
      * @throws InvalidExtensionException 文件校验异常
      */
-    public static final String uploadFileName(String baseDir, MultipartFile file, String[] allowedExtension,String fileName)
+    public static final String uploadFileName(String baseDir, MultipartFile file, String[] allowedExtension,String fileName,String type)
             throws FileSizeLimitExceededException, IOException, FileNameLengthLimitExceededException,
             InvalidExtensionException
     {
@@ -145,7 +147,12 @@ public class FileUploadUtils
 
         String absPath = getAbsoluteFile(baseDir, fileName).getAbsolutePath();
         file.transferTo(Paths.get(absPath));
-        return getFacePathFileName(baseDir, fileName);
+        if(ONE.equals(type)){
+            return getFacePathFileName(baseDir, fileName);
+        }else{
+            return getPathFileName(baseDir, fileName);
+        }
+
     }
 
 

+ 8 - 1
ruoyi-common/src/main/java/com/ruoyi/common/utils/poi/ExcelUtil.java

@@ -24,6 +24,8 @@ import java.util.Set;
 import java.util.UUID;
 import java.util.stream.Collectors;
 import javax.servlet.http.HttpServletResponse;
+
+import com.ruoyi.common.constant.Constants;
 import org.apache.commons.lang3.ArrayUtils;
 import org.apache.commons.lang3.RegExUtils;
 import org.apache.commons.lang3.reflect.FieldUtils;
@@ -622,7 +624,12 @@ public class ExcelUtil<T>
             String filename = encodingFilename(sheetName);
             out = new FileOutputStream(getAbsoluteFile(filename));
             wb.write(out);
-            return AjaxResult.success(filename);
+
+            int dirLastIndex = RuoYiConfig.getProfile().length() + 1;
+            String currentDir = StringUtils.substring(RuoYiConfig.getDownloadPath(), dirLastIndex);
+            String path =  Constants.RESOURCE_PREFIX + "/" + currentDir + filename;
+
+            return AjaxResult.success("导出成功",path);
         }
         catch (Exception e)
         {

+ 1 - 1
ruoyi-system/src/main/java/com/ruoyi/system/mapper/CardReplacementRecordMapper.java

@@ -59,5 +59,5 @@ public interface CardReplacementRecordMapper
      */
     public int deleteCardReplacementRecordByIds(Long[] ids);
 
-    List<CardReplacementRecord> selectCardReplacementRecordListWeek();
+    List<CardReplacementRecord> selectCardReplacementRecordListWeek(CardReplacementRecord cardReplacementRecord);
 }

+ 1 - 1
ruoyi-system/src/main/java/com/ruoyi/system/mapper/RecordLeaveMapper.java

@@ -60,5 +60,5 @@ public interface RecordLeaveMapper
      */
     public int deleteRecordLeaveByIds(Long[] ids);
 
-    List<RecordLeave> selectRecordLeaveListWeek();
+    List<RecordLeave> selectRecordLeaveListWeek(RecordLeave recordLeave);
 }

+ 18 - 0
ruoyi-system/src/main/java/com/ruoyi/system/service/Task.java

@@ -8,6 +8,7 @@ import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.core.redis.RedisCache;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.HolidayUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.domain.AttendanceTime;
 import com.ruoyi.system.domain.KaoqinConfig;
 import com.ruoyi.system.domain.KaoqinRecord;
@@ -72,6 +73,9 @@ public class Task {
         KaoqinRecord kaoqinRecord = new KaoqinRecord();
         kaoqinRecord.setKaTime(data);
         List<KaoqinRecord> kaoqinRecordList = kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
+        if(kaoqinRecordList == null || kaoqinRecordList.isEmpty()){
+            return;
+        }
         for (SysUser sysUser : userList) {
             boolean blt = false;
             if(attendanceTimes != null && !attendanceTimes.isEmpty()){
@@ -88,6 +92,20 @@ public class Task {
             boolean bl = true;
             for (KaoqinRecord record : kaoqinRecordList) {
                 if(record.getUserId().equals(sysUser.getUserId())){
+                    if(StringUtils.isNotBlank(record.getKaTypeAmIn())){
+                        record.setKaTypeAmIn(FIVE);
+                    }
+                    if(FOUR.equals(kaoqinConfig.getKaNum())){
+                        if(StringUtils.isNotBlank(record.getKaTypeAmOut())){
+                            record.setKaTypeAmOut(FIVE);
+                        }
+                        if(StringUtils.isNotBlank(record.getKaTypePmIn())){
+                            record.setKaTypePmIn(FIVE);
+                        }
+                    }
+                    if(StringUtils.isNotBlank(record.getKaTypePmOut())){
+                        record.setKaTypePmOut(FIVE);
+                    }
                     bl = false;
                 }
             }

+ 189 - 8
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/BusinessTripServiceImpl.java

@@ -1,24 +1,29 @@
 package com.ruoyi.system.service.impl;
 
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.system.domain.BusinessUser;
-import com.ruoyi.system.domain.ProcessConfiguration;
-import com.ruoyi.system.mapper.BusinessUserMapper;
-import com.ruoyi.system.mapper.ProcessConfigurationMapper;
-import com.ruoyi.system.mapper.SysUserMapper;
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.mapper.*;
+import com.ruoyi.system.service.IKaoqinRecordService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.ruoyi.system.mapper.BusinessTripMapper;
-import com.ruoyi.system.domain.BusinessTrip;
 import com.ruoyi.system.service.IBusinessTripService;
 
+import static com.ruoyi.common.constant.Constants.*;
+
 /**
  * 出差记录信息Service业务层处理
  * 
@@ -40,6 +45,22 @@ public class BusinessTripServiceImpl implements IBusinessTripService
     @Autowired
     private ProcessConfigurationMapper processConfigurationMapper;
 
+    @Autowired
+    private KaoqinConfigMapper kaoqinConfigMapper;
+
+    @Autowired
+    private IKaoqinRecordService kaoqinRecordService;
+
+    @Autowired
+    private KaoqinRecordMapper kaoqinRecordMapper;
+
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+    @Autowired
+    private SysDeptMapper deptMapper;
+
+
     /**
      * 查询出差记录信息
      * 
@@ -217,9 +238,154 @@ public class BusinessTripServiceImpl implements IBusinessTripService
         SysUser user = SecurityUtils.getLoginUser().getUser();
         businessTrip.setExaminersId(user.getUserId());
         businessTrip.setExaminersName(user.getNickName());
+        if (TWO.equals(businessTrip.getIsPass())) {
+            //查询出差信息
+            BusinessTrip trip = businessTripMapper.selectBusinessTripById(businessTrip.getId());
+            //出差人员
+            BusinessUser businessUser = new BusinessUser();
+            businessUser.setBusinessId(businessTrip.getId());
+            List<BusinessUser> businessUsers = businessUserMapper.selectBusinessUserList(businessUser);
+            //考勤规则
+            KaoqinConfig kaoqinConfig = kaoqinConfigMapper.selectKaoqinConfigBynew();
+
+            // 3. 解析出差时间范围
+            LocalDateTime start = DateUtils.convertToLocalDateTime(trip.getStartTime());
+            LocalDateTime end = DateUtils.convertToLocalDateTime(trip.getEndTime());
+            // 获取日期列表
+            List<LocalDate> leaveDates = DateUtils.getDateRange(start.toLocalDate(), end.toLocalDate());
+            for (BusinessUser businessUser1 : businessUsers) {
+                //查询打卡信息
+                KaoqinRecord kaoqinRecord = new KaoqinRecord();
+                kaoqinRecord.setUserId(businessUser1.getAbsenteeId());
+                kaoqinRecord.setStartTime(DateUtils.dateTime(trip.getStartTime()));
+                kaoqinRecord.setEndTime(DateUtils.dateTime(trip.getEndTime()));
+                List<KaoqinRecord> kaoqinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
+                Map<String, List<KaoqinRecord>> kaoqinRecordCollect = kaoqinRecords.stream().collect(Collectors.groupingBy(KaoqinRecord::getKaTime));
+
+                //查询人员信息
+                SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(businessUser1.getAbsenteeId()));
+
+                // 5. 处理每个请假日期
+                for (LocalDate date : leaveDates) {
+                    KaoqinRecord record = null;
+                    if (kaoqinRecordCollect.containsKey(DateUtils.convertToString(date, "yyyy-MM-dd"))) {
+                        record = new KaoqinRecord();
+                        record = kaoqinRecordCollect.get(DateUtils.convertToString(date, "yyyy-MM-dd")).get(0);
+                    }
+                    updateDailyAttendance(date, start, end, kaoqinConfig, record,sysUser);
+                }
+
+            }
+
+        }
+
         return businessTripMapper.updateBusinessTrip(businessTrip);
     }
 
+    private void updateDailyAttendance(LocalDate date, LocalDateTime leaveStart, LocalDateTime leaveEnd, KaoqinConfig config, KaoqinRecord record, SysUser sysUser) {
+        // 3. 不存在记录则创建新记录
+        if (record == null) {
+            record = createNewRecord(date, config,sysUser);
+        }
+
+        // 4. 更新打卡时段状态
+        updateTimeSlotStatus(record, date, leaveStart, leaveEnd, config);
+
+        // 5. 检查整体考勤状态
+        updateOverallStatus(record);
+
+        // 6. 保存更新
+        if(record.getRecordId() == null || record.getRecordId() == 0) {
+            kaoqinRecordMapper.insertKaoqinRecord(record);
+        }else{
+            kaoqinRecordMapper.updateKaoqinRecord(record);
+        }
+    }
+
+    private void updateTimeSlotStatus(KaoqinRecord record, LocalDate date, LocalDateTime leaveStart, LocalDateTime leaveEnd, KaoqinConfig config) {
+        // 从配置获取打卡时间
+        LocalDateTime amInEnd = DateUtils.combineDateTime(date,config.getKaTimeAmIn()); // 上午上班截止时间
+        LocalDateTime amOutStart = DateUtils.combineDateTime(date,config.getKaTimeAmOut());// 上午下班开始时间
+        LocalDateTime pmInEnd = DateUtils.combineDateTime(date,config.getKaTimePmIn());// 下午上班截止时间
+        LocalDateTime pmOutStart = DateUtils.combineDateTime(date,config.getKaTimePmOut());// 下午下班开始时间
+
+        // 检查请假是否覆盖各时段
+        if (isLeaveCovered(leaveStart, leaveEnd, amInEnd)) {
+            record.setKaTypeAmIn(EIGHT); // 上午上班出差
+        }
+        if(FOUR.equals(config.getKaNum())){
+            if (isLeaveCovered(leaveStart, leaveEnd,amOutStart)) {
+                record.setKaTypeAmOut(EIGHT); // 上午下班出差
+            }
+
+            if (isLeaveCovered(leaveStart, leaveEnd, pmInEnd)) {
+                record.setKaTypePmIn(EIGHT); // 下午上班出差
+            }
+        }
+/*
+        if (isLeaveCovered(leaveStart, leaveEnd, pmInEnd, pmOutStart)) {
+            record.setKaTypePmOut("7"); // 下午下班出差
+        }*/
+        if (isLeaveCovered(leaveStart, leaveEnd, pmOutStart)) {
+            record.setKaTypePmOut(EIGHT); // 下午下班出差
+        }
+    }
+
+    // 检查请假是否覆盖时间段
+    private boolean isLeaveCovered(LocalDateTime leaveStart, LocalDateTime leaveEnd,
+                                   LocalDateTime active) {
+        return (leaveStart.isBefore(active) &&
+                leaveEnd.isAfter(active));
+    }
+
+    // 更新整体考勤状态
+    private void updateOverallStatus(KaoqinRecord record) {
+        // 检查是否有异常状态(非正常和非请假)
+        boolean hasAbnormal = Stream.of(
+                        record.getKaTypeAmIn(),
+                        record.getKaTypeAmOut(),
+                        record.getKaTypePmIn(),
+                        record.getKaTypePmOut()
+                )
+                .filter(status -> !"1".equals(status) && !"8".equals(status))
+                .findAny()
+                .isPresent();
+
+        record.setKaStatus(hasAbnormal ? "2" : "1");
+    }
+
+    private KaoqinRecord createNewRecord(LocalDate date, KaoqinConfig config, SysUser sysUser) {
+        KaoqinRecord record = new KaoqinRecord();
+        record.setUserId(sysUser.getUserId());
+        record.setUserName(sysUser.getNickName());
+        record.setDeptId(sysUser.getDeptId());
+        record.setDeptName(sysUser.getDept().getDeptName());
+        record.setAncestors(sysUser.getDept().getAncestors());
+        record.setKaNum(config.getKaNum()); // 使用配置的打卡次数
+
+        // 设置日期相关字段
+        record.setKaYear(String.valueOf(date.getYear()));
+        record.setKaMonth(String.format("%02d", date.getMonthValue()));
+        record.setKaDay(String.format("%02d", date.getDayOfMonth()));
+        record.setKaWeek(DateUtils.getWeekday(date));
+        record.setKaTime(date.format(DateTimeFormatter.ISO_LOCAL_DATE));
+
+        // 设置默认状态
+        record.setKaTypeAmIn("5");
+        record.setKaTypeAmOut("5");
+        record.setKaTypePmIn("5");
+        record.setKaTypePmOut("5");
+        record.setKaStatus("1");
+
+        // 设置考勤地址
+        record.setKaAddressAmIn(config.getKaAddress());
+        record.setKaAddressAmOut(config.getKaAddress());
+        record.setKaAddressPmIn(config.getKaAddress());
+        record.setKaAddressPmOut(config.getKaAddress());
+
+        return record;
+    }
+
     @Override
     public List<BusinessTrip> presentList(BusinessTrip businessTrip) {
 
@@ -231,8 +397,23 @@ public class BusinessTripServiceImpl implements IBusinessTripService
             processConfiguration.setUserId(user.getUserId());
             processConfiguration.setType("3");
             List<ProcessConfiguration> list = processConfigurationMapper.selectProcessConfigurationList(processConfiguration);
+            if(list==null|| list.isEmpty()){
+                List<BusinessTrip> businessTripList = new ArrayList<>();
+                return businessTripList;
+            }
+            List<Long> deptIdList = new ArrayList<>();
             List<Long> deptIds = list.stream().map(ProcessConfiguration::getDeptId).collect(Collectors.toList());
-            businessTrip.setDeptIds(deptIds);
+            deptIdList.addAll(deptIds);
+            for (Long deptId : deptIds) {
+                //查询所有子部门
+                List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
+                if(children!=null && !children.isEmpty()){
+                    List<Long> childrenIds = children.stream().map(SysDept::getDeptId).collect(Collectors.toList());
+                    deptIdList.addAll(childrenIds);
+                }
+            }
+
+            businessTrip.setDeptIds(deptIdList);
         }
         return businessTripMapper.selectBusinessTripList(businessTrip);
     }

+ 36 - 12
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/CardReplacementRecordServiceImpl.java

@@ -1,22 +1,23 @@
 package com.ruoyi.system.service.impl;
 
+import java.util.ArrayList;
 import java.util.List;
 import java.util.stream.Collectors;
 
 import com.ruoyi.common.constant.HttpStatus;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
 import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.BusinessTrip;
 import com.ruoyi.system.domain.KaoqinRecord;
 import com.ruoyi.system.domain.ProcessConfiguration;
-import com.ruoyi.system.mapper.KaoqinRecordMapper;
-import com.ruoyi.system.mapper.ProcessConfigurationMapper;
+import com.ruoyi.system.mapper.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.ruoyi.system.mapper.CardReplacementRecordMapper;
 import com.ruoyi.system.domain.CardReplacementRecord;
 import com.ruoyi.system.service.ICardReplacementRecordService;
 
@@ -40,6 +41,11 @@ public class CardReplacementRecordServiceImpl implements ICardReplacementRecordS
     @Autowired
     private KaoqinRecordMapper kaoqinRecordMapper;
 
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+    @Autowired
+    private SysDeptMapper deptMapper;
     /**
      * 查询补卡记录
      * 
@@ -133,8 +139,12 @@ public class CardReplacementRecordServiceImpl implements ICardReplacementRecordS
         SysUser user = SecurityUtils.getLoginUser().getUser();
         //查询打卡信息
         if(TWO.equals(cardReplacementRecord.getIsPass())){
-            String date = DateUtils.getDate();
-            KaoqinRecord kaoqinRecord = kaoqinRecordMapper.selectKaoqinRecordByRecordByUser(user.getUserId(),date);
+            //查询信息
+            CardReplacementRecord cardReplacementRecord1 = cardReplacementRecordMapper.selectCardReplacementRecordById(cardReplacementRecord.getId());
+            //查询补卡人员信息
+            SysUser sysUser = sysUserMapper.selectUserById(cardReplacementRecord1.getUserId());
+            String date = cardReplacementRecord1.getApplicationDate();
+            KaoqinRecord kaoqinRecord = kaoqinRecordMapper.selectKaoqinRecordByRecordByUser(sysUser.getUserId(),date);
             if(kaoqinRecord != null){
                 if(ONE.equals(cardReplacementRecord.getKaSort())){
                     kaoqinRecord.setKaTypeAmIn(SIX);
@@ -151,12 +161,12 @@ public class CardReplacementRecordServiceImpl implements ICardReplacementRecordS
                 //将日期拆分成年月日的数组
                 String[] datas = date.split("-");
                 KaoqinRecord kaoqinRecords = new KaoqinRecord();
-                kaoqinRecords.setUserId(user.getUserId());
-                kaoqinRecords.setUserName(user.getNickName());
-                kaoqinRecords.setPhone(user.getPhonenumber());
-                kaoqinRecords.setDeptId(user.getDeptId());
-                kaoqinRecords.setDeptName(user.getDept().getDeptName());
-                kaoqinRecords.setAncestors(user.getDept().getAncestors());
+                kaoqinRecords.setUserId(sysUser.getUserId());
+                kaoqinRecords.setUserName(sysUser.getNickName());
+                kaoqinRecords.setPhone(sysUser.getPhonenumber());
+                kaoqinRecords.setDeptId(sysUser.getDeptId());
+                kaoqinRecords.setDeptName(sysUser.getDept().getDeptName());
+                kaoqinRecords.setAncestors(sysUser.getDept().getAncestors());
                 kaoqinRecords.setKaYear(datas[0]);
                 kaoqinRecords.setKaMonth(datas[1]);
                 kaoqinRecords.setKaDay(datas[2]);
@@ -193,8 +203,22 @@ public class CardReplacementRecordServiceImpl implements ICardReplacementRecordS
             processConfiguration.setUserId(user.getUserId());
             processConfiguration.setType(ONE);
             List<ProcessConfiguration> list = processConfigurationMapper.selectProcessConfigurationList(processConfiguration);
+            if(list==null|| list.isEmpty()){
+                List<CardReplacementRecord> cardReplacementRecordList = new ArrayList<>();
+                return cardReplacementRecordList;
+            }
+            List<Long> deptIdList = new ArrayList<>();
             List<Long> deptIds = list.stream().map(ProcessConfiguration::getDeptId).collect(Collectors.toList());
-            cardReplacementRecord.setDeptIds(deptIds);
+            deptIdList.addAll(deptIds);
+            for (Long deptId : deptIds) {
+                //查询所有子部门
+                List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
+                if(children!=null && !children.isEmpty()){
+                    List<Long> childrenIds = children.stream().map(SysDept::getDeptId).collect(Collectors.toList());
+                    deptIdList.addAll(childrenIds);
+                }
+            }
+            cardReplacementRecord.setDeptIds(deptIdList);
         }
         return cardReplacementRecordMapper.selectCardReplacementRecordList(cardReplacementRecord);
     }

+ 109 - 58
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/KaoqinRecordServiceImpl.java

@@ -3,10 +3,12 @@ package com.ruoyi.system.service.impl;
 import java.util.List;
 
 import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.common.core.domain.entity.SysRole;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.model.MqttMessage;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
 import com.ruoyi.system.domain.KaoqinConfig;
 import com.ruoyi.system.domain.KaoqinRecord;
 import com.ruoyi.system.mapper.KaoqinConfigMapper;
@@ -22,13 +24,12 @@ import static com.ruoyi.common.constant.Constants.*;
 
 /**
  * 考勤记录Service业务层处理
- * 
+ *
  * @author boman
  * @date 2023-02-09
  */
 @Service
-public class KaoqinRecordServiceImpl implements IKaoqinRecordService
-{
+public class KaoqinRecordServiceImpl implements IKaoqinRecordService {
     @Autowired
     private KaoqinRecordMapper kaoqinRecordMapper;
 
@@ -40,42 +41,57 @@ public class KaoqinRecordServiceImpl implements IKaoqinRecordService
 
     /**
      * 查询考勤记录
-     * 
+     *
      * @param recordId 考勤记录主键
      * @return 考勤记录
      */
     @Override
-    public KaoqinRecord selectKaoqinRecordByRecordId(Long recordId)
-    {
+    public KaoqinRecord selectKaoqinRecordByRecordId(Long recordId) {
         return kaoqinRecordMapper.selectKaoqinRecordByRecordId(recordId);
     }
 
     /**
      * 查询考勤记录列表
-     * 
+     *
      * @param kaoqinRecord 考勤记录
      * @return 考勤记录
      */
     @Override
-    public List<KaoqinRecord> selectKaoqinRecordList(KaoqinRecord kaoqinRecord)
-    {
+    public List<KaoqinRecord> selectKaoqinRecordList(KaoqinRecord kaoqinRecord) {
+        // 判断角色
+        SysUser user = SecurityUtils.getLoginUser().getUser();
+        if (!"admin".equals(user.getUserName())) {
+            List<SysRole> roles = user.getRoles();
+            Boolean bl = false;
+            for (SysRole role : roles) {
+                if ("conservator".equals(role.getRoleKey())) {
+                    bl = true;
+                    break;
+                }
+            }
+            if (bl) {
+                kaoqinRecord.setDeptId(user.getDeptId());
+            } else {
+                kaoqinRecord.setUserId(user.getUserId());
+            }
+        }
+
         return kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
     }
 
     /**
      * 新增考勤记录
-     * 
+     *
      * @param kaoqinRecord 考勤记录
      * @return 结果
      */
     @Override
-    public int insertKaoqinRecord(KaoqinRecord kaoqinRecord)
-    {
+    public int insertKaoqinRecord(KaoqinRecord kaoqinRecord) {
         //获取当前人员信息
         SysUser user = SecurityUtils.getLoginUser().getUser();
         String ancestors = kaoqinRecord.getAncestors();
         Long deptId = kaoqinRecord.getDeptId();
-        ancestors = ancestors +","+ deptId;
+        ancestors = ancestors + "," + deptId;
         kaoqinRecord.setAncestors(ancestors);
         kaoqinRecord.setCreateTime(DateUtils.getNowDate());
         kaoqinRecord.setPhone(user.getPhonenumber());
@@ -84,38 +100,35 @@ public class KaoqinRecordServiceImpl implements IKaoqinRecordService
 
     /**
      * 修改考勤记录
-     * 
+     *
      * @param kaoqinRecord 考勤记录
      * @return 结果
      */
     @Override
-    public int updateKaoqinRecord(KaoqinRecord kaoqinRecord)
-    {
+    public int updateKaoqinRecord(KaoqinRecord kaoqinRecord) {
         kaoqinRecord.setUpdateTime(DateUtils.getNowDate());
         return kaoqinRecordMapper.updateKaoqinRecord(kaoqinRecord);
     }
 
     /**
      * 批量删除考勤记录
-     * 
+     *
      * @param recordIds 需要删除的考勤记录主键
      * @return 结果
      */
     @Override
-    public int deleteKaoqinRecordByRecordIds(Long[] recordIds)
-    {
+    public int deleteKaoqinRecordByRecordIds(Long[] recordIds) {
         return kaoqinRecordMapper.deleteKaoqinRecordByRecordIds(recordIds);
     }
 
     /**
      * 删除考勤记录信息
-     * 
+     *
      * @param recordId 考勤记录主键
      * @return 结果
      */
     @Override
-    public int deleteKaoqinRecordByRecordId(Long recordId)
-    {
+    public int deleteKaoqinRecordByRecordId(Long recordId) {
         return kaoqinRecordMapper.deleteKaoqinRecordByRecordId(recordId);
     }
 
@@ -137,10 +150,10 @@ public class KaoqinRecordServiceImpl implements IKaoqinRecordService
         String nickName = filename.split("_")[1];
         String date = time.split(" ")[0];
         //查询打卡信息
-        KaoqinRecord kaoqinRecord = kaoqinRecordMapper.selectKaoqinRecordByRecordByUser(Long.getLong(userId),date);
+        KaoqinRecord kaoqinRecord = kaoqinRecordMapper.selectKaoqinRecordByRecordByUser(Long.parseLong(userId), date);
         //查询考勤规则
         KaoqinConfig kaoqinConfig = kaoqinConfigMapper.selectKaoqinConfigBynew();
-        if(kaoqinRecord == null){
+        if (kaoqinRecord == null) {
             //根据id查询人员信息
             SysUser sysUser = sysUserMapper.selectUserById(Long.getLong(userId));
             String[] dates = date.split("-");
@@ -159,75 +172,113 @@ public class KaoqinRecordServiceImpl implements IKaoqinRecordService
             kaoqinRecords.setCreateTime(DateUtils.getNowDate());
             //此次打卡为第一次打卡
             //判断是否在上班卡之前打卡
-            if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmIn()),"HH:mm:ss")<=0){
+            if (DateUtils.compareTimes(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimeAmIn()), "HH:mm:ss") <= 0) {
                 //在上班之前打卡
                 kaoqinRecords.setKaTimeAmIn(DateUtils.parseDate(time));
                 kaoqinRecords.setKaTypeAmIn(ONE);
                 kaoqinRecords.setKaStatus(ONE);
 
-            }else{
+            } else {
                 //在上班之后打卡
                 //判断配置要打几次卡
-                if(TWO.equals(kaoqinConfig.getKaNum())){
-                    if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()),"HH:mm:ss")>=0){
+                if (TWO.equals(kaoqinConfig.getKaNum())) {
+                    kaoqinRecords.setKaNum(TWO);
+                    if (DateUtils.compareTimes(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimePmOut()), "HH:mm:ss") >= 0) {
                         //正常下班
+                        kaoqinRecords.setKaTypeAmIn(FIVE);
                         kaoqinRecords.setKaTimePmOut(DateUtils.parseDate(time));
                         kaoqinRecords.setKaTypePmOut(ONE);
-                    }else{
+                    } else {
                         //迟到
                         kaoqinRecords.setKaTimeAmIn(DateUtils.parseDate(time));
                         kaoqinRecords.setKaTypeAmIn(TWO);
                     }
 
-                }else if(FOUR.equals(kaoqinConfig.getKaNum())){
-                    if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmOut()),"HH:mm:ss")<0){
-                        //正常下班
+                } else if (FOUR.equals(kaoqinConfig.getKaNum())) {
+                    if (DateUtils.isInTimeRange(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimeAmIn()), DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimeAmOut()))) {
+                        //迟到
                         kaoqinRecords.setKaTimeAmIn(DateUtils.parseDate(time));
                         kaoqinRecords.setKaTypeAmIn(TWO);
-                    }else if(DateUtils.isInTimeRange(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmOut()), DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmIn()))){
-                        kaoqinRecords.setKaTimePmIn(DateUtils.parseDate(time));
-                        kaoqinRecords.setKaTypePmIn(ONE);
-                    }else if(DateUtils.isInTimeRange(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmIn()), DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()))){
-                        kaoqinRecords.setKaTimePmIn(DateUtils.parseDate(time));
-                        kaoqinRecords.setKaTypePmIn(TWO);
-                    }else if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()),"HH:mm:ss")>=0){
+
+                    } else if (DateUtils.isInTimeRange(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimeAmOut()), DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimePmIn()))) {
+                        //上午正常下班 打卡类别-上午下班 1正常 2:迟到 3:外勤 4:早退
+                        kaoqinRecords.setKaTypeAmIn(FIVE);
+                        kaoqinRecords.setKaTimeAmOut(DateUtils.parseDate(time));
+                        kaoqinRecords.setKaTypeAmOut(ONE);
+                        kaoqinRecord.setKaTimePmIn(DateUtils.parseDate(time));
+                        kaoqinRecord.setKaTypePmIn(ONE);
+
+                    } else if (DateUtils.isInTimeRange(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimePmIn()), DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimePmOut()))) {
+                        //下午迟到 打卡类别-上午下班 1正常 2:迟到 3:外勤 4:早退
+                        kaoqinRecords.setKaTypeAmIn(FIVE);
+                        kaoqinRecords.setKaTypeAmOut(FIVE);
+                        kaoqinRecord.setKaTimePmIn(DateUtils.parseDate(time));
+                        kaoqinRecord.setKaTypePmIn(TWO);
+
+                    } else if (DateUtils.compareTimes(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimePmOut()), "HH:mm:ss") >= 0) {
+                        //下午正常下班
+                        kaoqinRecords.setKaTypeAmIn(FIVE);
+                        kaoqinRecords.setKaTypeAmOut(FIVE);
+                        kaoqinRecord.setKaTypePmIn(FIVE);
                         kaoqinRecords.setKaTimePmOut(DateUtils.parseDate(time));
                         kaoqinRecords.setKaTypePmOut(ONE);
                     }
                 }
             }
             kaoqinRecordMapper.insertKaoqinRecord(kaoqinRecords);
-        }else{
-            if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmIn()),"HH:mm:ss")<=0){
+        } else {
+            if (DateUtils.compareTimes(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimeAmIn()), "HH:mm:ss") <= 0) {
                 //在上班之前打卡
                 kaoqinRecord.setKaTimeAmIn(DateUtils.parseDate(time));
                 kaoqinRecord.setKaTypeAmIn(ONE);
                 kaoqinRecord.setKaStatus(ONE);
 
-            }else{
-                if(TWO.equals(kaoqinConfig.getKaNum())){
-                    if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()),"HH:mm:ss")>=0){
+            } else {
+                if (TWO.equals(kaoqinConfig.getKaNum())) {
+                    if (DateUtils.compareTimes(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimePmOut()), "HH:mm:ss") >= 0) {
                         //正常下班
                         kaoqinRecord.setKaTimePmOut(DateUtils.parseDate(time));
                         kaoqinRecord.setKaTypePmOut(ONE);
-                    }else{
-                        //迟到
+                    } else {
+                        //早退
                         kaoqinRecord.setKaTimePmOut(DateUtils.parseDate(time));
                         kaoqinRecord.setKaTypePmOut(FOUR);
                     }
 
-                }else if(FOUR.equals(kaoqinConfig.getKaNum())){
-                    if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmOut()),"HH:mm:ss")<0){
-                        //正常下班
-                        kaoqinRecord.setKaTimeAmIn(DateUtils.parseDate(time));
-                        kaoqinRecord.setKaTypeAmIn(TWO);
-                    }else if(DateUtils.isInTimeRange(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmOut()), DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimeAmIn()))){
-                        kaoqinRecord.setKaTimePmIn(DateUtils.parseDate(time));
-                        kaoqinRecord.setKaTypePmIn(ONE);
-                    }else if(DateUtils.isInTimeRange(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmIn()), DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()))){
-                        kaoqinRecord.setKaTimePmIn(DateUtils.parseDate(time));
-                        kaoqinRecord.setKaTypePmIn(TWO);
-                    }else if(DateUtils.compareTimes(time.split(" ")[1],DateUtils.parseDateToStr("HH:mm:ss",kaoqinConfig.getKaTimePmOut()),"HH:mm:ss")>=0){
+                } else if (FOUR.equals(kaoqinConfig.getKaNum())) {
+                    if (DateUtils.isInTimeRange(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimeAmIn()), DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimeAmOut()))) {
+                        if (StringUtils.isNotBlank(kaoqinRecord.getKaTypeAmIn())) {
+                            //早退 打卡类别-上午下班 1正常 2:迟到 3:外勤 4:早退
+                            kaoqinRecord.setKaTimeAmOut(DateUtils.parseDate(time));
+                            kaoqinRecord.setKaTypeAmOut(FOUR);
+                        } else {
+                            //迟到
+                            kaoqinRecord.setKaTimeAmIn(DateUtils.parseDate(time));
+                            kaoqinRecord.setKaTypeAmIn(TWO);
+                        }
+
+                    } else if (DateUtils.isInTimeRange(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimeAmOut()), DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimePmIn()))) {
+                        if (StringUtils.isNotBlank(kaoqinRecord.getKaTypeAmOut())) {
+                            //下午正常上班 打卡类别-上午下班 1正常 2:迟到 3:外勤 4:早退
+                            kaoqinRecord.setKaTimePmIn(DateUtils.parseDate(time));
+                            kaoqinRecord.setKaTypePmIn(ONE);
+                        } else {
+                            //上午正常下班
+                            kaoqinRecord.setKaTimeAmOut(DateUtils.parseDate(time));
+                            kaoqinRecord.setKaTypeAmOut(ONE);
+                        }
+                    } else if (DateUtils.isInTimeRange(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimePmIn()), DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimePmOut()))) {
+                        if (StringUtils.isNotBlank(kaoqinRecord.getKaTypePmIn())) {
+                            //下午早退
+                            kaoqinRecord.setKaTimePmOut(DateUtils.parseDate(time));
+                            kaoqinRecord.setKaTypePmOut(FOUR);
+                        } else {
+                            //下午迟到 打卡类别-上午下班 1正常 2:迟到 3:外勤 4:早退
+                            kaoqinRecord.setKaTimePmIn(DateUtils.parseDate(time));
+                            kaoqinRecord.setKaTypePmIn(TWO);
+                        }
+                    } else if (DateUtils.compareTimes(time.split(" ")[1], DateUtils.parseDateToStr("HH:mm:ss", kaoqinConfig.getKaTimePmOut()), "HH:mm:ss") >= 0) {
+                        //下午正常下班
                         kaoqinRecord.setKaTimePmOut(DateUtils.parseDate(time));
                         kaoqinRecord.setKaTypePmOut(ONE);
                     }

+ 211 - 32
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/RecordLeaveServiceImpl.java

@@ -1,33 +1,39 @@
 package com.ruoyi.system.service.impl;
 
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+import java.time.format.DateTimeFormatter;
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.List;
+import java.util.Map;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
+import com.ruoyi.common.core.domain.entity.SysDept;
 import com.ruoyi.common.core.domain.entity.SysUser;
 import com.ruoyi.common.exception.ServiceException;
 import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.SecurityUtils;
-import com.ruoyi.system.domain.CardReplacementRecord;
-import com.ruoyi.system.domain.ProcessConfiguration;
-import com.ruoyi.system.domain.RecordLeaveFj;
-import com.ruoyi.system.mapper.ProcessConfigurationMapper;
-import com.ruoyi.system.mapper.RecordLeaveFjMapper;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.domain.*;
+import com.ruoyi.system.mapper.*;
+import com.ruoyi.system.service.IKaoqinRecordService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
-import com.ruoyi.system.mapper.RecordLeaveMapper;
-import com.ruoyi.system.domain.RecordLeave;
 import com.ruoyi.system.service.IRecordLeaveService;
 
+import static com.ruoyi.common.constant.Constants.*;
+
 /**
  * 请假记录信息Service业务层处理
- * 
+ *
  * @author ruoyi
  * @date 2023-02-13
  */
 @Service
-public class RecordLeaveServiceImpl implements IRecordLeaveService 
-{
+public class RecordLeaveServiceImpl implements IRecordLeaveService {
     @Autowired
     private RecordLeaveMapper recordLeaveMapper;
 
@@ -36,42 +42,55 @@ public class RecordLeaveServiceImpl implements IRecordLeaveService
 
     @Autowired
     private RecordLeaveFjMapper recordLeaveFjMapper;
+    @Autowired
+    private SysUserMapper sysUserMapper;
+
+    @Autowired
+    private KaoqinConfigMapper kaoqinConfigMapper;
+
+    @Autowired
+    private IKaoqinRecordService kaoqinRecordService;
+
+    @Autowired
+    private KaoqinRecordMapper kaoqinRecordMapper;
+
+    @Autowired
+    private SysDeptMapper deptMapper;
 
     /**
      * 查询请假记录信息
-     * 
+     *
      * @param id 请假记录信息主键
      * @return 请假记录信息
      */
     @Override
-    public RecordLeave selectRecordLeaveById(Long id)
-    {
+    public RecordLeave selectRecordLeaveById(Long id) {
         return recordLeaveMapper.selectRecordLeaveById(id);
     }
 
     /**
      * 查询请假记录信息列表
-     * 
+     *
      * @param recordLeave 请假记录信息
      * @return 请假记录信息
      */
     @Override
-    public List<RecordLeave> selectRecordLeaveList(RecordLeave recordLeave)
-    {
+    public List<RecordLeave> selectRecordLeaveList(RecordLeave recordLeave) {
         SysUser user = SecurityUtils.getLoginUser().getUser();
-        recordLeave.setAbsenteeId(String.valueOf(user.getUserId()));
+        if (!"admin".equals(user.getUserName())) {
+            recordLeave.setAbsenteeId(String.valueOf(user.getUserId()));
+        }
         return recordLeaveMapper.selectRecordLeaveList(recordLeave);
     }
 
     /**
      * 新增请假记录信息
-     * 
+     *
      * @param recordLeave 请假记录信息
      * @return 结果
      */
     @Override
-    public int insertRecordLeave(RecordLeave recordLeave)
-    {
+    public int insertRecordLeave(RecordLeave recordLeave) {
         //获取当前人员信息
         SysUser user = SecurityUtils.getLoginUser().getUser();
         recordLeave.setAbsenteeId(String.valueOf(user.getUserId()));
@@ -85,15 +104,14 @@ public class RecordLeaveServiceImpl implements IRecordLeaveService
 
     /**
      * 修改请假记录信息
-     * 
+     *
      * @param recordLeave 请假记录信息
      * @return 结果
      */
     @Override
-    public int updateRecordLeave(RecordLeave recordLeave)
-    {
+    public int updateRecordLeave(RecordLeave recordLeave) {
         RecordLeave recordLeave1 = recordLeaveMapper.selectRecordLeaveById(recordLeave.getId());
-        if(!"0".equals(recordLeave1.getIsPass())){
+        if (!"0".equals(recordLeave1.getIsPass())) {
             throw new ServiceException("当前补卡已处理,无法修改");
         }
         recordLeave.setSubmitTime(DateUtils.getNowDate());
@@ -102,25 +120,23 @@ public class RecordLeaveServiceImpl implements IRecordLeaveService
 
     /**
      * 批量删除请假记录信息
-     * 
+     *
      * @param ids 需要删除的请假记录信息主键
      * @return 结果
      */
     @Override
-    public int deleteRecordLeaveByIds(Long[] ids)
-    {
+    public int deleteRecordLeaveByIds(Long[] ids) {
         return recordLeaveMapper.deleteRecordLeaveByIds(ids);
     }
 
     /**
      * 删除请假记录信息信息
-     * 
+     *
      * @param id 请假记录信息主键
      * @return 结果
      */
     @Override
-    public int deleteRecordLeaveById(Long id)
-    {
+    public int deleteRecordLeaveById(Long id) {
         return recordLeaveMapper.deleteRecordLeaveById(id);
     }
 
@@ -128,23 +144,186 @@ public class RecordLeaveServiceImpl implements IRecordLeaveService
     public int audit(RecordLeave recordLeave) {
         //获取当前人员信息
         SysUser user = SecurityUtils.getLoginUser().getUser();
+
+        if (TWO.equals(recordLeave.getIsPass())) {
+            RecordLeave recordLeave1 = recordLeaveMapper.selectRecordLeaveById(recordLeave.getId());
+            //查询人员信息
+            SysUser sysUser = sysUserMapper.selectUserById(Long.valueOf(recordLeave1.getAbsenteeId()));
+            //考勤规则
+            KaoqinConfig kaoqinConfig = kaoqinConfigMapper.selectKaoqinConfigBynew();
+            //查询打卡信息
+            KaoqinRecord kaoqinRecord = new KaoqinRecord();
+            kaoqinRecord.setUserId(sysUser.getUserId());
+            kaoqinRecord.setStartTime(DateUtils.dateTime(recordLeave1.getStartTime()));
+            kaoqinRecord.setEndTime(DateUtils.dateTime(recordLeave1.getEndTime()));
+            List<KaoqinRecord> kaoqinRecords = kaoqinRecordMapper.selectKaoqinRecordList(kaoqinRecord);
+            Map<String, List<KaoqinRecord>> kaoqinRecordCollect = kaoqinRecords.stream().collect(Collectors.groupingBy(KaoqinRecord::getKaTime));
+
+
+            // 3. 解析请假时间范围
+            LocalDateTime start = DateUtils.convertToLocalDateTime(recordLeave1.getStartTime());
+            LocalDateTime end = DateUtils.convertToLocalDateTime(recordLeave1.getEndTime());
+            // 获取日期列表
+            //List<String> dates = DateUtils.getDateStringsBetween(recordLeave1.getStartTime(), recordLeave1.getEndTime());
+            List<LocalDate> leaveDates = DateUtils.getDateRange(start.toLocalDate(), end.toLocalDate());
+            // 5. 处理每个请假日期
+            for (LocalDate date : leaveDates) {
+                KaoqinRecord record = null;
+                if (kaoqinRecordCollect.containsKey(DateUtils.convertToString(date, "yyyy-MM-dd"))) {
+                    record = new KaoqinRecord();
+                    record = kaoqinRecordCollect.get(DateUtils.convertToString(date, "yyyy-MM-dd")).get(0);
+                }
+                updateDailyAttendance(recordLeave1, date, start, end, kaoqinConfig, record, sysUser);
+            }
+
+        }
+
         recordLeave.setExaminersId(user.getUserId());
         recordLeave.setExaminersName(user.getNickName());
         return recordLeaveMapper.updateRecordLeave(recordLeave);
     }
 
+    // 更新单日考勤记录
+    private void updateDailyAttendance(RecordLeave leave, LocalDate date,
+                                       LocalDateTime leaveStart, LocalDateTime leaveEnd,
+                                       KaoqinConfig config, KaoqinRecord record, SysUser sysUser) {
+
+
+        // 3. 不存在记录则创建新记录
+        if (record == null) {
+            record = createNewRecord(leave, date, config, sysUser);
+        }
+
+        // 4. 更新打卡时段状态
+        updateTimeSlotStatus(record, date, leaveStart, leaveEnd, config);
+
+        // 5. 检查整体考勤状态
+        updateOverallStatus(record);
+
+        // 6. 保存更新
+        if (record.getRecordId() == null || record.getRecordId() == 0) {
+            kaoqinRecordMapper.insertKaoqinRecord(record);
+        } else {
+            kaoqinRecordMapper.updateKaoqinRecord(record);
+        }
+
+    }
+
+    // 创建新的考勤记录
+    private KaoqinRecord createNewRecord(RecordLeave leave, LocalDate date, KaoqinConfig config, SysUser sysUser) {
+        KaoqinRecord record = new KaoqinRecord();
+        record.setUserId(Long.parseLong(leave.getAbsenteeId()));
+        record.setUserName(leave.getAbsenteeName());
+        record.setDeptId(leave.getDeptId());
+        record.setDeptName(leave.getDeptName());
+        record.setAncestors(sysUser.getDept().getAncestors());
+        record.setKaNum(config.getKaNum()); // 使用配置的打卡次数
+
+        // 设置日期相关字段
+        record.setKaYear(String.valueOf(date.getYear()));
+        record.setKaMonth(String.format("%02d", date.getMonthValue()));
+        record.setKaDay(String.format("%02d", date.getDayOfMonth()));
+        record.setKaWeek(DateUtils.getWeekday(date));
+        record.setKaTime(date.format(DateTimeFormatter.ISO_LOCAL_DATE));
+
+        // 设置默认状态
+        record.setKaTypeAmIn("5");
+        record.setKaTypeAmOut("5");
+        record.setKaTypePmIn("5");
+        record.setKaTypePmOut("5");
+        record.setKaStatus("1");
+
+        // 设置考勤地址
+        record.setKaAddressAmIn(config.getKaAddress());
+        record.setKaAddressAmOut(config.getKaAddress());
+        record.setKaAddressPmIn(config.getKaAddress());
+        record.setKaAddressPmOut(config.getKaAddress());
+
+        return record;
+    }
+
+    // 更新打卡时段状态
+    private void updateTimeSlotStatus(KaoqinRecord record, LocalDate date,
+                                      LocalDateTime leaveStart, LocalDateTime leaveEnd,
+                                      KaoqinConfig config) {
+        // 从配置获取打卡时间
+        LocalDateTime amInEnd = DateUtils.combineDateTime(date, config.getKaTimeAmIn()); // 上午上班截止时间
+        LocalDateTime amOutStart = DateUtils.combineDateTime(date, config.getKaTimeAmOut());// 上午下班开始时间
+        LocalDateTime pmInEnd = DateUtils.combineDateTime(date, config.getKaTimePmIn());// 下午上班截止时间
+        LocalDateTime pmOutStart = DateUtils.combineDateTime(date, config.getKaTimePmOut());// 下午下班开始时间
+
+        // 检查请假是否覆盖各时段
+        if (isLeaveCovered(leaveStart, leaveEnd, amInEnd)) {
+            record.setKaTypeAmIn(SEVEN); // 上午上班请假
+        }
+        if (FOUR.equals(config.getKaNum())) {
+            if (isLeaveCovered(leaveStart, leaveEnd, amOutStart)) {
+                record.setKaTypeAmOut(SEVEN); // 上午下班请假
+            }
+
+            if (isLeaveCovered(leaveStart, leaveEnd, pmInEnd)) {
+                record.setKaTypePmIn(SEVEN); // 下午上班请假
+            }
+        }
+/*
+        if (isLeaveCovered(leaveStart, leaveEnd, pmInEnd, pmOutStart)) {
+            record.setKaTypePmOut("7"); // 下午下班请假
+        }*/
+        if (isLeaveCovered(leaveStart, leaveEnd, pmOutStart)) {
+            record.setKaTypePmOut(SEVEN); // 下午下班请假
+        }
+    }
+
+    // 检查请假是否覆盖时间段
+    private boolean isLeaveCovered(LocalDateTime leaveStart, LocalDateTime leaveEnd,
+                                   LocalDateTime active) {
+        return (leaveStart.isBefore(active) &&
+                leaveEnd.isAfter(active));
+    }
+
+    // 更新整体考勤状态
+    private void updateOverallStatus(KaoqinRecord record) {
+        // 检查是否有异常状态(非正常和非请假)
+        boolean hasAbnormal = Stream.of(
+                        record.getKaTypeAmIn(),
+                        record.getKaTypeAmOut(),
+                        record.getKaTypePmIn(),
+                        record.getKaTypePmOut()
+                )
+                .filter(status -> !"1".equals(status) && !"7".equals(status))
+                .findAny()
+                .isPresent();
+
+        record.setKaStatus(hasAbnormal ? "2" : "1");
+    }
+
+
     @Override
     public List<RecordLeave> presentList(RecordLeave recordLeave) {
         //获取当前人员信息
         SysUser user = SecurityUtils.getLoginUser().getUser();
-        if (!"admin".equals(user.getUserName())){
+        if (!"admin".equals(user.getUserName())) {
             //获取当前人员补卡配置所在的部门id
             ProcessConfiguration processConfiguration = new ProcessConfiguration();
             processConfiguration.setUserId(user.getUserId());
             processConfiguration.setType("2");
             List<ProcessConfiguration> list = processConfigurationMapper.selectProcessConfigurationList(processConfiguration);
+            if (list == null || list.isEmpty()) {
+                List<RecordLeave> recordLeaveList = new ArrayList<>();
+                return recordLeaveList;
+            }
+            List<Long> deptIdList = new ArrayList<>();
             List<Long> deptIds = list.stream().map(ProcessConfiguration::getDeptId).collect(Collectors.toList());
-            recordLeave.setDeptIds(deptIds);
+            deptIdList.addAll(deptIds);
+            for (Long deptId : deptIds) {
+                //查询所有子部门
+                List<SysDept> children = deptMapper.selectChildrenDeptById(deptId);
+                if(children!=null && !children.isEmpty()){
+                    List<Long> childrenIds = children.stream().map(SysDept::getDeptId).collect(Collectors.toList());
+                    deptIdList.addAll(childrenIds);
+                }
+            }
+            recordLeave.setDeptIds(deptIdList);
         }
         return recordLeaveMapper.selectRecordLeaveList(recordLeave);
     }

+ 6 - 0
ruoyi-system/src/main/resources/mapper/system/BusinessTripMapper.xml

@@ -53,6 +53,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="reason != null  and reason != ''"> and reason = #{reason}</if>
             <if test="photo != null  and photo != ''"> and photo = #{photo}</if>
             <if test="deptId != null "> and dept_id = #{deptId}</if>
+            <if test="deptIds!=null and deptIds.size() >0">
+                and dept_id in
+                <foreach item="deptId" collection="deptIds" open="(" separator="," close=")">
+                    #{deptId}
+                </foreach>
+            </if>
             <if test="deptName != null  and deptName != ''"> and dept_name like concat('%', #{deptName}, '%')</if>
             <if test="initiatorId != null "> and initiator_id = #{initiatorId}</if>
             <if test="initiatorName != null  and initiatorName != ''"> and initiator_name like concat('%', #{initiatorName}, '%')</if>

+ 3 - 1
ruoyi-system/src/main/resources/mapper/system/CardReplacementRecordMapper.xml

@@ -53,7 +53,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </select>
     <select id="selectCardReplacementRecordListWeek" parameterType="CardReplacementRecord" resultMap="CardReplacementRecordResult">
         <include refid="selectCardReplacementRecordVo"/>
-        WHERE WEEK(application_date, 1) = WEEK(CURDATE(), 1);
+        WHERE  1=1
+        <if test="deptId != null  and deptId != 0"> and dept_id = #{deptId}</if>
+        and WEEK(application_date, 1) = WEEK(CURDATE(), 1);
     </select>
 
     <insert id="insertCardReplacementRecord" parameterType="CardReplacementRecord" useGeneratedKeys="true" keyProperty="id">

+ 1 - 1
ruoyi-system/src/main/resources/mapper/system/KaoqinRecordMapper.xml

@@ -59,7 +59,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="userName != null  and userName != ''"> and user_name like concat( #{userName}, '%')</if>
             <if test="phone != null  and phone != ''"> and phone = #{phone}</if>
             <if test="deptName != null  and deptName != ''"> and dept_name like concat( #{deptName}, '%')</if>
-            <if test="deptId != null  and deptId != ''"> and find_in_set(#{deptId}, ancestors)</if>
+            <if test="deptId != null  and deptId != ''"> and (find_in_set(#{deptId}, ancestors) or dept_id = #{deptId})</if>
             <if test="kaNum != null  and kaNum != ''"> and ka_num = #{kaNum}</if>
             <if test="kaYear != null  and kaYear != ''"> and ka_year = #{kaYear}</if>
             <if test="kaMonth != null  and kaMonth != ''"> and ka_month = #{kaMonth}</if>

+ 2 - 1
ruoyi-system/src/main/resources/mapper/system/ProcessConfigurationMapper.xml

@@ -25,7 +25,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectProcessConfigurationList" parameterType="ProcessConfiguration" resultMap="ProcessConfigurationResult">
         <include refid="selectProcessConfigurationVo"/>
-        <where>  
+        <where>
+            <if test="userId != null "> and user_id = #{userId}</if>
             <if test="userName != null  and userName != ''"> and user_name like concat('%', #{userName}, '%')</if>
             <if test="deptName != null  and deptName != ''"> and dept_name like concat('%', #{deptName}, '%')</if>
             <if test="type != null  and type != ''"> and type = #{type}</if>

+ 2 - 0
ruoyi-system/src/main/resources/mapper/system/RecordLeaveMapper.xml

@@ -35,8 +35,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="absenteeName != null  and absenteeName != ''"> and absentee_name like concat('%', #{absenteeName}, '%')</if>
             <if test="examinersName != null  and examinersName != ''"> and examiners_name like concat('%', #{examinersName}, '%')</if>
             <if test="category != null  and category != ''"> and category = #{category}</if>
+            <if test="absenteeId != null  and absenteeId != ''"> and absentee_id = #{absenteeId}</if>
             <if test="isPass != null  and isPass != ''"> and is_pass = #{isPass}</if>
             <if test="submitTime != null "> and date_format(submit_time,'%y%m%d') = date_format(#{submitTime},'%y%m%d')</if>
+            <if test="deptId != null "> and dept_id = #{deptId}</if>
             <if test="deptIds!=null and deptIds.size() >0">
                 and dept_id in
                 <foreach item="deptId" collection="deptIds" open="(" separator="," close=")">